|
|
1.1 root 1: /* SQLWindow.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: * Written by Jack Greenfield
7: *
8: */
9:
10: #import "ScrollViewExtras.h"
11: #import "SQLWindow.h"
12: #import "MultiBinder.h"
13:
14: #define FAILURE NXLocalizedString("Failure:", NULL, \
15: "Message given to user when an operation has failed.")
16:
17: #define CANNOT_CONNECT NXLocalizedString("Cannot connect to database", NULL, \
18: "Message given to user to explain what fails. ")
19:
20: #define OK NXLocalizedString("OK", NULL, "Okay to continue ")
21:
22: @implementation SQLWindow
23:
24: - free
25: {
26: [database free];
27: return [super free];
28: }
29:
30: - initWithFile:(const char *)filename
31: {
32: char path[MAXPATHLEN];
33:
34: if ((self = [super init]) != nil)
35: {
36: database = [[DBDatabase alloc] initFromFile:filename];
37: if (![database connect])
38: {
39: NXRunAlertPanel(FAILURE, CANNOT_CONNECT, OK, NULL, NULL);
40: return [self free];
41: }
42:
43: [[NXBundle mainBundle] getPath:path forResource:"SQLWindow" ofType:"nib"];
44: [NXApp loadNibFile:path owner:self withNames:NO];
45: [[resultsView window] setDelegate:self];
46: [[resultsView window] setTitleAsFilename:filename];
47: [[queryView docView] selectAll:self];
48: [[resultsView window] makeKeyAndOrderFront:self];
49: }
50:
51: return self;
52: }
53:
54: - database { return database; }
55:
56: - evaluate:sender
57: {
58: int charCount;
59: char *buffer;
60: MultiBinder *binder;
61: id <DBContainers> rowsList;
62:
63: if ((charCount = [[queryView docView] textLength]) > 0)
64: {
65: binder = [[MultiBinder alloc] initFromPropertyLists:nil];
66: [binder setDatabase:database];
67: [binder setDelegate:self];
68: rowsList = [[List alloc] init];
69: [binder setContainer: rowsList];
70:
71: buffer = (char *) alloca(1 + charCount);
72: [[queryView docView] getSubstring:buffer start:0 length:charCount];
73: buffer[charCount] = 0;
74: while (charCount > 0 && buffer[--charCount] == '\n')
75: buffer[charCount] = 0;
76:
77: [resultsView sprintf:"%s\n", buffer];
78: if (![binder evaluateString:buffer])
79: [resultsView sprintf:"EVALUATION FAILED\n\n"];
80: else
81: if (![binder fetch])
82: [resultsView sprintf:"FETCH FAILED\n\n"];
83: else
84: /* For the last result set, binderWillChangeResultSet
85: * needs to be called explicitly.
86: */
87: [self binderWillChangeResultSet:binder];
88:
89: [resultsView sprintf:"\n"];
90: [binder free];
91: [(List *)rowsList free];
92: }
93:
94: [[queryView docView] selectText:self];
95: return self;
96: }
97:
98: - clear:sender
99: {
100: [resultsView clear:sender];
101: [[queryView docView] selectText:self];
102: return self;
103: }
104:
105: - print:sender
106: {
107: [resultsView print:sender];
108: [[queryView docView] selectText:self];
109: return self;
110: }
111:
112: /* This delegate method will be called every time a new result set is being
113: * fetched. All objects returned by the binder fetch can be retrieved from the
114: * binder container (named rowsList here). Note that the container will get
115: * flushed everytime a new result set is retrieved. This delegate method is the
116: * place where you can save the result set elsewhere if needed.
117: */
118: - binderWillChangeResultSet:(MultiBinder *)binder
119: {
120: int rowsIndex;
121: int rowsCount;
122: int propIndex;
123: int propCount;
124: List *rowsList;
125: List *propList;
126:
127: propList = [[List alloc] init];
128: [binder getCurrentProperties:propList];
129: rowsList = binder->container; // public instance variable!!!
130: rowsCount = [rowsList count];
131: [resultsView sprintf:"\nresult set %d\n", [binder currentResultSet]];
132: [resultsView sprintf:"%u records selected\n", rowsCount];
133: [binder setFirst];
134: for (rowsIndex = 0; rowsIndex < rowsCount; ++rowsIndex)
135: {
136: propCount = [propList count];
137: for (propIndex = 0; propIndex < propCount; ++propIndex)
138: {
139: id p = [propList objectAt:propIndex];
140: [resultsView sprintf:"%s=(%s) ",
141: [p name], [[binder valueForProperty:p] stringValue]];
142: }
143:
144: [resultsView sprintf:"\n"];
145: [binder setNext];
146: }
147:
148: [propList free];
149: return self;
150: }
151:
152: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.