ViewManager subclass: #XSQLBrowser instanceVariableNames: ' connection events fixedFont leaks logFile logPipe map selectFor sems spawningMap sqlFilePathString sqlHandle sqlTextPane statements statementPane transcriptPane ' classVariableNames: ' Linked DBMS ' poolDictionaries: ' CharacterConstants XSQLConstants ' ! !XSQLBrowser class methods ! buildOtherConstants XSQLConstants at: 'XsqlSQLNOT' put: 0. XSQLConstants at: 'XsqlSELECT' put: 1. XSQLConstants at: 'XsqlTRANSACTION' put: 2. XSQLConstants at: 'XsqlINSERT' put: 3. XSQLConstants at: 'XsqlUPDATE' put: 4. XSQLConstants at: 'XsqlXUPDATE' put: 5. XSQLConstants at: 'XsqlSQLHANDLERETURNED' put: 6. XSQLConstants at: 'XsqlDELETE' put: 7. XSQLConstants at: 'XsqlCREATE' put: 8. XSQLConstants at: 'XsqlXCREATE' put: 9. XSQLConstants at: 'XsqlDROP' put: 10. XSQLConstants at: 'XsqlCONNECT' put: 11. XSQLConstants at: 'XsqlOTHER' put: 12. XSQLConstants at: 'XrecMAXCLASS' put: 5.! buildXSQLTypes | typeNames | "Set the IBM numerics for types" XSQLConstants at: 'XSQLtypeCHAR' put: 448. "Build dictionary of names associated with numerics." XSQLConstants at: 'XSQLTYPES' put: (typeNames := Dictionary new). typeNames at: XSQLtypeCHAR put: 'CHAR'.! linkSQL "Make sure the image is ready for XSQL operations." "Smalltalk at: #XSQLConstants put: Dictionary new. THIS HAS TO BE DONE IN INSTALL PROC" | aStructDef | (Linked = nil) ifTrue: [Smalltalk at: #XSQL put: (XSQLDBMS open: 'XSQLDBMS'). XSQLDBMS xsqlStructsAthruI. XSQLDBMS xsqlStructsJthruZ. Linked := true.].! purgeLink Linked := nil. DBMS := nil.! rcsLog "$Id: XSQLBRWS.CLS 1.2 1997/07/28 08:16:54 JUAN2 Exp $" "$Log: XSQLBRWS.CLS $ "Revision 1.2 1997/07/28 08:16:54 JUAN2 "Platform cognates 1. " "Revision 1.1 1997/07/27 22:22:06 JUAN2 "Initial revision ""! ! !XSQLBrowser methods ! acceptAndReparse: anXSQLTextPane at: aStatementIndex disposition: aString "Submit the contents of aTextTPane to xsqlSplice." | batchState fileNamePtr newScript rc statementsProcessedOK insertCode thisStatement xsqlFragment | batchState := DBMS at: 4. sqlFilePathString = nil ifTrue: [aString = 'DELETE' ifTrue: [sqlTextPane contents: '--*NEW XSQL Fragment' at: 0. ^nil ]. newScript := Prompter prompt: 'A XSQL script path is required!!' default: 'script.xsql'. newScript = nil | newScript isEmpty ifTrue: [^nil]. sqlFilePathString := newScript. fileNamePtr := ExternalAddress copyToNonSmalltalkMemory: (sqlFilePathString asAsciiZ). batchState bytesAtOffset: 50 put: (fileNamePtr asParameter). leaks add: fileNamePtr. ]. aString = 'DELETE' ifTrue: [aStatementIndex > 0 ifTrue: [ thisStatement := (statements at: aStatementIndex) at: 1. rc := XSQL xsqlFreeXSQL: (thisStatement contents asParameter). statements removeIndex: aStatementIndex. statementPane contents: ((statementPane contents) removeIndex: aStatementIndex). ]. ^nil ]. xsqlFragment := ExternalAddress copyToNonSmalltalkMemory: ( anXSQLTextPane contents asAsciiZ ). aString = 'INSERT' ifTrue: [insertCode := 1.]. aString = 'REPLACE' ifTrue: [insertCode := 2.]. statementsProcessedOK := XSQL xsqlSplice: (xsqlFragment asParameter) at: aStatementIndex do: insertCode. statementsProcessedOK > 0 ifTrue:[ self newBoxListFromParse: insertCode nAct: (statementsProcessedOK @ 1) at: aStatementIndex ]. xsqlFragment free.! acceptLogLine "Append the log line just passed in logPipe to the log pane." | thisLine logPacket logPacketSize | logPacket := logPipe at: 3. logPacketSize := logPipe at: 5. thisLine := String new: (logPacketSize - 2). thisLine replaceFrom: 1 to: (logPacketSize - 3) with: (logPacket messageBody) startingAt: 1. transcriptPane nextPutAll: thisLine; cr.! acceptLogLine: aString "Format aString in xsqlLogPrint form and append to the log pane." transcriptPane nextPutAll: '--XSQL-- '; nextPutAll: aString; cr.! asynchMonitor | thisEvent eventStuff | [(sems at: 2) hasSignals] whileFalse: [(sems at: 3) wait. self acceptLogLine: 'Asynch notification received.'. eventStuff := events at: 1. thisEvent := events removeFirst. "self halt." thisEvent = 'EOT' ifTrue: [self setRunMenu.]. ]! backgroundMonitor "Create client end and monitor XSQLDBMS log pipe for event messages and dispatch as appropos. Release the processor after every event. This ST/V process performs log pane and result table to text pane updates." | handleStruct actionTaken attributes openFlags openMode pipeHandle pState bytesAvailable bytesRead pipePacket rc whichDosCall clock dryCycles notified hasSlept | notified := false. pipeHandle := ExternalHandle new. actionTaken := ExternalHandle new. openFlags := 1. openMode := 64. bytesAvailable := SelfDefinedStructure named: 'AVAILDATA'. pState := ExternalHandle new. bytesRead := ExternalHandle new. pipePacket := SelfDefinedStructure named: 'PIPE_MSG'. clock := 0. hasSlept := false. (logPipe = nil) ifTrue: [logPipe := OrderedCollection new: 6. logPipe add: '\PIPE\SQLBRWSR.LOG'; "at: 1 - logName" add: pipeHandle; "at: 2 - logHandle" add: pipePacket; "at: 3 - logPacket" add: false; "at: 4 - logEndSem" add: 0. "at: 5 - logPacketSize" rc := KernelDLL open: ((logPipe at:1) asParameter) handle: (pipeHandle asParameter) action: (actionTaken asParameter) initSize: nil attribute: nil flags: openFlags mode: openMode reserved: nil. rc = 0 ifFalse: [self acceptLogLine: '...\PIPE\SQLBRWSR.LOG OS/2 Error: ',(rc printString). ^nil]. ]. dryCycles := 0. [logPipe = nil] whileFalse: [whichDosCall := 'PEEKNMPIPE: '. rc := KernelDLL peekNmPipe: pipeHandle pBuffer: (pipePacket asParameter) bufLen: 4 bytesRead: (bytesRead asParameter) pAvailData: (bytesAvailable asParameter) pipeState: (pState asParameter). (rc = 0) & ((bytesAvailable bufferedNow) >= 4) ifTrue: [(bytesAvailable bufferedNow) >= (bytesAvailable thisMessageSize) ifTrue: [dryCycles := 0. whichDosCall := 'READ: '. rc := KernelDLL read32: pipeHandle buffer: (pipePacket asParameter) bufSize: (bytesAvailable thisMessageSize) bytesRead: (bytesRead asParameter). (rc = 0) & ((bytesRead asInteger) = (bytesAvailable thisMessageSize)) ifTrue: [ (pipePacket eventCode) = 0 ifTrue: [logPipe at: 5 put: (bytesRead asInteger). self acceptLogLine ] ifFalse: [ (pipePacket eventCode) = 1 ifTrue: [events add: ((OrderedCollection new) add: 'EOT'). (sems at: 3) signal. ] ifFalse: [self acceptLogLine: 'Unknown event: ', ((pipePacket eventCode) printString). ]. ]. ]. ]. ] ifFalse: [dryCycles := dryCycles + 1.]. rc ~= 0 ifTrue: [self acceptLogLine: whichDosCall,(rc printString). self disconnect. ^nil ]. (logPipe at: 4) ifTrue: [rc := KernelDLL close32: pipeHandle . (sems at: 2) signal. ^nil ]. notified ifFalse: [notified := true. CursorManager normal change.]. dryCycles > 10 ifTrue: [KernelDLL sleep: 66. dryCycles := 9. hasSlept ifFalse: [hasSlept := true. self acceptLogLine: 'Browser initialization completed OK.'. ]. ]. Processor yield. ]. " self acceptLogLine: (whichDosCall,(rc printString),',',(bytesRead printString), ',',((bytesAvailable thisMessageSize) printString),',', ((bytesAvailable bufferedNow) printString))."! boxListFromParse: ignored "Answer a new content for the receiver, statementPane" | batchState nthStatement thisStatement thisXStatement newContents thisStatementLabel nextStatement newStatementsBlock | DBMS = nil ifTrue: [^nil]. batchState := DBMS at: 4. nthStatement := (batchState nStatements). statements := OrderedCollection new: nthStatement. nextStatement := (SelfDefinedStructure named: 'EXTENDED_SQL' atAddress: (ExternalAddress usingBytes: (batchState statements)) ). statementPane contents = nil ifTrue: [sqlTextPane toggleWrap]. newContents := OrderedCollection new: nthStatement. [nthStatement > 0] whileTrue: [ thisStatement := nextStatement. statements add: (Array with: thisStatement with: nil with: nil with: false). " at: 1 - EXTENDED_SQL for this statement(ST/V SDS)" " at: 2 - Active handle obtained from XSQLDBMS for this statement" " at: 3 - View open on this statement." " at: 4 - Marking Boolean" (thisStatement augment) asInteger = 0 ifFalse: [thisXStatement := (SelfDefinedStructure named: 'BATCH_SQL' atAddress: (ExternalAddress usingBytes: (thisStatement augment))). (thisXStatement prequel) asInteger = 0 ifFalse: [thisStatementLabel := (String fromAddress: (ExternalAddress usingBytes: (thisXStatement prequel))). ] ifTrue: [thisStatementLabel := (String fromAddress: (ExternalAddress usingBytes: (thisStatement text))). ]. ] ifTrue: [thisStatementLabel := (String fromAddress: (ExternalAddress usingBytes: (thisStatement text))). ]. newContents add: thisStatementLabel. nthStatement := nthStatement - 1. (nthStatement > 0 & ((thisStatement next) asInteger ~= 0)) ifTrue: [nextStatement := SelfDefinedStructure named: 'EXTENDED_SQL' atAddress: (ExternalAddress usingBytes: (thisStatement next)). ]. ]. statementPane contents: newContents. ^newContents! changeDetails "open a XSQLBrowserControl in information mode." XSQLBrowserControl new openOn: self forUpdate: true.! close: aPane "Private - Close the receiver." | rc disconnectCode batchState source target | DBMS = nil ifTrue: [^nil]. batchState := DBMS at: 4. connection = nil ifFalse: [source := connection at: 1. target := connection at: 2. disconnectCode := 0. source = nil ifFalse: [disconnectCode := 1]. target = nil ifFalse: [disconnectCode = 1 ifTrue: [disconnectCode := 3] ifFalse: [disconnectCode := 2] ]. disconnectCode > 0 ifTrue: [ self disconnectFrom: disconnectCode ]. ]. logPipe = nil ifFalse: [logPipe at: 4 put: true. (sems at: 2) wait. ]. XSQL xsqlEndXSQL. "XSQL close." XSQL := nil. DBMS := nil. Linked := nil. "leaks do: [:each | each free]." Smalltalk isRunTime ifTrue: [ (MessageBox confirm: 'Are you sure you want to exit?') ifTrue: [self close. ^Smalltalk exit] ifFalse: [^self]] ifFalse: [^self close].! closeResultAt: aStatementIndex (statements at: aStatementIndex) at: 3 put: nil.! connect "An XSQLConnectionSelection sends us connectTo:inMode:role: or resumes the user interface." XSQLConnectionSelection new openFor: self answerMode: 1 withSites: (DBMS at: 1).! connectMenu ^((Menu labels: '~Connect...\~Disconnect...' withCrs lines: #( 1 ) selectors: #(connect disconnect )) title: '~Connect'; owner: self; yourself)! connectName "Answer a ST/V string containing the name of the current data source or target." | guiState result currentSource | self setDefaultConnectName. guiState := DBMS at: 5. currentSource := (guiState source). result := String fromAddress: (ExternalAddress usingBytes: currentSource) . ^result! connectTo: aConnectName inMode: aConnectMode role: roleString | getSlotValue rc objectName subjectName connectionCopy connectNamePtr batchState guiState connectStruct connectHandle thisConnect appNamePtr errNo isSource | roleString = 'SOURCE' ifTrue: [isSource := true.] ifFalse: [isSource := false.]. connectNamePtr := ExternalAddress copyToNonSmalltalkMemory: aConnectName. leaks add: connectNamePtr. sqlHandle := SelfDefinedStructure named: 'SQLHANDLE'. batchState := DBMS at: 4. guiState := DBMS at: 5. getSlotValue := XSQL xsqlGetConnectSlot: sqlHandle asParameter. (getSlotValue asPMLong asInteger) = 0 ifTrue: [ errNo := XSQL xsqlErr. self acceptLogLine: ('Connect failure: ',(errNo printString)). ^nil ]. connectStruct := SelfDefinedStructure named: 'SQLTHREAD' atAddress: (ExternalAddress usingBytes: getSlotValue). connectStruct flags: ((connectStruct flags) at: 7 put: 1 for: 1). connection = nil ifTrue: [connection := Array with: nil with: nil]. appNamePtr := ExternalAddress copyToNonSmalltalkMemory: 'SQLBRWSR'. leaks add: appNamePtr. connectHandle := XSQL xsqlConnect: (connectNamePtr asParameter) for: (appNamePtr asParameter) using: (sqlHandle value). connectHandle = 0 ifTrue: [self error: 'Connect to ',aConnectName,' failed!!!!']. thisConnect := Array with: connectHandle with: aConnectName . isSource ifTrue: [connection at: 1 put: thisConnect. guiState bytesAtOffset: XSQLguiSourceOFF put: (connectNamePtr ). guiState sourceMode: aConnectMode. guiState sourceHandle: connectHandle. guiState flags: ((guiState flags) at: 0 put: 1 for: 1). self acceptLogLine: 'Source Database: ',aConnectName,' is connection #',(connectHandle printString). ] ifFalse: [connection at: 2 put: thisConnect. batchState bytesAtOffset: 0 put: (connectNamePtr ). batchState targetMode: aConnectMode. batchState targetHandle: connectHandle. batchState flags: ((batchState flags) at: 3 put: 1 for: 1). self acceptLogLine: 'Target Database: ',aConnectName,' is connection #',(connectHandle printString). ]. "SelfDefinedStructureInspector new openOn: (connectStruct)."! consult "Launch consult on the currently marked fragments."! deleteMarked | goner i n thisStatement thisXStatement statementIndex nSelected rc selected newContents newStatements thisStatementLabel | statements = nil ifTrue: [^nil]. selected := statementPane selections. newStatements := OrderedCollection new. nSelected := selected size. nSelected < 1 ifTrue: [MessageBox notify: 'Invalid delete request.' withText: 'No statement marked for delete.'. ^nil ]. (MessageBox confirm: 'Are you sure you want to delete marked statements?') ifFalse: [^nil]. i := 0. n := 0. statements do: [ :each | i := i + 1. goner := false. selected detect: [ :removee | goner := (removee = i)] ifNone: [newStatements add: each.]. goner ifTrue: [thisStatement := (statements at: i) at: 1. rc := XSQL xsqlFreeXSQL: (thisStatement contents asParameter). sqlTextPane statementIndex = i ifTrue: [sqlTextPane contents: '--*New Fragment' at: 0.]. n := n + 1. ]. ]. statements := newStatements. newContents := OrderedCollection new: (statements size). statements do: [ :each | thisStatement := each at: 1. (thisStatement augment) asInteger = 0 ifFalse: [thisXStatement := (SelfDefinedStructure named: 'BATCH_SQL' atAddress: (ExternalAddress usingBytes: (thisStatement augment))). (thisXStatement prequel) asInteger = 0 ifFalse: [thisStatementLabel := (String fromAddress: (ExternalAddress usingBytes: (thisXStatement prequel)) ). ] ifTrue: [thisStatementLabel := (String fromAddress: (ExternalAddress usingBytes: (thisStatement text))). ] ] ifTrue: [thisStatementLabel := (String fromAddress: (ExternalAddress usingBytes: (thisStatement text))). ]. newContents add: thisStatementLabel. ]. statementPane contents: newContents. self acceptLogLine: ((n printString),' XSQL statement(s) DELETED.').! deleteStatement | thisStatement statementIndex nSelected selected newContents rc | statements = nil ifTrue: [^nil]. selected := statementPane selections. nSelected := nSelected size. nSelected > 1 ifTrue: [MessageBox notify: 'Ambiguous delete request.' withText: 'More than one statement selected for unit delete.'. ^nil ]. (MessageBox confirm: 'Are you sure you want to delete this statement?') ifFalse: [^nil]. thisStatement := (statements at: (selected at: 1)) at: 1. rc := XSQL xsqlFreeXSQL: (thisStatement contents asParameter). statements removeIndex: (selected at: 1). statementPane contents: ((statementPane contents) removeIndex: (selected at: 1)). self acceptLogLine: '1 XSQL statement DELETED'.! disconnect | disconnectCode | connection = nil ifTrue: [MessageBox notify: 'Invalid disconnect request.' withText: 'Not connected to anything.'. ^nil]. disconnectCode := 0. (connection at: 1) = nil ifFalse: [disconnectCode := 1]. (connection at: 2) = nil ifFalse: [disconnectCode = 1 ifTrue: [disconnectCode := 3] ifFalse: [disconnectCode := 2] ]. disconnectCode = 3 ifTrue: [XSQLConnectionSelection new openFor: self answerMode: 2 withSites: nil. ] ifFalse: [self disconnectFrom: disconnectCode ].! disconnectFrom: which | thisHandle source target batchState guiState | "XSQLConnectSelection sends this message where which: 1 => source, which: 2 => target, which: 3 => both." source := connection at: 1. target := connection at: 2. batchState := DBMS at: 4. guiState := DBMS at: 5. ((which = 2) | (which = 3)) ifTrue: [target = nil ifFalse: [thisHandle := (batchState targetHandle). self acceptLogLine: 'Disconnecting Target: ',(target at: 2). XSQL xsqlDisconnect: thisHandle. connection at: 2 put: nil. ] ]. ((which = 1) | (which = 3)) ifTrue: [source = nil ifFalse: [thisHandle := (guiState sourceHandle). self acceptLogLine: 'Disconnecting Source: ',(source at: 2), '(',(thisHandle printString),')'. XSQL xsqlDisconnect: thisHandle. connection at: 1 put: nil. ] ].! displayDetails "open a XSQLBrowserControl in information mode." XSQLBrowserControl new openOn: self forUpdate: false.! editMenu: aTextPane aTextPane setMenu: (TextPane editMenu).! editStatement: selectBox "User has clicked on a fragment. XXSQLEdit fragment and adjust state. Edit is normal ST/V edit. Difference is in accept method which must re-parse the fragment." | nSelected thisStatement thisXStatement statementIndex xsqlComment xsqlStatement xsqlFragment seperator rawString rawStringPtr noneMarked firstMark topPane | statementIndex := selectBox selection. statements = nil ifTrue: [^nil]. self viewMenu: selectBox. topPane := self mainView. (statements at: statementIndex) = nil ifTrue: [^nil]. ((statements at: statementIndex) at: 4) ifTrue: [(sqlTextPane statementIndex = statementIndex) ifTrue: [sqlTextPane contents: '--*New'. (statements at: statementIndex) at: 4 put: false. ]. (statements at: statementIndex) at: 4 put: false. self setRunMenu. ^nil ] ifFalse: [noneMarked := true. statements do: [:each | (each at: 4) ifTrue: [noneMarked := false]]. noneMarked ifTrue: [ topPane := self mainView. (topPane menuWindow menuTitled: 'Run') enableItem: 'Run ~Marked'. ]. (statements at: statementIndex) at: 4 put: true]. thisStatement := (statements at: statementIndex) at: 1. seperator := ' \' withCrs. (thisStatement augment) asInteger = 0 ifFalse: [thisXStatement := (SelfDefinedStructure named: 'BATCH_SQL' atAddress: (ExternalAddress usingBytes: (thisStatement augment))). (thisXStatement prequel) asInteger = 0 ifFalse: [xsqlComment := (String fromAddress: (ExternalAddress usingBytes: (thisXStatement prequel))). ] ifTrue: [xsqlComment := '--No Comment']. (thisStatement text) asInteger ~= 0 ifTrue: [xsqlStatement := (String fromAddress: (ExternalAddress usingBytes: (thisStatement text))). ]. xsqlStatement = nil ifFalse: [xsqlFragment := (xsqlComment, seperator, xsqlStatement).] ifTrue: [xsqlFragment := xsqlComment.]. (thisXStatement sequel) asInteger ~= 0 ifTrue: [rawString := (String fromAddress: (ExternalAddress usingBytes: (thisXStatement sequel))). xsqlFragment := (xsqlFragment, seperator, '--USING', seperator, rawString ) ]. (thisXStatement mapping) asInteger ~= 0 ifTrue: [rawStringPtr := XSQL xsqlDisplayMap: (thisStatement augment). rawString := String fromAddress: (ExternalAddress usingBytes: rawStringPtr ). xsqlFragment := (xsqlFragment, seperator, '--MAPPING', seperator, rawString ) ]. ] ifTrue: [xsqlStatement := (String fromAddress: (ExternalAddress usingBytes: (thisStatement text))). xsqlFragment := xsqlStatement. ]. sqlTextPane contents: xsqlFragment at: statementIndex. self setRunMenu.! executeMenu ^((Menu labels: '~Run All\Run ~Marked\Ma~p\~Stop Run' withCrs lines: #( 2 3 ) selectors: #(runAll runMarked runMapping haltRun )) title: '~Run'; owner: self; yourself)! fileMenu ^((Menu labels: '~Open New\~Save\Save ~As\Save ~Marked\~Restore' withCrs " lines: #(1 4)" selectors: #(open save saveAs saveMarked restore)) title: '~File'; owner: self; yourself)! haltRun (sems = nil) ifTrue: [ ^nil]. (sems at: 2) signal.! insertStatement "Insert a new statement. If nothing selected, insert after the last statement or create new statement collection. If something is selected, insert before the first selection. Let XSQLDBMS handle the EXTENDED_SQL baggage. Will always succeed and causes a new statements to be created."! launchLibrary "open a LibraryBrowser on local file system." LibraryBrowser new open.! launchMenu ^((Menu labels: '~Details\~XAccess\~Consult' withCrs lines: #( 1 ) selectors: #(selectDetails launchLibrary consult)) title: '~Launch'; owner: self; yourself)! loadAndLink "Parse the text file and fill the statement pane." | batchState batchStateP connectsP cursorsP fileNamePtr guiState guiStateP profileName i lastStatement logAndPipeName mainText rc state stateP | CursorManager execute change. DBMS = nil ifTrue: [DBMS := OrderedCollection new: 5. " at: 1 - DBMS Process state" " at: 2 - Cursors (For whole system process)." " at: 3 - Connections (For whole system process)." " at: 4 - Batch Extension State" " at: 5 - Interactive Executor State" stateP := ExternalHandle new. cursorsP := ExternalHandle new. connectsP := ExternalHandle new. batchStateP := ExternalHandle new. guiStateP := ExternalHandle new. logAndPipeName := 'SQLBRWSR.LOG'. logAndPipeName := logAndPipeName asAsciiZ. profileName := 'XACCESS.INI'. rc := XSQL execAdaptive: (stateP asParameter) context: (cursorsP asParameter) database: (connectsP asParameter). rc ~= 0 ifTrue: [self error: (rc printString)]. DBMS add: (state := SelfDefinedStructure named: 'DBMS_PROCESS' atAddress: (ExternalAddress usingBytes: stateP)). state bytesAtOffset: 46 put: logAndPipeName. XSQL xsqlSetSiteDependencies: nil. DBMS add: cursorsP. DBMS add: connectsP. rc := XSQL xsqlLink: nil batchState: (batchStateP asParameter) guiState: (guiStateP asParameter) this: nil. rc ~= 0 ifTrue: [self error: 'XSQLDBMS Link Error: ',(rc printString)]. DBMS add: (batchState := SelfDefinedStructure named: 'BATCH_STATE' atAddress: (ExternalAddress usingBytes: batchStateP)). DBMS add: (guiState := SelfDefinedStructure named: 'INTERACTIVE_STATE' atAddress: (ExternalAddress usingBytes: guiStateP)). sqlFilePathString = nil ifFalse: [fileNamePtr := ExternalAddress copyToNonSmalltalkMemory: (sqlFilePathString asAsciiZ). batchState bytesAtOffset: 50 put: (fileNamePtr asParameter). leaks add: fileNamePtr. ]. profileName = nil ifFalse: [fileNamePtr := ExternalAddress copyToNonSmalltalkMemory: (profileName asAsciiZ). state bytesAtOffset: 38 put: (fileNamePtr asParameter). leaks add: fileNamePtr. ]. guiState optimization: 1. "state flags1: (self at: 0 in: (state flags1) put: 200 for: 8)." ]. CursorManager hand change. logPipe = nil ifTrue: [Processor fork: [self backgroundMonitor]. "at: (Processor highUserPriority)"]. (sqlFilePathString = nil) ifFalse: [rc := XSQL xsqlBatchLink: nil with: nil. (rc asPMLong asInteger) ~= 0 ifTrue: [lastStatement := "Remove this" (SelfDefinedStructure named: 'EXTENDED_SQL' atAddress: (ExternalAddress usingBytes: rc) ). guiState statements: (batchState statements). statementPane update. ] ifFalse: [self acceptLogLine: sqlFilePathString,' is not a valid XSQL file.'.]. ].! mappingCandidate "If the currently selected statements are the right statement types for a mapping answer true." | markedTypes nMarked nthStatement statementN stmntNType | markedTypes := OrderedCollection new. nMarked := 0. nthStatement := 0. statements do: [:each | nthStatement := nthStatement + 1. (each at: 4) ifTrue: [nMarked := nMarked + 1. statementN := (statements at: nthStatement) at: 1. stmntNType := (statementN flags) at: 0 for: 8. markedTypes add: stmntNType. ]. ]. nMarked > 2 ifTrue: [^false]. nMarked < 1 ifTrue: [^false]. nMarked = 1 ifTrue: [(stmntNType = XsqlXUPDATE) ifTrue: [^true]. ^false ]. (markedTypes includes: XsqlSELECT) & (markedTypes includes: XsqlCREATE) ifTrue: [^true]. (markedTypes includes: XsqlSELECT) & (markedTypes includes: XsqlINSERT) ifTrue: [^true]. ^false.! markAll | i markAllList | statements = nil ifTrue: [^nil]. i := 1. markAllList := OrderedCollection new: (statements size). statements do: [ :each | each at: 4 put: true. markAllList add: i. i := i + 1. ]. statementPane selection: markAllList. self setViewMenu.! marshallCandidateMap "Construct map. map at: 1 - (type of source stmn/frgmnt, index, ...) map at: 2 - (type of target stmn/frgmnt, index, ...) . . . Answer success/failure as Boolean. " | sourceDetermined markedType markedTypes nMarked nthStatement soleIndex statementN stmntNType | markedTypes := OrderedCollection new. nMarked := 0. nthStatement := 0. statements do: [:each | nthStatement := nthStatement + 1. (each at: 4) ifTrue: [nMarked := nMarked + 1. soleIndex := nthStatement. statementN := (statements at: nthStatement) at: 1. stmntNType := (statementN flags) at: 0 for: 8. markedType := OrderedCollection new. markedType add: (stmntNType deepCopy); add: (nthStatement deepCopy); add: nil. markedTypes add: (markedType deepCopy). ]. ]. map := OrderedCollection new. nMarked = 1 ifTrue: [map add: #(XsqlXUPDATE, soleIndex, nil). ^true ]. sourceDetermined := false. markedTypes do: [:each| (each at: 1) = XsqlSELECT ifTrue: [map add: each. each at: 3 put: 1. sourceDetermined := true.]. ]. sourceDetermined ifTrue: [markedTypes do: [:each| (each at: 3) = nil ifTrue: [map add: each.] ifFalse: [each at: 3 put: nil]. ] ] ifFalse:[MessageBox notify: 'Ambiguous Map.' withText: 'Can''t figure out source from target'. ^false ]. ^true.! newBoxListFromParse: actionCode nAct: nAction at: aStatementIndex "Bring ST/V variable statements into synch with action already performed by XSQLDBMS" | batchState nthStatement thisStatement newContents thisStatementLabel nextStatement oldStatements ithStatement mthStatement newProcessed newElement mStatements nActing nActedUpon change changed thisXStatement | statementPane contents = nil ifTrue: [^self boxListFromParse: nil] ifFalse: [mStatements := statementPane contents size.]. nActing := nAction x. nActedUpon := nAction y. batchState := DBMS at: 4. nthStatement := (batchState nStatements). oldStatements := statements. statements := OrderedCollection new: nthStatement. nextStatement := (SelfDefinedStructure named: 'EXTENDED_SQL' atAddress: (ExternalAddress usingBytes: (batchState statements)) ). statementPane contents = nil ifTrue: [sqlTextPane toggleWrap]. newContents := OrderedCollection new: nthStatement. ithStatement := nthStatement. [ithStatement > 0] whileTrue: [ ithStatement := ithStatement - 1. statements add: nil.]. ithStatement := 1. mthStatement := 1. newProcessed := 0. changed := ' '. [nthStatement > 0] whileTrue: [thisStatement := nextStatement. (thisStatement augment) asInteger = 0 ifFalse: [thisXStatement := (SelfDefinedStructure named: 'BATCH_SQL' atAddress: (ExternalAddress usingBytes: (thisStatement augment)) ). (thisXStatement prequel) asInteger = 0 ifFalse: [thisStatementLabel := (String fromAddress: (ExternalAddress usingBytes: (thisXStatement prequel)) ). ] ifTrue: [thisStatementLabel := (String fromAddress: (ExternalAddress usingBytes: (thisStatement text)) ). ] ] ifTrue: [thisStatementLabel := (String fromAddress: (ExternalAddress usingBytes: (thisStatement text)) ). ]. newContents add: thisStatementLabel. ((thisStatement next) asInteger ~= 0) ifTrue: [nextStatement := SelfDefinedStructure named: 'EXTENDED_SQL' atAddress: (ExternalAddress usingBytes: (thisStatement next)) . ]. newElement := false. ( ( mthStatement < aStatementIndex ) | ( ( mthStatement >= (aStatementIndex + nActedUpon)) & ( mthStatement > mStatements) ) ) ifTrue: [ statements at: ithStatement put: (oldStatements at: mthStatement). mthStatement := mthStatement + 1. ] ifFalse: [ actionCode = 1 ifTrue: [ change := 'INSERTED.'. newProcessed = 0 ifTrue: [newProcessed := newProcessed - 1. statements at: ithStatement put: (oldStatements at: mthStatement). mthStatement := mthStatement + 1.]. newProcessed < 0 ifTrue: [newProcessed := 1. newElement := true. ]. newProcessed > 0 ifTrue: [newProcessed := newProcessed + 1. newElement := true. ]. ]. actionCode = 2 ifTrue: [ change := 'REPLACED.'. newProcessed = 0 ifTrue: [mthStatement := mthStatement + 1.]. newProcessed := newProcessed + 1. newElement := true.]. ]. newElement ifTrue: [statements at: ithStatement put: (Array with: thisStatement with: nil with: nil with: false).]. nthStatement := nthStatement - 1. ithStatement := ithStatement + 1. ]. statementPane contents: newContents. self acceptLogLine: (nActedUpon printString),' XSQL statement(s) ',change. ^newContents! open | fileNamePtr userString rc guiState batchState lastStatement titleString temp | (userString := (FileDialog new openFile file)) = nil ifTrue: [^nil]. DBMS = nil ifTrue: [^nil]. batchState := DBMS at: 4. guiState := DBMS at: 5. leaks = nil ifTrue: [leaks := OrderedCollection new.]. fileNamePtr := ExternalAddress copyToNonSmalltalkMemory: (userString asAsciiZ). leaks add: fileNamePtr. batchState bytesAtOffset: 50 put: (fileNamePtr asParameter). ((guiState statements) asInteger = 0) ifFalse: [XSQL xsqlEndXSQL.]. rc := XSQL xsqlBatchLink: nil with: nil. (rc asPMLong asInteger) ~= 0 ifTrue: [sqlFilePathString := userString. (sqlFilePathString size > 30) ifTrue: [temp := userString reversed asStream. temp := (temp upTo: $\) reversed. titleString := 'XSQL in ...\',temp.] ifFalse: [titleString := 'XSQL in ',sqlFilePathString.]. self labelWithoutPrefix: titleString. guiState statements: (batchState statements). statementPane update. ] ifFalse: [self acceptLogLine: userString,' is not a valid XSQL module.'.].! openOn: xsqlFileStream using: xsqlFilePath "open an instance of the receiver on the file at xsqlFilePath" | listLineHeight vRatio hRatio sqlFilePath sqlFileStream titleString | DBMS = nil ifFalse: [MessageBox notify: 'XSQL Operator Error' withText: 'XSQL Browser already running!!'. ^nil ]. CursorManager execute change. listLineHeight := ListFont height + 4. Smalltalk at: #XSQLDBMS ifAbsent: [self error: 'XSQLDBMS class is missing']. vRatio == nil ifTrue: [vRatio := 2 / 3]. hRatio == nil ifTrue: [hRatio := 2 / 3]. leaks = nil ifTrue: [leaks := OrderedCollection new.]. xsqlFileStream = 'nil' ifTrue: [sqlFileStream := nil. sqlFilePath := nil. ] ifFalse: [sqlFileStream := xsqlFileStream. sqlFilePath := xsqlFilePath. ]. sqlFilePath = nil ifFalse: [((sqlFilePath at: (sqlFilePath size)) = $\) ifFalse: [sqlFilePathString := (sqlFilePath,'\',sqlFileStream) asAsciiZ.] ifTrue: [sqlFilePathString := (sqlFilePath,sqlFileStream) asAsciiZ.]. (sqlFilePathString size > 30) ifTrue: [titleString := 'XSQL in ...\',sqlFileStream.] ifFalse: [titleString := 'XSQL in ',sqlFilePathString.]. ] ifTrue: [titleString := 'XSQL Browser'.]. self owner: self; labelWithoutPrefix: titleString; icon: ( Icon fromModule: 'XSQLICON' id: 1 ); yourself. self when: #close perform: #close:. self when: #menuBuilt perform: #resetActionBar:. self addSubpane: (statementPane := MultipleSelectListBox new owner: self; when: #getContents perform: #boxListFromParse:; when: #select perform: #editStatement:; when: #doubleClickSelect perform: #selectStatement:; when: #getMenu perform: #viewMenu:; framingRatio: (Rectangle leftTopUnit extentFromLeftTop: (hRatio @ vRatio))). self addSubpane: (sqlTextPane := XSQLTextPane new owner: self; when: #getContents perform: #editStatement:; when: #saveXSQL perform: #acceptXSQL; when: #getMenu perform: #editMenu:; font: (fixedFont := Font allFonts detect: [:i| i fixedWidth & i isImage & (i height > 10)] ifNone: [SysFont]); framingRatio: ( (Rectangle leftTopUnit right: hRatio) extentFromLeftTop: ((1 - hRatio) @ vRatio) ) ). self addSubpane: (transcriptPane := XSQLLogPane new owner: self; when: #save perform: #accept; when: #getMenu perform: #editMenu:; font: (fixedFont := Font allFonts detect: [:i| i fixedWidth & i isImage & (i height > 10)] ifNone: [SysFont]); framingRatio: ( (Rectangle leftTopUnit down: (hRatio)) extentFromLeftTop: (1 @ (1 - hRatio)) ) ). Linked = nil ifTrue: [(self class) buildXSQLTypes. (self class) buildOtherConstants. (self class) linkSQL]. XSQLDBMS clearCachedAddresses. self openWindow. self menuWindow removeMenu: (self menuWindow menuTitled: 'ListEdit' ). self menuWindow removeMenu: (self menuWindow menuTitled: '~Edit' ). transcriptPane nextPutAll: 'XSQL 0.290 ',((Date dateAndTimeNow) printString); cr; nextPutAll: 'Copyright(c) 1993-1997 American Kybernetik, Inc.'; cr; cr. sqlTextPane contents: '--*NEW XSQL Fragment' at: 0. self menuWindow removeMenu: (self menuWindow menuTitled: 'Edit' ). (self menuWindow menuTitled: 'File' ) disableItem: '~Save'. (self menuWindow menuTitled: 'File' ) disableItem: 'Save ~As'. (self menuWindow menuTitled: 'File' ) disableItem: 'Save ~Marked'. (self menuWindow menuTitled: 'File' ) disableItem: '~Restore'. (self menuWindow menuTitled: 'Launch' ) disableItem: '~Consult'. "(hm := HelpManager for: self mainView title: 'XSQL/2 Documentation' file: 'xsql.hlp' dialogs: (Array with: Prompter windowId)) buildMenuBar. " events := OrderedCollection new. " sems at: 1 = next index in sems to use." " at: 2 = ontic sem" " at: 3 = asynch sem" " at: 4 - n = Other task sems" sems := OrderedCollection new. sems add: 4; add: (Semaphore new); add: (Semaphore new). Processor fork: [self asynchMonitor]. "at: (Processor highUserPriority)" self loadAndLink. "XSQL xsqlInit." XSQL xsqlTraceOn: nil atLevel: 201.! openSchema | fileNamePtr userString rc guiState batchState lastStatement titleString temp | (userString := (FileDialog new openFile file)) = nil ifTrue: [^nil]. DBMS = nil ifTrue: [^nil]. batchState := DBMS at: 4. guiState := DBMS at: 5. leaks = nil ifTrue: [leaks := OrderedCollection new.]. fileNamePtr := ExternalAddress copyToNonSmalltalkMemory: (userString asAsciiZ). leaks add: fileNamePtr. batchState bytesAtOffset: 50 put: (fileNamePtr asParameter). ((guiState statements) asInteger = 0) ifFalse: [XSQL xsqlEndXSQL.]. rc := XSQL xsqlBatchLink: nil with: nil. (rc asPMLong asInteger) ~= 0 ifTrue: [lastStatement := "Remove this" (SelfDefinedStructure named: 'EXTENDED_SQL' atAddress: (ExternalAddress usingBytes: rc) ). sqlFilePathString := userString. (sqlFilePathString size > 30) ifTrue: [temp := userString reversed asStream. temp := (temp upTo: $\) reversed. titleString := 'XSQL in ...\',temp.] ifFalse: [titleString := 'XSQL in ',sqlFilePathString.]. self labelWithoutPrefix: titleString. guiState statements: (batchState statements). statementPane update. ] ifFalse: [self acceptLogLine: userString,' is not a valid XSQL file.'.].! resetActionBar: topPane topPane menuWindow removeMenu: (topPane menuWindow menuTitled: '~File' ); removeMenu: (topPane menuWindow menuTitled: '~Smalltalk' ); removeMenu: (topPane menuWindow menuTitled: '~Edit' ); removeMenu: (topPane menuWindow menuTitled: '~Help' ). topPane menuWindow addMenu: (self fileMenu); addMenu: (self connectMenu ); addMenu: (self executeMenu); addMenu: (self launchMenu). (topPane menuWindow menuTitled: 'Run') disableItem: '~Stop Run'. (topPane menuWindow menuTitled: 'Run') disableItem: 'Run ~Marked'. (topPane menuWindow menuTitled: 'Run') disableItem: 'Ma~p'.! restore! run: statementIndex notify: nthSem "Execute the statement or command at aStatementIndex in statements." | batchState connectHandle connectName guiState state thisStmntType thisXStmnt thisStatement thisStmntQuad theHandle | "self halt." statements = nil ifTrue: [^nil]. state := DBMS at: 1. guiState := DBMS at: 5. batchState := DBMS at: 4. thisStatement := (statements at: statementIndex) at: 1. (statements at: statementIndex) at: 2 put: nil. "self setDefaultConnectName." CursorManager question changeFor: [ theHandle := XSQL xsqlExecXSQL: (guiState dbHandle) this: (thisStatement contents asParameter). ]. CursorManager execute change. [:errorValue | errorValue := XSQL xsqlErr . errorValue ~= 0 ifTrue: [self error: ('XSQLDBMS error #',(errorValue printString))] ]. self syncConnections. theHandle > 0 ifTrue: [(statements at: statementIndex) at: 2 put: theHandle.] ifFalse: [(statements at: statementIndex) at: 2 put: nil.]. thisStmntQuad := (statements at: statementIndex). (thisStmntQuad at: 2) = nil ifFalse: [thisStmntType := (thisStatement flags) at: 0 for: 8 . ((thisStmntType = XsqlSQLNOT) | (thisStmntType > XsqlSQLHANDLERETURNED)) ifTrue: ["self halt." XSQL xsqlEndSQL: theHandle. thisStmntQuad at: 2 put: nil. ]. ]. nthSem = nil ifFalse: [(sems at: nthSem) signal]. CursorManager normal change. ^thisStmntQuad! runAll statements = nil ifTrue: []. self runAll: nil.! runAll: aStatementCollection "If aStatementCollection is nil, run all. Else run those whose indices are in aStatementCollection." | guiState ithStatement state statementsToGo thisStmntType thisXStmnt thisStmnt thisStmntQuad thisSQLHandle thisSite running nthStatement nthSem topPane noneMarked | state := DBMS at: 1. guiState := DBMS at: 5. aStatementCollection = nil ifTrue: [ statementsToGo := statements size. ] ifFalse: [ statementsToGo := aStatementCollection size.]. ithStatement := 1. running := true. CursorManager execute change. topPane := self mainView. (topPane menuWindow menuTitled: 'Run') enableItem: '~Stop Run'. (topPane menuWindow menuTitled: 'Run') disableItem: 'Run ~Marked'. (topPane menuWindow menuTitled: 'Run') disableItem: 'Ma~p'. (topPane menuWindow menuTitled: 'Run') disableItem: '~Run All'. [(statementsToGo > 0) & running] whileTrue: [aStatementCollection = nil ifTrue: [nthStatement := ithStatement] ifFalse: [nthStatement := (aStatementCollection at: ithStatement)]. nthSem := (sems at: 1). (sems size < nthSem) ifTrue: [sems add: (Semaphore new)]. "Processor fork: ["thisStmntQuad := self run: nthStatement notify: nthSem"]". "(sems at: nthSem) wait. sems at: 1 put: nthSem." thisStmntQuad = nil ifFalse: [thisStmnt := thisStmntQuad at: 1. thisSQLHandle := thisStmntQuad at: 2. thisStmntType := (thisStmnt flags) at: 0 for: 8 . ((thisStmntType > XsqlSQLNOT) & (thisStmntType < XsqlSQLHANDLERETURNED) & (thisSQLHandle = nil)) ifTrue: [running := false]. (thisSQLHandle ~= nil) ifTrue: [((thisStmntType > XsqlSQLNOT) & (thisStmntType < XsqlSQLHANDLERETURNED)) ifFalse: [ XSQL xsqlEndSQL: (thisSQLHandle)]. ]. ]. statementsToGo := statementsToGo - 1. ithStatement := ithStatement + 1. (sems at: 2) hasSignals ifTrue: [running := false.]. Processor yield. ]. CursorManager normal change. (topPane menuWindow menuTitled: 'Run') disableItem: '~Stop Run'. (topPane menuWindow menuTitled: 'Run') enableItem: '~Run All'. noneMarked := true. statements do: [:each | (each at: 4) ifTrue: [noneMarked := false]]. noneMarked ifTrue: [(topPane menuWindow menuTitled: 'Run') disableItem: 'Run ~Marked'. ]. [(sems at: 1 ) < (aStatementCollection size)] whileTrue: [Processor yield]. running ifTrue: [self acceptLogLine: 'The XSQL completed OK.'.] ifFalse: [self acceptLogLine: 'The XSQL was terminated.'.]. Processor yield.! runMapping "Map will not have been enabled unless plausible statements were marked. If an explicit mapping statement is selected xsqlMap it. If an implicit set of mapping statements is present, sythesize a mapping statement from them. Otherwise present the final mapping option menu." | synthesis finalOption statementPtr1 statementPtr2 | (self marshallCandidateMap) ifFalse: [MessageBox notify: 'Invalid Map Selection.' withText: 'The marked statements cannot form a mapping.'. ^nil ]. ((map at: 1) at: 1) = XsqlUPDATE ifTrue: [finalOption := (((Menu labels: '~Execute Mapping\~Cancel Mapping' withCrs lines: #(1 2) selectors: #('E' 'C') ) owner: self ) popUp). ] ifFalse: ["finalOption := (((Menu labels: '~Synthesize Mapping\~Cancel Mapping' withCrs lines: #(1 2) selectors: #('S' 'C') ) owner: self ) popUp). finalOption = 'C' ifTrue:[^nil]." synthesis := XSQL xsqlSynthesizeMapAt: ((map at: 1) at: 2) and: ((map at: 2) at: 2). synthesis asInteger = 0 ifFalse: [ MessageBox notify: 'Mapping Synthesis Failure: ',(synthesis printString) withText: 'The marked statements cannot be the basis of a mapping.'. ]. "finalOption := (((Menu labels: '~Modify Mapping\~Execute Mapping\~Cancel Mapping' withCrs lines: #(1 2 3) selectors: #('M' 'E' 'C') ) owner: self ) popUp)." finalOption := 'M' ]. finalOption = 'C' ifTrue: [^nil]. finalOption = 'M' ifTrue: [self startInteractiveMap]. finalOption = 'E' ifTrue: [self runMarked.].! runMarked "Collect the marked statements and run them." | nSelected selected | statements = nil ifTrue: [^nil]. selected := statementPane selections. nSelected := selected size. nSelected < 1 ifTrue: [MessageBox notify: 'Invalid execution request.' withText: 'No statement selected for execution.'. ^nil ]. self runAll: selected.! save "Write the text for all of the statements to the current sql text file path." self saveAll: statements toPath: sqlFilePathString.! saveAll: statementCollection toPath: aPathString "Write the text for all of the statements in the collection to the indicated path." | newXSQL thisStatement thisXStatement thisText text1 | CursorManager hand change. newXSQL := File pathName: aPathString. newXSQL nextPutAll: ('--* XSQL Generated this file from ',sqlFilePathString); cr; nextPutAll: ('--* ... on ',' mm-dd-yy '); cr. statementCollection do: [ :each | thisStatement := each at: 1. (thisStatement augment) asInteger = 0 ifFalse: [thisXStatement := (SelfDefinedStructure named: 'BATCH_SQL' atAddress: (ExternalAddress usingBytes: (thisStatement augment)) ). (thisXStatement prequel) asInteger = 0 ifFalse: [thisText := (String fromAddress: (ExternalAddress usingBytes: (thisXStatement prequel)) ). newXSQL nextPutAll: thisText; cr. text1 := thisXStatement prequel. ]. ] ifTrue: [text1 := nil]. (text1 = nil | (text1 ~= (thisStatement text)) & (thisStatement text) asInteger ~= 0) ifTrue: [thisText := (String fromAddress: (ExternalAddress usingBytes: (thisStatement text)) ). newXSQL nextPutAll: thisText; cr. ]. ]. newXSQL close. CursorManager normal change. self acceptLogLine: ((statementCollection size printString),' XSQL statement(s) written to ',aPathString).! saveAs "Write the text for all of the statements to a file specified by the user." self saveAll: statements toPath: (FileDialog new openFile file).! saveMarked "Write the text for all marked statements to a file specified by the user." | nSelected selected selectedStmnts | statements = nil ifTrue: [^nil]. selected := statementPane selections. nSelected := selected size. nSelected < 1 ifTrue: [MessageBox notify: 'Invalid save request.' withText: 'No statement(s) selected for save.'. ^nil ]. selectedStmnts := OrderedCollection new. selected do: [:each | selectedStmnts add: (statements at: each).]. self saveAll: selectedStmnts toPath: (FileDialog new openFile file).! selectDetails | selectMenu selectMode | selectMenu := (((Menu labels: '~Edit\~View\~Cancel' withCrs lines: #( 1 2 ) selectors: #('E' 'V' 'C') ) owner: self) ). "selectMenu disableItem: 'E'." (selectMode := selectMenu popUp) = 'C' ifTrue: [^nil]. (selectMode = 'E') ifTrue: [^self changeDetails]. ^self displayDetails.! selectStatement: listBox "User has double-clicked. Execute the statement if it does not have a handle. If it has a handle and is eligible for but doesn't have a ResultTableBrowser, then open one on it. If it has a 'Browser, switch to it. If the statement was executed and after that it had a 'Browser, the pre-existing one is closed." | guiState thisStmntType thisStmntQuad theHandle thisStatement statementIndex nSelected selected connectHandle | statements = nil ifTrue: [^nil]. selected := statementPane selections. nSelected := selected size. nSelected > 1 ifTrue: [MessageBox notify: 'Ambiguous execution request.' withText: 'More than one statement selected for unit execution.'. ^nil ]. nSelected < 1 ifTrue: [^nil]. guiState := DBMS at: 5. thisStmntQuad := statements at: (selected at: 1). thisStatement := thisStmntQuad at: 1. thisStmntType := (thisStatement flags) at: 0 for: 8 . (thisStmntQuad at: 2) = nil ifTrue: [self run: (selected at: 1) notify: nil. (thisStmntQuad at:3) = nil ifTrue: [((thisStmntType > XsqlSQLNOT) & (thisStmntType < XsqlSQLHANDLERETURNED)) ifTrue: [((thisStmntQuad at: 2) ~= nil) ifTrue: [thisStmntQuad at: 3 put: (XSQLResultBrowser new openFor: self withCursor: (thisStmntQuad at: 2) at: (selected at:1)). ]. ] ] ifFalse: [(thisStmntQuad at: 3) close. ((thisStmntQuad at: 2) ~= nil) ifTrue: [thisStmntQuad at: 3 put: (XSQLResultBrowser new openFor: self withCursor: (thisStmntQuad at: 2) at: (selected at:1)). ]. ]. ] ifFalse: [ (thisStmntQuad at: 3) = nil ifTrue: [( ((thisStmntType > XsqlSQLNOT) & (thisStmntType < XsqlSQLHANDLERETURNED)) & ((thisStmntQuad at: 2) ~= nil) ) ifTrue: [ thisStmntQuad at: 3 put: (XSQLResultBrowser new openFor: self withCursor: (thisStmntQuad at: 2) at: (selected at:1)). ]. ] ifFalse: [(thisStmntQuad at: 3) attention.]. ]. statementPane clearSelections.! selectStatementAt: aStatementIndex "modified clone of (the late) statementSelected:" | guiState thisStmntType thisStmntQuad theHandle thisStatement statementIndex connectHandle editMode viewClass viewResult | guiState := DBMS at: 5. thisStmntQuad := statements at: aStatementIndex. thisStatement := thisStmntQuad at: 1. thisStmntType := (thisStatement flags) at: 0 for: 8 . ((viewResult := self viewClassAt: aStatementIndex with: thisStmntQuad) at: 1) = nil ifTrue: [^nil]. editMode := viewResult at: 3. viewClass := viewResult at: 1. ((thisStmntQuad at: 2) = nil) & editMode ifTrue: [self run: aStatementIndex notify: nil. (thisStmntQuad at:3) = nil ifTrue: [((thisStmntQuad at: 2) ~= nil) & (viewClass ~= nil) ifTrue: [thisStmntQuad at: 3 put: (viewClass new openFor: selectFor withCursor: (thisStmntQuad at: 2) at: aStatementIndex). ]. ] ifFalse: [(thisStmntQuad at: 3) close. ((thisStmntQuad at: 2) ~= nil) & (viewClass ~= nil) ifTrue: [thisStmntQuad at: 3 put: (viewClass new openFor: selectFor withCursor: (thisStmntQuad at: 2) at: aStatementIndex). ]. ]. ] ifFalse: [(thisStmntQuad at: 3) = nil ifTrue: [viewClass ~= nil ifTrue: [ thisStmntQuad at: 3 put: (viewClass new openFor: selectFor withCursor: (thisStmntQuad at: 2) at: aStatementIndex). ]. ] ifFalse: [(thisStmntQuad at: 3) attention.]. ].! setDefaultConnectName | guiState state thisSite | guiState := DBMS at: 5. state := DBMS at: 1. (((guiState connectName) asInteger) = 0) & (((state siteTable) asInteger) ~= 0) ifTrue: [thisSite := (SelfDefinedStructure named: 'SITE' atAddress: (ExternalAddress usingBytes: (state siteTable))) . guiState connectName: (thisSite name). guiState accessMode: (thisSite accessMode). "self acceptLogLine: 'Connect name and mode defaulted'." ].! setRunMenu "Renable what should be." | nSelected selected statementIndex topPane | "self halt." statements = nil ifTrue: [^nil]. statementIndex := statementPane selection. selected := statementPane selections. topPane := self mainView. nSelected := selected size. (nSelected >= 1) ifTrue: [(topPane menuWindow menuTitled: 'Run') enableItem: 'Run ~Marked'. (self mappingCandidate) ifTrue: [(topPane menuWindow menuTitled: 'Run') enableItem: 'Ma~p'] ifFalse: [(topPane menuWindow menuTitled: 'Run') disableItem: 'Ma~p'] ] ifFalse: [(topPane menuWindow menuTitled: 'Run') disableItem: 'Run ~Marked'. (topPane menuWindow menuTitled: 'Run') disableItem: 'Ma~p'. ]. (topPane menuWindow menuTitled: 'Run') disableItem: '~Stop Run'. (topPane menuWindow menuTitled: 'Run') enableItem: '~Run All'.! setViewMenu | nSelected selected topPane viewMenu | viewMenu := Menu labels: ('~Delete\D~elete Marked\~Mark All\~Unmark All\~View XSQL') withCrs lines: #(2 3 5 8) selectors: #(deleteStatement deleteMarked markAll unmarkAll viewXSQL ). statements = nil ifTrue: [^nil]. selected := statementPane selections. topPane := statementPane. nSelected := selected size. (nSelected >= 1) ifTrue: [viewMenu enableAll. (nSelected > 1) ifTrue: [viewMenu disableItem: '~View XSQL'.] ] ifFalse: [viewMenu disableAll.]. nSelected = (statements size) ifTrue: [viewMenu disableItem: '~Mark All'.] ifFalse: [viewMenu enableItem: '~Mark All'.]. statementPane setPopupMenu: (viewMenu title: 'ViewMenu'; owner: self; yourself).! startInteractiveMap "start the source, target, and map control windows." | mapper sqlHandlePair source sourceIndex target targetIndex | source := map at: 1. target := map at: 2. sourceIndex := (source at: 2). targetIndex := (target at: 2). mapper := XSQLColumnMapping for: self. selectFor := mapper. self selectStatementAt: sourceIndex. spawningMap := true. self selectStatementAt: targetIndex. spawningMap := false. sqlHandlePair := #(((statements at: sourceIndex) at: 2) ((statements at: targetIndex) at: 2) ). mapper openWithHandles: sqlHandlePair.! state DBMS = nil ifTrue: [^nil]. ^(DBMS at: 1).! statement: aStatementIndex statements = nil ifFalse: [^(statements at: aStatementIndex)] ifTrue: [^nil].! stepMarked "runAll selected, check control after execution of each but last."! syncConnections "Check if backend has set source or target and set ST/V variables appropos." | connectName batchState guiState | batchState := DBMS at: 4. guiState := DBMS at: 5. (batchState targetHandle) ~= 0 ifTrue: [connection = nil ifTrue: [connection := Array with: nil with: nil.]. connectName := String fromAddress: (ExternalAddress usingBytes: (batchState target)) . connection at: 2 put: (Array with: (batchState targetHandle) with: connectName). "self acceptLogLine: 'Target synched.'." ]. (guiState sourceHandle) ~= 0 ifTrue: [connection = nil ifTrue: [connection := Array with: nil with: nil.]. connectName := String fromAddress: (ExternalAddress usingBytes: (guiState source)) . connection at: 1 put: (Array with: (guiState sourceHandle) with: connectName). "self acceptLogLine: 'Source synched.'." ].! unmarkAll statements = nil ifTrue: [^nil]. statements do: [ :each | each at: 4 put: false. ]. statementPane clearSelections. self setViewMenu.! viewClassAt: aStatementIndex with: thisStmntQuad | guiState thisStmntType theHandle thisStatement thisXStatement thisHit hitP nParms viewMode answer viewMenu | "self halt." guiState := DBMS at: 5. thisStatement := thisStmntQuad at: 1. thisStmntType := (thisStatement flags) at: 0 for: 8. "self halt." answer := Array with: nil with: (thisStmntQuad at: 2) with: false. " at:1 - view class, at:2 - active cursor, at:3 whether execution needed or not" (thisStatement augment) asInteger = 0 ifFalse: [thisXStatement := (SelfDefinedStructure named: 'BATCH_SQL' atAddress: (ExternalAddress usingBytes: (thisStatement augment)) ). (thisXStatement this) asInteger = 0 ifFalse: [thisHit := (SelfDefinedStructure named: 'KNOWN_SQL' atAddress: (ExternalAddress usingBytes: (thisXStatement this)) ). nParms := (thisHit flags) at: 0 for: 8 . "self halt." ] ifTrue: [nParms := 0]. ] ifTrue: [nParms := 0.]. ((thisStmntType > XsqlSQLNOT) & (thisStmntType < XsqlSQLHANDLERETURNED)) ifTrue: [(thisStmntType = XsqlSELECT) "& (nParms = 0)" ifTrue: [answer at: 1 put: XSQLResultBrowser; at: 3 put: true. ] ifFalse: [spawningMap ifFalse:[viewMenu := (((Menu labels: '~Edit\~View\~Cancel' withCrs lines: #( 1 2 ) selectors: #('E' 'V' 'C') ) owner: self) ). nParms = 0 ifTrue: [viewMenu disableItem: 'E'.]. (viewMode := viewMenu popUp) = 'C' ifTrue: [^answer] ifFalse: [viewMode = 'E' ifTrue: [answer at: 1 put: XSQLDynamicEditor.] ifFalse: [answer at: 1 put: XSQLResultBrowser.]. ]. ] ifTrue:[answer at: 1 put: XSQLDynamicEditor; at: 3 put: true. ]. ]. ^answer ] ifFalse: [^nil].! viewMenu: selectBox self setViewMenu.! viewXSQL | thisStatement statementIndex nSelected selected runSet thisStatementLabel | statements = nil ifTrue: [^nil]. selected := statementPane selections. nSelected := selected size. nSelected < 1 ifTrue: [MessageBox notify: 'Invalid execution request.' withText: 'No statement selected for view.'. ^nil ]. runSet := OrderedCollection new: nSelected. selectFor := self. selected do: [ :each | self selectStatementAt: each. ].! !