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