From VisualWorks®, 7.6 of February 8, 2008 on March 3, 2008 at 9:41:21 pm (Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned. Choose terminate or close.'] <class> <name>ExternalDatabaseException</name> <environment>Database</environment> <super>Core.Error</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseException
ExternalDatabaseException is raised in case of the external database common errors.
</comment> <class> <name>UnableToExecuteSQL</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToExecuteSQL
UnableToExecuteSQL is used to indicate that the prepared SQL text could not be executed.
</comment> <class> <name>DuplicateIndexesError</name> <environment>Database</environment> <super>Database.UnableToExecuteSQL</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.DuplicateIndexesError
DuplicateIndexesError is used to indicate attempting to add an index having the same columns as an existing index.
</comment> <class> <name>InvalidSessionState</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.InvalidSessionState
InvalidSessionState is as not been commented. The comment should state the purpose of the class and also explain any unobvious aspects of the implementation.
</comment> <class> <name>IndexConflict</name> <environment>Database</environment> <super>Database.UnableToExecuteSQL</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.IndexConflict
IndexConflict is used to indicate attempt to insert or update an object that has the same index value as another object.
</comment> <class> <name>UnableToPrepare</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToPrepare
UnableToPrepare is used to indicate that it is unable to prepare an SQL statement.
</comment> <class> <name>InvalidTableName</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.InvalidTableName
InvalidTableName is used to indicate that the query specified an invalid table name
</comment> <class> <name>AdHocQueryTool</name> <environment>Database</environment> <super>UI.ApplicationModel</super> <private>false</private> none connection session answerStream queryModel tableModel whichDriverModel connectedStatusHolder executeStatusHolder moreAnswersStatusHolder profile blockFactorModel <imports></imports> <category>Database-Tools</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.AdHocQueryTool
AdHocQueryTool is a simple application that supports ad hoc database queries, and demonstrates the use of the External Database Interface. Instance variables: connection <ExternalDatabaseConnection> The current database connection. queryModel <ValueHolder> Holds the latest query. tableModel <TableInterface> The table used to display results. whichDriverModel <ValueHolder> Holds the name of the Database Connect to use. usernameModel <ValueHolder> Holds the username to use to make the connection. passwordModel <ValueHolder> Holds the password to use to make the connection. environmentModel <ValueHolder> Holds the environment (connect) string to make the connection. blockFactorModel <ValueHolder> Holds the block factor to use when executing the query.
</comment> <class> <name>InvalidTransactionState</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.InvalidTransactionState
InvalidTransactionState is used to indicate that the application cannot use a function at a given time.
</comment> <class> <name>TooManyActiveConnections</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.TooManyActiveConnections
TooManyActiveConnections is used to indicate that the driver for this connection already has the maximum number of active connections.
</comment> <class> <name>SQLSyntaxError</name> <environment>Database</environment> <super>Database.UnableToExecuteSQL</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.SQLSyntaxError
SQLSyntaxError is used to indicate that the SQL text could not be prepared.
</comment> <class> <name>ConnectionException</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ConnectionException
ConnectionException is raised to indicate problems in the ANSI-2 exception class named connection exception.
</comment> <class> <name>UnableToConnectToSQLserver</name> <environment>Database</environment> <super>Database.ConnectionException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToConnectToSQLserver
UnableToConnectToSQLserver is used to indicate that the connection cannot be made to the database server. This signal is used when it is the server that is the cause of the failure. If it is possible to segregate the errors, an unableToConnectToSQLEnvironmentSignal should be used.
</comment> <class> <name>UnableToConnectToSQLenvironment</name> <environment>Database</environment> <super>Database.UnableToConnectToSQLserver</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToConnectToSQLenvironment
UnableToConnectToSQLenvironmentS is used to indicate that the connection cannot be made to the database environment for some reason other than the server itself. This signal is used when it is possible to segregate the error causes, otherwise unableToConnectToSQLserverSignal should be used.
</comment> <class> <name>ExternalDatabaseResumableException</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseResumableException
ExternalDatabaseResumableException is a super class of the external database resumable exceptions.
</comment> <class> <name>RequiredPassword</name> <environment>Database</environment> <super>Database.ExternalDatabaseResumableException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.RequiredPassword
RequiredPassword is used to indicate that a password is required in order to connect. This signal is proceedable and expects a password string as the proceedWith: value.
</comment> <class> <name>UnableToAllocateHandle</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToAllocateHandle
UnableToAllocateHandle is used to indicate that a handle could not be allocated.
</comment> <class> <name>UnableToFreeResource</name> <environment>Database</environment> <super>Database.ExternalDatabaseResumableException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToFreeResource
UnableToFreeResource is used to indicate that an external resource could not be released/dropped/free'd.
</comment> <class> <name>UnsupportedDriverFunctionality</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnsupportedDriverFunctionality
UnsupportedDriverFunctionality is used to indicate that an attempt was made to use functionality which is not available from the underlying API due to the current execution circumstances.
</comment> <class> <name>DynamicSQLError</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.DynamicSQLError
DynamicSQLError is used to indicate problems in the ANSI-2 exception class named dynamic SQL error.
</comment> <class> <name>InvalidDescriptorCount</name> <environment>Database</environment> <super>Database.DynamicSQLError</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.InvalidDescriptorCount
InvalidDescriptorCount is used to indicate that there are more input variables in an SQL statement than are found in the bind object.
</comment> <class> <name>ExternalDatabaseFramework</name> <environment>Database</environment> <super>Core.Object</super> <private>false</private> none stateHolder traceStream traceLevel participants participantsSemaphore <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseFramework
Class ExternalDatabaseFramework is an abstract class defining common services for the implementation of the external database interface. Applications never use this class directly. The external database interface defines application-visible services and is composed of abstract classes. To access a database, a driver is used. Each driver is a set of concrete classes which implement the external database interface services by making calls to a specific database interface library. A driver may also extend the services available to the application in order to provide features which are unique to that database library. The interface divides overall services into connections, sessions, answer streams, and column descriptions. Each of these concepts is represented by a class. ExternalDatabaseConnection defines transaction and connection management services. ExternalDatabaseSession defines services for preparing and executing SQL statements. ExternalDatabaseAnswerStream defines services for processing the answer set of a SELECT statement. ExternalDatabaseColumnDescription defines information which describes a column of a table or answer set. ExternalDatabaseTransaction is used by the connection to handle transaction services, but is not directly utilized by application programmers using the external database interface. As a naming convention, the driver-specific subclasses of the above abstract classes will have the driver name as a prefix in the class name in place of "ExternalDatabase". ExternalDatabaseFramework services: 1) registration for active instances of a subclass (used when holding external handles) 2) a framework for finalization 3) a signal dictionary for all signals 4) a framework for trace output collection and generation 5) a framework for activation control (pause and resume) 6) a collection of participants (see below for definition of participation) 7) a framework for preparing trace entries Registry: The basic design of the external database interface requires every driver class that holds external resources have a registry. It is assumed that: 1) the holder of external resources is registered whenever it holds that external resource or is paused (see the ExternalDatabaseConnection class for the definition of pause and resume); and 2) that the executors hold strong references only to handles, the state of the object, and parent objects. Participation: An application uses instances of several external database interface classes which have specific relationships according to their role. The relationships comprise a hierarchy where one or more instances of a class *lower* in the hierarchy are said to *participate* in the context defined by an instance of the class *above* them. For instance, a session is said to participate in a connection. Participation is recorded in a weak array that is the size of the number of participants. The array is weak to facilitate the automatic release of external resources when instances of the external database interface classes are no longer used. Instance variables: stateHolder <ValueHolder on: Symbol> Holds the current state. Legal states are defined by the subclasses. traceStream <WriteStream on: String> A private stream used for preparing complex trace entries. traceLevel <SmallInteger> The trace level, copied from the class side on instance creation. If zero, tracing is disabled. participants <WeakArray> Holds references to participating (subordinate) external database objects. Used to propogate operations downward when multiple objects must cooperate to provide a function. participantsSemaphore <RecursionLock> Used for mutual exclusion protection on uses of the participants array. Class variables: TraceLevel <SmallInteger> The current tracing level for the class. TraceCollector <nil | TextCollector | Stream> nil => do not output the trace. TraceSequencer <RecursionLock> Use for mutual exclusion to ensure that trace entries are not interleaved. Subclasses must implement the following messages instance protocol private-finalization key private-library calls acquireExternal dismissExternal class protocol accessing connectionClass private-registry registry: Notation: Assume: a pre-condition for a method. Enforce: a pre-condition that is enforced by raising an exception. Enforce-quietly: a pre-condition that is enforced and the method is a no-op. Assert: a condition that must be met in the middle of a method. Assure: a post-condition which is guaranteed on method completion.
</comment> <class> <name>ExternalDatabaseConnection</name> <environment>Database</environment> <super>Database.ExternalDatabaseFramework</super> <private>false</private> none transaction username password environment transactionCoordinator cachedSession isolationLevel environmentMap xif xifMap dependents <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseConnection
ExternalDatabaseConnection is the abstract class defining database connection services. The maximum number of active connections is controlled by the driver. All drivers are required to support coordinated transactions. If full atomic behavior is not available, it is simulated with a serial broadcast commit on each participating connection. A two-phase commit protocol would ensure true coordination for commits and rollbacks. Implementation Details: Participation relationships: An instance of the connection subclasses will participate in an instance of the transaction subclass. An instance of the session subclass will participate in an instance of the connection subclass. Inherited instance variables: stateHolder <ValueHolder on: (#new | #xactNo | #xactYes | #paused)> The state variable is used to track the legal operations on connections. traceStream <WriteStream on: String> A private stream used for preparing complex trace entries. traceLevel <SmallInteger> The trace level, copied from the class side on instance creation. If zero, tracing is disabled. participants <WeakArray of: ExternalDatabaseSession> The session instances that participate in the connection. participantsSemaphore <RecursionLock> Used for mutual exclusion protection of uses of the participants array. Instance variables: transaction <ExternalDatabaseTransaction | nil> Transaction that this connection is a part of. username <String | nil> Name of current user; driver will signal if required and == nil. password <String | nil> Password of current user; driver will signal if required and == nil. environment <String | nil> Logical or physical name for environment; driver will signal if required and == nil. transactionCoordinator <ValueHolder on: Boolean> Holds true if this connection is a transaction coordinator for other connections. cachedSession <nil | ExternalDatabaseSession> Holds onto a session for reuse by getSession. isolationLevel < Symbol | nil> Holds the isolationLevel for this connection. Class variables: DefaultConnection <Symbol | nil> Contains name of subclass to use when creating a new connection. DefaultEnvironment <String | nil> Contains logical environment to use as a default for connecting. StandardSignals <IdentityDictionary of: Signal> Maps signal names to signals. PlatformType <nil | Symbol> Platform/OS type that we're running on. Used to select an platform-specific ExternalInterface subclass. Class instance variables: environmentMap <Dictionary | nil> Each driver maintains a map of logical to physical environments. Subclasses must implement the following messages: instance protocol private-library calls acquireExternal: class protocol accessing sessionClass transactionClass kind activation pause resume private-accessing call private-activation install
</comment> <class> <name>TransactionException</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.TransactionException
TransactionException is used to indicate an error in transaction processing.
</comment> <class> <name>InvalidConnectionState</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.InvalidConnectionState
InvalidConnectionState is used to indicate that the application cannot use a function at a given time.
</comment> <class> <name>ConnectionProfile</name> <environment>Database</environment> <super>Core.Object</super> <private>false</private> none name driverClassName environment userName password originalName <imports></imports> <category>Database-Connection Dialog</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ConnectionProfile
An instances of ConnectionProfile is a set of database connection parameters. In other words, a profile represents future database connection(s). The difference between a profile and a connection is that a profile can be incomplete--for example have no connection type (driverClassName) set. It also has a human-readable name. ConnectionProfiles are mostly created and manipulated by ConnectionDialogs. Instance Variables: name <String | nil> A human-readable string of arbitrary format used by the UI to identify profiles. driverClassName <Symbol | nil> The name of the ExternalDatabaseConnection subclass to instantiate to create the connection. environment <String | nil> The connection environment string. userName <String | nil> The database user name. password <String | nil> The database user's password originalName <String | nil> A duplicate of the original value of <name>. The name may be reset to nil by a connection dialog while a profile is being modified, yet this saved value allows to remember the original name to save the profile afterwards.
</comment> <class> <name>CouldNotResolveServiceName</name> <environment>Database</environment> <super>Database.ConnectionException</super> <private>false</private> none <imports></imports> <category>Database</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.CouldNotResolveServiceName
CouldNotResolveServiceName is raised to indicate that the service (or TNS alias) specified when trying to connect does not exist.
</comment> <class> <name>TransactionPhase2Fatal</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.TransactionPhase2Fatal
TransactionPhase2Fatal is used to indicate a fatal error in the second phase of a two-phase commit or rollback. This usually means that manual recovery will be required to complete the transaction.
</comment> <class> <name>RequiredEnvironment</name> <environment>Database</environment> <super>Database.ExternalDatabaseResumableException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.RequiredEnvironment
RequiredEnvironment is used to report that the environment is a required parameter by this driver and no default was specified.
</comment> <class> <name>UnableToDisconnect</name> <environment>Database</environment> <super>Database.ExternalDatabaseResumableException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToDisconnect
UnableToDisconnect is used to indicate that an error occurred when trying to end the connection. This signal is proceedable.
</comment> <class> <name>RowIsReferencedError</name> <environment>Database</environment> <super>Database.UnableToExecuteSQL</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.RowIsReferencedError
RowIsReferencedError is used to indicate that a row may not be deleted nor the primary key changed because it is still referenced.
</comment> <class> <name>UnableToOpenCursor</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToOpenCursor
UnableToOpenCursor is used to indicate that a cursor could not be opened.
</comment> <class> <name>ExternalDatabaseError</name> <environment>Database</environment> <super>Core.Object</super> <private>false</private> none dbmsErrorCode dbmsErrorString osErrorCode osErrorString <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseError
An ExternalDatabaseError is returned as the parameter for exceptions raised by the External Database Interface to describe conditions reported by the dbms api in use. Other exceptions will have nil for the parameter value. The instance variables may all be nil to indicate that (in the current situation) there is no available/appropriate value for that field. Individual drivers may subclass if they have additional information to provide when errors occur. Instance Variables: dbmsErrorCode <SmallInteger | nil> The code provided by the dbms api. dbmsErrorString <String | nil> The string associated with the dbmsErrorCode. osErrorCode <SmallInteger | nil> The error code provided by the dbms api which is attributed to the underlying operating system. This is usually just detail information about the dbmsErrorCode. osErrorString <String | nil> The string associated with the osErrorCode.
</comment> <class> <name>TooManyActiveSessions</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.TooManyActiveSessions
TooManyActiveSessions is used to indicate that the connection already has the maximum number of active sessions.
</comment> <class> <name>UnableToFetchData</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToFetchData
UnableToFetchData is used to indicate that the row or rows could not be fetched.
</comment> <class> <name>ExternalDatabaseColumnDescription</name> <environment>Database</environment> <super>Core.Object</super> <private>false</private> none name index type length precision scale nullable <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseColumnDescription
Class ExternalDatabaseColumnDescription defines the common protocol for accessing meta-data about columns. The information available is limited by the database api library. If any of the properties of a column are unknown, a nil value is reported. Instance variables: name <String | nil> The name of the column. If the column is derived (in an answer set), the name may not be defined (nil) or an empty string. index <SmallInteger | nil> The ordinal position of the column in the answer set or in the table. type <Magnitude class | nil> The Smalltalk class which is used to hold data from the column. length <SmallInteger | nil> The number of bytes to represent the column. In some database api libraries, this is the maximum storage length. In others, it is the display length. If both are available, it is the maximum of the two. precision <SmallInteger | nil> The total number of digits in a decimal number. scale <SmallInteger | nil> The number of digits to the right of the decimal point. nullable <Boolean | nil> True implies that this column may hold null values.
</comment> <class> <name>UnableToCloseCursor</name> <environment>Database</environment> <super>Database.ExternalDatabaseResumableException</super> <private>false</private> none <imports></imports> <category>Database</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToCloseCursor
UnableToCloseCursor is used to indicate that the Oracle cursor could not be closed. This signal is proceedable.
</comment> <class> <name>UnableToCancelCursor</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToCancelCursor
UnableToCancelCursor is used to indicate that an Oracle cursor could not be canceled. This signal is not proceedable.
</comment> <class> <name>TooManyActiveTransactions</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.TooManyActiveTransactions
TooManyActiveTransactions is used to indicate that the driver for this connection already has the maximum number of active transactions.
</comment> <class> <name>ExternalDatabaseTransaction</name> <environment>Database</environment> <super>Database.ExternalDatabaseFramework</super> <private>false</private> none memberCountHolder remainingCountHolder <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseTransaction
Class ExternalDatabaseTransaction is a private abstract class used by the external database interface to manage transaction services on behalf of one or more connections. ExternalDatabaseTransaction reduces the differences between independent and coordinated (sometimes called distributed) database transaction styles. Independent transactions limit the unit of work to a single connection with a database. Coordinated transactions allow multiple concurrent connections to comprise the unit of work. For either independent or coordinated transactions, commiting or aborting all changes made during the unit of work should be atomic. ExternalDatabaseTransaction unifies these two transaction styles by allowing multiple connections (of the same driver) to be coordinated whether or not there is direct support from the underlying database system. A *two-phase commit* protocol is required to assure atomicity for the unit of work. When a two-phase commit protocol is not available, a less rigorous serial broadcast strategy is used. In this approach, each connection is asked to commit or rollback in turn. If there is a system or network failure before all have completed the work, it is possible that not all will perform the same action to complete the transaction. The application is responsible for recovery in the event that not all commits are completed. Implementation Considerations: Participation relationships: An instance of the connection subclasses will participate in an instance of the transaction subclass. Inherited instance variables: stateHolder <ValueHolder on: (#xactNo | #xactYes | #committing | #aborting | #paused)> The state variable is used to track the legal operations on transactions. traceStream <WriteStream on: String> A private stream used for preparing complex trace entries. traceLevel <SmallInteger> The trace level, copied from the class side on instance creation. If zero, tracing is disabled. participants <WeakArray of: ExternalDatabaseConnection> The connection instances that are coordinated via the transaction instance. participantsSemaphore <RecursionLock> Used for mutual exclusion protection on uses of the participants array. Instance variables: memberCountHolder <ValueHolder on: SmallInteger> A count of the number of connections that are members of the current transaction. remainingCountHolder <ValueHolder on: SmallInteger> A count of the number of connections that remain members of the current transaction. If this number is less than the number held in memberCount, we are in the #committed or #aborting states. This will persist until the last executor is heard from. Subclasses must implement the following messages instance protocol private-library calls beginExternal commitExternal rollbackExternal
</comment> <class> <name>UnableToQueryDriverInformation</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToQueryDriverInformation
UnableToQueryDriverInformation is used to indicate that driver information could not be queried.
</comment> <class> <name>UnsupportedCursorType</name> <environment>Database</environment> <super>Database.ExternalDatabaseResumableException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnsupportedCursorType
UnsupportedCursorType is used to indicate that an attempt was made to use an unsupported cursor type.
</comment> <class> <name>UnableToQueryHandleInformation</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToQueryHandleInformation
UnableToQueryHandleInformation is used to indicate that the handle information could not be queried.
</comment> <class> <name>DBProfileManager</name> <environment>Database</environment> <super>UI.ApplicationModel</super> <private>false</private> none profileListHolder connectedIcon <imports> private XML.XMLParser private XML.SAXWriter private XML.Document private XML.Element </imports> <category>Tools-Settings-VW</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.DBProfileManager
DBProfileManager is cloned from its Store counterpart, RepositoryManager, is the standalone application for managing database connections. It uses a dataset to list the known connections and allows one to manage connections, including saving to and loading from files. Instance Variables: connectedIcon <Image> The image used by the dataset to mark the currenly connected profile, if any. profileListHolder <SelectionInList> The model of the profile list.
</comment> <class> <name>DBProfileListSetting</name> <environment>Tools</environment> <super>Tools.GenericSettingDescriptor</super> <private>false</private> none profiles <imports> private Database.DBProfileManager private Database.ConnectionProfile </imports> <category>Tools-Settings-VW</category> <attributes> <package>Database</package> </attributes> </class> <comment> Tools.DBProfileListSetting
DBProfileListSetting is cloned from its Store counterpart, StoreRepositoryListSetting, holds the list of profiles. Instance Variables: profiles <ConnectionProfile> the list of profiles ownd by the DBProfileManager.
</comment> <class> <name>ExternalDatabaseTransactionError</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseTransactionError
ExternalDatabaseTransactionError is used to indicate an attempt to commit/rollback a database transaction failed.
</comment> <class> <name>AuthenticationFailure</name> <environment>Database</environment> <super>Database.ConnectionException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.AuthenticationFailure
AuthenticationFailure is raised when the server failed to authenticate the username and/or password
</comment> <class> <name>ObjectLocked</name> <environment>Database</environment> <super>Database.UnableToExecuteSQL</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ObjectLocked
ObjectLocked is used to indicate that an object is locked when attempting to change it in the database
</comment> <class> <name>UnableToBind</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToBind
UnableToBind is used to indicate that the input or output bind was unsuccessful.
</comment> <class> <name>MissingBindVariable</name> <environment>Database</environment> <super>Database.UnableToBind</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.MissingBindVariable
MissingBindVariable is used to indicate that a bind variable is missing.
</comment> <class> <name>ExternalDatabaseLibraryInaccessible</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseLibraryInaccessible
ExternalDatabaseLibraryInaccessible is used to indicate that a driver is not able to access the database library. Either the OE does not contain the database library or it cannot be found in the search path for dynamic link libraries.
</comment> <class> <name>DBProfilePropertiesDialog</name> <environment>Tools</environment> <super>UI.SimpleDialog</super> <private>false</private> none profileHolder acceptTrigger databaseListHolder databaseHolder environmentHolder userNameHolder passwordHolder nameHolder <imports></imports> <category>Tools-Settings-VW</category> <attributes> <package>Database</package> </attributes> </class> <comment> Tools.DBProfilePropertiesDialog
DBProfilePropertiesDialog is a clone of the Store RepositoryPropertiesDialog, and is used by DBProfileManager to edit properties of individual database connections. Most of the instance variables hold aspects of the dialog's widgets. The aspects are buffered value holders on aspect adaptors on the contents of 'profileHolder' variable. Instance Variables: acceptTrigger <ValueHolder with: Boolean> Trigger channel of the buffered value databaseHolder <BufferedValueHolder> databaseListHolder <List> environmentHolder <BufferedValueHolder> nameHolder <BufferedValueHolder> passwordHolder <BufferedValueHolder> profileHolder <ValueHolder> Holds the profile whose properties are being edited. userNameHolder <BufferedValueHolder>
</comment> <class> <name>NoDefaultConnection</name> <environment>Database</environment> <super>Database.ExternalDatabaseResumableException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.NoDefaultConnection
NoDefaultConnection is used to report that ExternalDatabaseConnection doesn't know which Connection to use for a new connection.
</comment> <class> <name>InvalidParameterMarker</name> <environment>Database</environment> <super>Database.DynamicSQLError</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.InvalidParameterMarker
InvalidParameterMarker is used to indicate that the parameter marker is incorrect.
</comment> <class> <name>UnsupportedIsolationLevel</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnsupportedIsolationLevel
UnsupportedIsolationLevel is used to indicate that an attempt was made to set an unsupported isolation level.
</comment> <class> <name>ByteFieldDescriptor</name> <environment>Database</environment> <super>Core.Object</super> <private>false</private> none template max isLongType <imports></imports> <category>Database-Support</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ByteFieldDescriptor
Instances of ByteFieldDescriptor describe variable-length data fields. Used by protocol private to the ObjectLens. Instance Variables: template <Object> a template object describing the class of values in the field max <SmallInteger> the maximum size of objects in the field
</comment> <class> <name>UnableToDestroyConnectionPool</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <class> <name>UnableToDescribe</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.UnableToDescribe
UnableToDescribe is used to indicate that description of a input variable or an output column could not be acquired.
</comment> <class> <name>ConnectionDialog</name> <environment>Database</environment> <super>UI.SimpleDialog</super> <private>false</private> none connectionProfileListHolder connectionProfileHolder databaseListHolder databaseHolder environmentListHolder environmentHolder userNameListHolder userNameHolder passwordHolder currentProfileHolder lastUsedProfile <imports></imports> <category>Database-Connection Dialog</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ConnectionDialog
This is the dialog used to set parameters of a database connection. The dialog also allows to save often used sets of parameters as profiles that can be selected with a single click. The primary access point is the messages under the 'utilities' protocol on the class side: chooseProfile which former opens the dialog and answers an instance of ConnectionProfile with the settings selected by the user. If the dialog has been cancelled, the answer is nil. The client code is then responsible for connecting to the database and handling possible errors, however the dialog class can help with that if all that is required is to attempt a connection and display a message box in case of an error. See the class-side method connect: This very simple pattern of using the dialog is illustrated by two methods under the 'examples' protocol on the class side. Instance Variables: connectionProfileListHolder <ValueHolder with: <List of: String>> This and most of the following variables hold various aspects of the dialog interface. connectionProfileHolder <ValueHolder with: String> databaseListHolder <ValueHolder with: <List of: Symbol>> databaseHolder <AspectAdaptor> environmentListHolder <ValueHolder with: <List of: String>> environmentHolder <AspectAdaptor> userNameListHolder <ValueHolder with: <List of: String>> userNameHolder <AspectAdaptor> passwordHolder <AspectAdaptor> currentProfileHolder <ValueHolder with: ConnectionProfile> A value holder with the "working copy" of a ConnectionProfile. It is a subject channel of some of the aspects above, which are aspects adaptors. Class instance Variables: lastUsedProfile <ConnectionProfile> The connection profile most recently accepted by the user.
</comment> <class> <name>DBProfileListPage</name> <environment>Tools</environment> <super>Tools.SettingsManagerPage</super> <private>false</private> none setting profileManager profileListHolder profileHolder <imports> private Database.ConnectionDialog private Database.ConnectionProfile </imports> <category>Tools-Settings-VW</category> <attributes> <package>Database</package> </attributes> </class> <comment> Tools.DBProfileListPage
DBProfileListPage is cloned from its Store counterpart, StoreRepositoryListPage, and used with the settings tools to maintain the list of database connections (or profiles). Instance Variables: profileHolder <ConncetionProfile> holds the current profile. profileListHolder <SelectionInList> holds the list of profiles. profileManager <DBProfileManager> holds, saves and loads the profiles. setting <DBProfileListSetting> related to the settings tool.
</comment> <class> <name>RequiredUsername</name> <environment>Database</environment> <super>Database.ExternalDatabaseResumableException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.RequiredUsername
RequiredUsername is used to indicate that a username is required in order to connect. This signal is proceedable and expects a username string as the proceedWith: value.
</comment> <class> <name>ExternalDatabaseSession</name> <environment>Database</environment> <super>Database.ExternalDatabaseFramework</super> <private>false</private> none connection query queryFragments bindInput bindTemplate bindOutput useNamedOutputBinding bindValues resultTemplate allocateForEachRow blockFactor numColumns columnDescriptions rowAdaptors rowBuffersHolder bufferIndex answerStream currentRow scrollable <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseSession
ExternalDatabaseSession is the abstract class defining the application interface to executing prepared SQL statements or stored procedures, describing the results of the execution, and acquiring streams of results. Inherited instance variables: stateHolder <ValueHolder on: (#new | #connected | #prepared | #executing | #ready | #validResults | #fetchingData | #paused)> The state variable is used to track the legal operations on sessions. traceStream <WriteStream on: String> A private stream used for preparing complex trace entries. traceLevel <SmallInteger> The trace level, copied from the class side on instance creation. If zero, tracing is disabled. participants <WeakArray of: ExternalDatabaseAnswerStream> The answer stream instance that participates in this session. There will never be more than one. participantsSemaphore <RecursionLock> Used for mutual exclusion protection of uses of the participants array. Instance variables: connection <ExternalDatabaseConnection> The connection context in which this session executes SQL statements or stored procedures. query <String> The SQL query provided by the client. queryFragments <Collection of: (String | SmallInteger | Symbol)> The query, canonized for parameter binding. bindInput <Object | nil> The object to obtain bind values from, if any are required. bindOutput <Object | nil> The bind object to use for output rows. If nil, output rows are instances of Array. bindValues <IdentityDictionary> A private dictionary, keyed by bind position, of values bound to parameters. Used to avoid unneccessary rebinds. useNamedOutputBinding <Boolean> Determines if the output bind object should be populated by sending it mutators fashined from the column names. The default is populate the bind object by directly indexing its instance variables. allocateForEachRow <Boolean> When true (the default), the answer stream will create a copy of the output bind object for each row. When false, the answer stream will use the same bind object repeatedly. blockFactor <SmallInteger> The number of rows to fetch in a block from the dbms server. currentRow <Object | nil> The session's bindOutput object or an appropriate Array (i.e. with the right number of cells to match the number of columns). The adaptors used to insert values into the appropriate repository for each column are given a copy of this or use it directly if allocateForEachRow is false. numColumns <SmallInteger> The number of columns in the answer set. columnDescriptions <(Array of: ExternalDatabaseColumnDescription) | nil> Array containing a description of each column in the answer set. rowAdaptors <Array of: BlockClosure> A block for each column of the output. Each block takes two arguments (subject and value) and is responsible for inserting the value into the instance or indexed variable of the subject. rowBuffersHolder <ValueHolder on: (Array of: (ExternalDatabaseBuffer | Array))> Each driver will need space to store the data as it is returned from the dbms api. For systems which do not fetch rows directly into predeclared buffer, it is still important to allocate these buffers once to avoid the overhead of constantly allocating and deallocating space. answerStream <ExternalDatabaseAnswerStream | nil> A reference to the active answer stream. scrollable <Boolean> Determines whether the cursor is scrollable. bindTemplate <Object> Private variable for Object Lens use. resultTemplate <Object> Private variable for Object Lens use. bufferIndex <SmallInteger> Private variable for Object Lens use. Subclasses must implement the following messages instance protocol data processing rowCount private-answer set advanceExternal allocateRowBufferExternal: getColumnDescriptionExternal: hasAnswerSetExternal getFieldExternal: cancelAnswerSetExternal private-execution executeExternal readyExternal resultsExternal moreResultsExternal cancelExternal private-binding prepareExternal bindValue:at: schema access listTablesLike: describeColumns: private-ObjectLens bindInput:template:to: flattenResultTemplate:onto: nextViaTemplate:
</comment> <class> <name>ExternalDatabaseAnswerStream</name> <environment>Database</environment> <super>Core.Stream</super> <private>false</private> none session nextRow <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseAnswerStream
ExternalDatabaseAnswerStream is the class for receiving rows returned from an SQL select statement or stored procedure. Implementation Details: ExternalDatabaseAnswerStream is a subclass of Stream since it is not practical to transparently support the skip functionality of PeekableStream and it does not have a collection as is assumed by PositionableStream. Instance Variables: session <ExternalDatabaseSession | nil> Holds the reference to the parent of the answer stream, or nil if the answer stream is no longer connected (as will happen at end-of-stream). nextRow <Object | nil> Caches the next object to be returned. The object will be an instance of the bindOutput object, if one was provided, otherwise it will be an instance of Array.
</comment> <class> <name>ConnectionNotOpen</name> <environment>Database</environment> <super>Database.ConnectionException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ConnectionNotOpen
ConnectionNotOpen is raised to indicate that the connection does not have a connection to the SQL-environment.
</comment> <class> <name>ExternalDatabaseBuffer</name> <environment>Database</environment> <super>Core.Object</super> <private>false</private> none databaseType encoding elementSize count bufferPointer <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <comment> Database.ExternalDatabaseBuffer
ExternalDatabaseBuffer is a private, abstract class used by ExternalDatabaseSession to represent and manage an external database buffer, and to translate between a limited set of Smalltalk objects and their external database specific representation in the buffer. Subclasses extend ExternalDatabaseBuffer to deal with particular databases. Instance variables: databaseType <Object> The type of data that the buffer will contain. The interpretation of this is subclass dependent. encoding <Symbol> The encoding that Strings will be subjected to. elementSize <SmallInteger> The maximum length of a single data item. count <SmallInteger> The cardinality of (number of item slots in) the buffer. A count of zero indicates that the buffer will hold a scalar value. bufferPointer <nil | CPointer> When allocated, the CPointer that "holds" the buffer. Subclasses must implement the following messages instance protocol accessing at: at:put:
</comment> <class> <name>UnableToSetEnvironmentAttribute</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <class> <name>UnableToCreateConnectionPool</name> <environment>Database</environment> <super>Database.ExternalDatabaseException</super> <private>false</private> none <imports></imports> <category>Database-Interface</category> <attributes> <package>Database</package> </attributes> </class> <name>Profiles</name> <environment>Database.DBProfileManager</environment> <private>false</private> <constant>false</constant> <category>profiles</category> <initializer>List new</initializer> <attributes> <package>Database</package> </attributes> <name>PlatformType</name> <environment>Database.ExternalDatabaseConnection</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Database</package> </attributes> <name>DefaultConnection</name> <environment>Database.ExternalDatabaseConnection</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Database</package> </attributes> <name>StandardSignals</name> <environment>Database.ExternalDatabaseConnection</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Database</package> </attributes> <name>DefaultEnvironment</name> <environment>Database.ExternalDatabaseConnection</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Database</package> </attributes> <name>LastUsedProfile</name> <environment>Database.ConnectionDialog</environment> <private>false</private> <constant>false</constant> <category>profiles</category> <initializer>nil</initializer> <attributes> <package>Database</package> </attributes> <name>Profiles</name> <environment>Database.ConnectionDialog</environment> <private>false</private> <constant>false</constant> <category>profiles</category> <initializer>OrderedCollection new</initializer> <attributes> <package>Database</package> </attributes> <name>TraceLevel</name> <environment>Database.ExternalDatabaseFramework</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Database</package> </attributes> <name>TraceSequencer</name> <environment>Database.ExternalDatabaseFramework</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Database</package> </attributes> <name>TraceCollector</name> <environment>Database.ExternalDatabaseFramework</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Database</package> </attributes> <methods> Database.AdHocQueryTool <category>initialize-release</category>
initialize self queryModel onChangeSend: #changedQuery to: self. self tableModel columnLabelsArray: #(). self blockFactor: 1. self connectedStatusHolder onChangeSend: #connectedStatusChanged to: self. self executeStatusHolder onChangeSend: #executeStatusChanged to: self. self moreAnswersStatusHolder onChangeSend: #moreAnswersStatusChanged to: self.
</methods> <methods> Database.AdHocQueryTool <category>accessing</category>
blockFactor ^self blockFactorModel value
blockFactor: anInteger self blockFactorModel value: (anInteger > 1 ifTrue: [anInteger] ifFalse: [ 1 ])
environment ^profile environment
password ^profile password
query ^self queryModel value
username ^profile userName
whichDriver ^profile driverClassName
</methods> <methods> Database.AdHocQueryTool <category>actions</category>
changedQuery connection notNil ifTrue: [ self executeStatusHolder value: self query isEmpty not ]
connect profile := Database.ConnectionDialog chooseProfile. connection := profile isNil ifTrue: [nil] ifFalse: [Database.ConnectionDialog connect: profile]. connection ifNil: [session := nil] ifNotNil: [connection password: profile password. session := connection getSession]. self connectedStatusHolder value: connection notNil
disconnect Cursor database showWhile: [connection disconnect]. session := nil. connection := nil. self connectedStatusHolder value: false
execute | discardSession | discardSession := false. Cursor database showWhile: [ [session isNil ifTrue: [session := connection getSession connect]. session prepare: self query asString. session blockFactor: self blockFactor. session execute. answerStream := session answer. self nextAnswer] on: connection class externalDatabaseErrorSignal do: [:exception | self reportError: (self messageFor: exception). discardSession := true. exception return]]. discardSession ifTrue: [session notNil ifTrue: [session disconnect]]
fetchBuffers | saveBlockFactor spec dialog | saveBlockFactor := self blockFactor. "Raise dialog." spec := self class interfaceSpecFor: #buffersSpec. dialog := SimpleDialog new. dialog builder source: self. dialog parentView: builder window. dialog allButOpenFrom: spec. dialog builder openDialog. "Restore original value?" (dialog accept value) ifFalse: [ self blockFactor: saveBlockFactor ]
nextAnswer | cols list | cols := Array new: 0. list := Array new: 0. answerStream == #noMoreAnswers ifFalse: [ answerStream == #noAnswerStream ifFalse: [ cols := answerStream columnDescriptions. list := answerStream upToEnd ]. self updateTable: list column: cols. (answerStream := session answer) == #noMoreAnswers ifTrue: [ self moreAnswersStatusHolder value: false. session disconnect. session := nil ] ifFalse: [ self moreAnswersStatusHolder value: true ] ].
</methods> <methods> Database.AdHocQueryTool <category>aspects</category>
blockFactorModel "This method was generated by UIDefiner. The initialization provided below may have been preempted by an initialize method." ^blockFactorModel isNil ifTrue: [blockFactorModel := 0 asValue] ifFalse: [blockFactorModel]
connectedStatusHolder ^connectedStatusHolder isNil ifTrue: [connectedStatusHolder := false asValue] ifFalse: [connectedStatusHolder]
executeStatusHolder ^executeStatusHolder isNil ifTrue: [executeStatusHolder := false asValue] ifFalse: [executeStatusHolder]
moreAnswersStatusHolder ^moreAnswersStatusHolder isNil ifTrue: [moreAnswersStatusHolder := false asValue] ifFalse: [moreAnswersStatusHolder]
queryModel "This method was generated by UIDefiner. The initialization provided below may have been preempted by an initialize method." ^queryModel isNil ifTrue: [queryModel := String new asValue] ifFalse: [queryModel]
tableModel "This method was generated by UIDefiner. The initialization provided below may have been preempted by an initialize method." ^tableModel isNil ifTrue: [tableModel := TableInterface new selectionInTable: SelectionInTable new] ifFalse: [tableModel]
</methods> <methods> Database.AdHocQueryTool <category>interface opening</category>
postOpenWith: aBuilder "This message is sent by the builder after it has opened a completed window." "The disconnect, execute, and next answer buttons are enabled under program control." | menuBar | "We want to notice any character typed into the query so that an accept isn't required." (aBuilder componentAt: #query) widget controller continuousAccept: true. "Arrange for the menu items to be enabled correctly." menuBar := aBuilder menuAt: #menuBar. (menuBar atNameKey: #connect) enabled: [self connectedStatusHolder value not]. (menuBar atNameKey: #disconnect) enabled: self connectedStatusHolder. (menuBar atNameKey: #execute) enabled: self executeStatusHolder. (menuBar atNameKey: #nextAnswer) enabled: self moreAnswersStatusHolder
</methods> <methods> Database.AdHocQueryTool <category>private</category>
connectedStatusChanged | connected | connected := self connectedStatusHolder value. (builder componentAt: #connect) isEnabled: connected not. (builder componentAt: #disconnect) isEnabled: connected. connected ifTrue: [ self query isEmpty ifFalse: [ self executeStatusHolder value: true ] ] ifFalse: [ self executeStatusHolder value: false. self moreAnswersStatusHolder value: false ]
executeStatusChanged (builder componentAt: #execute) isEnabled: self executeStatusHolder value
messageFor: exception | errs msg | exception == connection class authenticationFailureSignal ifTrue: [ ^exception errorString ]. ( (errs := exception parameter) notNil and: [ errs isEmpty not and: [ (msg := (exception parameter at: 1) dbmsErrorString) notNil and: [ msg isEmpty not ] ] ] ) ifTrue: [ ^msg ] ifFalse: [ ^exception errorString ]
moreAnswersStatusChanged (builder componentAt: #nextAnswer) isEnabled: self moreAnswersStatusHolder value
reportError: errorText | spec dialog | "Raise dialog." spec := self class interfaceSpecFor: #reportErrorSpec. dialog := SimpleDialog new. dialog builder source: self. dialog builder aspectAt: #errorText put: errorText asValue. dialog parentView: builder window. dialog allButOpenFrom: spec. dialog builder window label: (#errDatabaseError << #database >> 'Database Error'). (dialog builder componentAt: #errorText) widget controller keyboardHook: [:ev :ctrlr | nil ]. "Deny type-in, but allow menu for copy" dialog builder openDialog
updateTable: list column: descrs | table colAdaptors tableAdaptor colNames colWidths col mwidth width | table := self tableModel. colAdaptors := RowAdaptor adaptForIndexes: (1 to: descrs size). tableAdaptor := TableAdaptor on: list adaptors: colAdaptors. colNames := List new. colWidths := List new. mwidth := 'm' asComposedText width. "I.e. width of representative character" 1 to: descrs size do: [ :index | col := descrs at: index. colNames add: col name. width := 36 max: (col name asComposedText width + 1). width := width max: ((mwidth * col maxColumnConstraint asInteger) min: (3 * 72)). colWidths add: width ]. descrs size > 0 ifTrue: [ table columnWidths: colWidths. table columnLabelsArray: colNames ]. table columnLabelsFormats: #left. table selectionInTable table: tableAdaptor
</methods> <methods> Database.AdHocQueryTool <category>events</category>
noticeOfWindowClose: aWindow "The ApplicationWindow aWindow is in the process of closing. Disconnect from the database if needed." connection notNil ifTrue: [ self disconnect ]
</methods> <methods> Database.ExternalDatabaseResumableException class <category>testing</category>
mayResume ^true
</methods> <methods> Database.ExternalDatabaseFramework <category>initialize-release</category>
initialize "Establish initial value for instance variables." "Subclasses which override must include super initialize." traceLevel := TraceLevel. self stateHolder: nil asValue. self initializeParticipants
install "Perform all processing relevant for just returning from a snapshot." "Assume: reciever is registered." self installExternal. self participantsDo: [ :each | each installExternal ]
</methods> <methods> Database.ExternalDatabaseFramework <category>printing</category>
printOn: aStream "Append to the argument aStream a sequence of characters that identifies the receiver." super printOn: aStream. self isExecutor ifTrue: [ aStream nextPut: $' ]
</methods> <methods> Database.ExternalDatabaseFramework <category>private-accessing</category>
state "Answer with the current state of the External Database object." ^stateHolder value
state: aSymbol "Set the current state of the External Database object." stateHolder setValue: aSymbol
stateHolder: aValueHolder "Initialize the holder of state information." stateHolder := aValueHolder
traceLevel ^traceLevel
traceLevel: anInteger traceLevel := anInteger
</methods> <methods> Database.ExternalDatabaseFramework <category>private-activation</category>
activate "Time to revive all connections to external resources." "Assume: receiver is registered." "Enforce-quietly: receiver is paused." self state == #paused ifFalse: [ ^self ]. self acquireExternal notNil ifTrue: [ self class register: self ] ifFalse: [ self class unregister: self ]. self participantsDo: [ :each | each activate ]
dismiss "Time to release any external resources." "Assume: receiver is registered." self class unregister: self. "Avoid duplication of resource release." self state == #paused ifFalse: [ self dismissExternal ]
quiesce "Time to quiesce all connections to external resources." "Assume: receiver is registered." "Enforce-quietly: receiver is not paused." self state == #paused ifTrue: [ ^self ]. [ self participantsDo: [ :each | each quiesce ]. self dismissExternal ] ensure: [ self state: #paused ]
</methods> <methods> Database.ExternalDatabaseFramework <category>private-finalization</category>
executor "Answer with the executor." "Subclassess which want to override to add information to the executor should use super executor to create the executor initially." | ex | "Make a new instance, but all the initialization will happen as part of the executor methods." ex := self class basicNew. "The state machine must be exposed to the executor." ex stateHolder: stateHolder. "The executor retains the ability to trace" ex traceLevel: traceLevel. ^ex
finalize "Release all external resource." "Enforce-quietly: receiver is not paused." self state == #paused ifTrue: [^self]. self initializeParticipants. "It's not necessary to report errors at this time." [self finalizeExternal] on: self class connectionClass externalDatabaseErrorSignal do: [:ex | ex return]
finalizeExternal "Release all external resources." ( traceLevel >= 1 ) ifTrue: [ self class trace: nil ]. self dismissExternal
key "Key value to use when inserting receiver into a handle registry. This value needs to be unique within the registry." ^self subclassResponsibility
</methods> <methods> Database.ExternalDatabaseFramework <category>private-library calls</category>
acquireExternal "Acquire the external resources. If the external resources cannot be acquired, an exception is raised." ^self subclassResponsibility
dismissExternal "Release the external resources." "All activity within this method must function with only the instance variables defined in the executor object." ^self subclassResponsibility
installExternal "Perform return from snapshot processing." "Subclasses that override should invoke super installExternal." self state: #paused "Assure: no dangling CPointers remain."
</methods> <methods> Database.ExternalDatabaseFramework <category>private-participation</category>
addParticipant: aParticipant "Add aParticipant to the collection of participants in receiver's scope. A new participant is added to the collection if it is not already present." | p new | participantsSemaphore critical: [ "Check for and return immediately if already a particpant." ((p := self participants) includes: aParticipant) ifTrue: [ ^self ]. new := p class withAll: (p copyWith: aParticipant). p become: new ] "This method of growing the participants gives the exact same kind of collection. This is necessary because WeakArray>>copyWith: does not answer another WeakArray."
initializeParticipants "Initialize the instance variables which define the participation mechanism." participants := WeakArray new: 0. participantsSemaphore := RecursionLock new. participants addDependent: self
participants "Answer with the collection of participants. The participants collection should always be accessed in a critical section controlled with the participantsSemaphore." ^participants
participantsDetect: aBlock ifNone: exceptionBlock "Evaluate aBlock with each of the receiver's elements as the argument. Answer the first element for which aBlock evaluates to true." "Since the participants are a WeakArray, we also need to skip over 0 values (the death of a participant will leave a 0)." ^participantsSemaphore critical: [ (self participants copy) detect: [ :each | (each == 0 or: [ each isExecutor ]) ifTrue: [ false ] ifFalse: [ aBlock value: each ] ] ifNone: exceptionBlock ]
participantsDo: aBlock "Invoke aBlock for each participant." "Since the participants are a WeakArray, we also need to skip over 0 values (the death of a participant will leave a 0)." participantsSemaphore critical: [ (self participants copy) do: [ :each | (each == 0 or: [ each isExecutor ]) ifFalse: [ aBlock value: each ] ] ]
participantsSize "Answer the size of the participants array." "Since the participants are a WeakArray, we also need to skip over 0 values (the death of a participant will leave a 0)." | total | participantsSemaphore critical: [ total := self participants inject: 0 into: [:subTotal :next | next == 0 ifTrue: [ subTotal ] ifFalse: [ subTotal + 1] ] ]. ^total
removeParticipant: aParticipant "Remove aParticipant from the collection of participants in receiver's scope." | p | participantsSemaphore critical: [ ((p := self participants) includes: aParticipant) ifFalse: [ ^self ]. p become: (p class withAll: (p copyWithout: aParticipant)) ] "This method of shrinking the participants gives the exact same kind of collection. This is necessary because WeakArray>>copyWithout: does not answer another WeakArray."
</methods> <methods> Database.ExternalDatabaseFramework <category>private-testing</category>
isExecutor "Answer true if the receiver is really an executor, not the primary object." ^self participants isNil
</methods> <methods> Database.ExternalDatabaseFramework <category>private-tracing</category>
emitTrace "Answer the receiver's trace buffer contents. Reset the trace stream to be empty." | trace | trace := traceStream contents. traceStream reset. ^trace
traceStream "Answer the receiver's trace stream. Create the stream if necessary." ^traceStream isNil ifTrue: [ traceStream := (String new: 64) writeStream ] ifFalse: [ traceStream ]
</methods> <methods> Database.ExternalDatabaseFramework <category>private-updating</category>
update: anAspectSymbol with: aParameter from: aSender "Receive a change notice from an object, denoted by aSender, of whom the receiver is a dependent. The argument anAspectSymbol is typically a Symbol that indicates what change has occurred and aParameter is additional information." | p | (anAspectSymbol == #ElementExpired and: [aSender == self participants]) ifTrue: [ participantsSemaphore critical: [ (p := self participants) become: (p class withAll: (p copyWithout: 0)) ] ]
</methods> <methods> Database.ExternalDatabaseFramework class <category>class initialization</category>
initialize "Establish class variables." "ExternalDatabaseFramework initialize" TraceLevel := 0. TraceSequencer := RecursionLock new.
</methods> <methods> Database.ExternalDatabaseFramework class <category>accessing</category>
connectionClass "Answer the class to use for connection objects associated with receiver." ^self subclassResponsibility
</methods> <methods> Database.ExternalDatabaseFramework class <category>tracing</category>
shouldTrace: level "Answer true if tracing is enabled through level." ^self traceLevel >= level
trace: aStringOrNil "Emit the standard trace header followed by aString (if not nil) into the trace log." | header when sender depth | TraceCollector == nil ifTrue: [ ^self ]. header := WriteStream on: (String new: 64). when := Time dateAndTimeNow. sender := thisContext sender. depth := TraceLevel > 4 ifTrue: [ TraceLevel - 4 ] ifFalse: [ 1 ]. "Emit a timestamp" header nextPutAll: '{'; "print: (when at: 1);" nextPutAll: ((when at: 1) printFormat: #(1 2 3 $ 2 2)); nextPutAll: ' '; print: (when at: 2); nextPutAll: '} '. "curly-brace, space and a tab" "Emit a stack trace" [ depth > 0 ] whileTrue: [ header nextPutAll: sender mclass printString; nextPutAll: '>>'; nextPutAll: sender selector asString. sender := sender sender. (depth := depth - 1) > 0 ifTrue: [ header cr; tab: 6 ] ]. TraceSequencer critical: [ TraceCollector nextPutAll: header contents; cr. ( aStringOrNil size > 0 ) ifTrue: [ TraceCollector tab; nextPutAll: aStringOrNil; cr ]. TraceCollector flush ]
traceLevel "Answer the level of tracing that is enabled for this class." TraceLevel isNil ifTrue: [ TraceLevel := 0 ]. ^TraceLevel
</methods> <methods> Database.ExternalDatabaseFramework class <category>private-activation</category>
activate "Resume operation on suspended database connections." "Each of the driver classes whose instances hold external resources must maintain a registry of active and inactive instances so that all such resources may be released at appropriate times. As each member of the collection is activated it should reregister." | registry | (registry := self registry) isNil ifTrue: [ ^self shouldNotImplement ]. registry do: [ :each | each state == #paused ifTrue: [ each activate ] ]
quiesce "Suspend operation on active database connections." "Each of the driver classes whose instances hold external resources must maintain a registry of active and inactive instances so that all such resources may be released at appropriate times. As each member of the collection is activated it should reregister." | registry | (registry := self registry) isNil ifTrue: [ ^self shouldNotImplement ]. registry do: [ :each | each state == #paused ifFalse: [ each quiesce ] ]
returnFromSnapshot "No external resources can be held at this point. Reset all appropriate control information as if operation had been paused." | registry | ( TraceLevel >= 1 ) ifTrue: [ self trace: nil ]. (registry := self registry) isNil ifTrue: [ ^self shouldNotImplement ]. registry do: [ :each | each install ]
</methods> <methods> Database.ExternalDatabaseFramework class <category>private-registry</category>
initRegistry "Initialize the registry to the proper form of collection." self registry: HandleRegistry new.
register: sender "Register the sender." | registry | ^(registry := self registry) notNil ifTrue: [ registry register: sender ]
registry "Answer with the registry." "Subclasses must override if they have registries." ^nil
registry: aCollection "Record aCollection as the registry." ^self subclassResponsibility
unregister: uh "Remove the argument from the active registry." | registry | (registry := self registry) isNil ifFalse: [registry unregister: uh]
</methods> <methods> Database.ExternalDatabaseConnection <category>initialize-release</category>
initialize "Establish initial value for instance variables." "Subclasses which override must include super initialize." super initialize. self state: #new. transaction := nil. self transactionCoordinator: false asValue.
</methods> <methods> Database.ExternalDatabaseConnection <category>accessing</category>
environment "Answer the environment to use when connecting to the SQL-environment." ^environment
environment: aString "Set the environment to use when connecting to the SQL-environment. An empty string should be used to specify the 'default' environment. If the environment is nil, the driver will raise a proceedable exception (requiredEnvironmentSignal on a connection class) when connecting." environment := aString
password "Answer the password to use when connecting to the SQL-environment." ^password
password: aString "Set the password to use when connecting to the SQL-environment. Passwords are not required by all database systems (or on all platforms). An empty string should be used for the no-password case. If the password is nil, the driver will raise a proceedable exception (requiredPasswordSignal on a connection class) when connecting." password := aString
username "Answer the username to use when connecting to the SQL-environment." ^username
username: aString "Set the username to use when connecting to the SQL-environment. An empty string should be used to connect as the default user unless the driver requires something else. If the username is nil, the driver will raise a proceedable exception (requiredUsernameSignal on a connection class) when connecting." username := aString
</methods> <methods> Database.ExternalDatabaseConnection <category>connections</category>
connect "Establish connection with SQL-environment ." self connect: self password.
connect: aPassword "Establish connection with SQL-environment using the supplied password." "Enforce: external resources not held." self isConnected ifTrue: [ ^self class invalidConnectionStateSignal raise ]. ( traceLevel >= 1 ) ifTrue: [ (self traceStream) nextPutAll: (#Version << #database >> 'Version: ') asString; nextPutAll: self class version. self class trace: self emitTrace ]. self acquireTransaction. self acquire: aPassword. self state: #xactNo
disconnect "Terminate connection with SQL-environment. An outstanding transaction (if any) is aborted." ( self state == #new ) ifTrue: [ ^self ]. cachedSession := nil. self inTransactionMode ifTrue: [ self rollback ]. self participantsDo: [ :each | each disconnect ]. self dismiss. self dismissTransaction. self state: #new
getSession "Answer an instance of the driver's subclass of ExternalDatabaseSession." self isConnected ifFalse: [ self class connectionNotOpenSignal raise ]. ^cachedSession notNil ifTrue: [ | session | session := cachedSession. cachedSession := nil. session ] ifFalse: [ self class sessionClass newForConnection: self ]
prepare: aString "Answer an instance of the driver's subclass of ExternalDatabaseSession and prepare the SQL text in aString for processing. The number of active sessions is driver-dependent." ^self getSession prepare: aString
</methods> <methods> Database.ExternalDatabaseConnection <category>testing</category>
inTransactionMode "Answer true if a multi-statement transaction has been started." | xact | ^(xact := self transaction) isNil ifTrue: [ false ] ifFalse: [ xact inTransactionMode ]
isConnected "Answer whether receiver is connected to database." | stateTemp | ^((stateTemp := self state) == #new or: [ stateTemp == #paused ]) not
isTransactionCoordinator "Answer true if this connection has been designated as the coordinator for a multiple connection transaction." ^self transactionCoordinator value
</methods> <methods> Database.ExternalDatabaseConnection <category>transactions</category>
begin "Mark the beginning of a multi-statement transaction. This is necessary if the transaction needs to include more than one statement in the transaction." self inTransactionMode ifTrue: [ ^self class invalidTransactionStateSignal raise ]. self transaction begin
beTransactionCoordinator "Designate this connection as the commit coordinator for a collection of connections. Connections must be desginated as commit coordinators before they connect." self state == #new ifFalse: [ self class invalidTransactionStateSignal raise ]. self transactionCoordinator value: true. self acquireTransaction
commit "Commit all database changes made during the current multi-statement transaction." self inTransactionMode ifTrue: [ self transaction commit ]
rollback "Rollback all database changes made during the current multi-statement transaction." self inTransactionMode ifTrue: [ self transaction rollback ]
transactionCoordinatorFor: aConnection "Designate this connection as the commit coordinator for aConnection. If the receiver is not currently a transaction coordinator and is not connected, it will be designated as such. aConnection must not be connected." "Become a transaction coordinator if not already." self state == #new ifTrue: [ self isTransactionCoordinator ifFalse: [ self beTransactionCoordinator ] ] ifFalse: [ self isTransactionCoordinator ifFalse: [ self class invalidTransactionStateSignal raise ] ]. "Enforce: aConnection isn't a transaction coordinator and is not connected." (aConnection isConnected or: [aConnection isTransactionCoordinator]) ifTrue: [ self class invalidTransactionStateSignal raise ]. "aConnection assumes receiver's transaction." aConnection useTransaction: self transaction
</methods> <methods> Database.ExternalDatabaseConnection <category>private-accessing</category>
encoding ^#default
isolationLevel "Answer the current isolation level." ^isolationLevel
isolationLevel: anIsolationLevel "Set the current isolation level." self subclassResponsibility.
platformType "Answer the current platform type" ^self class platformType
transaction "Answer the transaction for commit/rollback coordination." ^transaction
transaction: aTransaction "Set the transaction for commit/rollback coordination." transaction := aTransaction
transactionCoordinator ^transactionCoordinator
transactionCoordinator: anExternalDatabaseValueHolder transactionCoordinator := anExternalDatabaseValueHolder
</methods> <methods> Database.ExternalDatabaseConnection <category>private-activation</category>
acquire: aPassword "Time to acquire any external resources." (self acquireExternal: aPassword) notNil ifTrue: [ self class register: self ]
acquireTransaction "If we don't have a transaction object, arrange for one." self transaction isNil ifTrue: [ self useTransaction: self class transactionClass new ]
activate super activate. self state: #xactNo
dismissTransaction "We don't need our transaction object any more." self transaction dismiss. self transaction removeParticipant: self. self transaction: nil
quiesce "Time to quiesce all connections to external resources." "Enforce-quietly: receiver is connected." self isConnected ifFalse: [ ^self ]. "If we're in a transaction, roll it back now to assure a consistent state." self inTransactionMode ifTrue: [ self rollback ]. super quiesce
useTransaction: aTransaction "Use aTransaction as our transaction." self transaction: aTransaction. self transaction addParticipant: self. self transaction acquire
</methods> <methods> Database.ExternalDatabaseConnection <category>private-finalization</category>
executor "Answer with the executor." "Subclassess will want to override to add information to the executor. The subclass method should use super executor to create the executor initially." | ex | ex := super executor. ex transaction: self transaction. ex transactionCoordinator: self transactionCoordinator. ^ex
finalizeExternal "Release all external resource." ( traceLevel >= 1 ) ifTrue: [ self class trace: nil ]. self transaction addParticipant: self. self inTransactionMode ifTrue: [ "Assert: the connection cannot be in the paused state." self transaction executorFinishingTransaction ]. self transaction dismiss. super finalizeExternal
</methods> <methods> Database.ExternalDatabaseConnection <category>private-library calls</category>
acquireExternal "Dispatch to proper method for connection classes." self acquireExternal: self password
acquireExternal: aPassword "Acquire the external resources involved with a connection to the SQL-environment." "The username, password, and environment variables may be nil to indicate that the proper value is unknown or an empty string to indicate that the DBMS is expected to take the default. If the value for one of these variables is required, raise the proceedable signal requiredUsernameSignal, requiredPasswordSignal, or requiredEnvironmentSignal and use the proceed value. Do not record this value in the instance variable." self subclassResponsibility "Note: implementations of this method are expected to use self class mapLogical: self environment in order to determine the proper environment string to use."
beginExternal "Mark the beginning of receiver's portion of a transaction. Most dbms define this as a side-effect of using a transaction-initiating statement. This is provided as a convenience for drivers that require knowledge of the event to control their state machines." self isConnected ifFalse: [ ^self class connectionNotOpenSignal raise ]. self state == #xactNo ifTrue: [ self state: #xactYes ] "Drivers with a transaction concept that spans multiple connections may never invoke this method. Thus, those drivers should overide this with ^self shouldNotImplement."
commitExternal "Commit all changes made by receiver's connection." | wasInTrans | (wasInTrans := (self state == #xactYes)) ifTrue: [ self state: #xactNo ]. ^wasInTrans "Drivers with a transaction concept that spans multiple connections may never invoke this method. Thus, those drivers should overide this with ^self shouldNotImplement."
rollbackExternal "Rollback all changes made by receiver's connection." | wasInTrans | (wasInTrans := (self state == #xactYes)) ifTrue: [ self state: #xactNo ]. ^wasInTrans "Drivers with a transaction concept that spans multiple connections may never invoke this method. Thus, those drivers should overide this with ^self shouldNotImplement."
</methods> <methods> Database.ExternalDatabaseConnection class <category>class initialization</category>
initialize "Establish class variables." "ExternalDatabaseConnection initialize" | theLens | (ObjectMemory dependents includes: self) ifFalse: [ ObjectMemory addDependent: self ]. (theLens := #{LensSession} valueOrDo: [nil]) notNil ifTrue: [ theLens initializeAllSignals ]. self initializeExceptionClasses.
initializeExceptionClasses "Initialize related exception classes." AuthenticationFailure notifierString: (#errUsernamePassword << #database >> 'Invalid username/password'); nameClass: self message: #authenticationFailureSignal. ConnectionException notifierString: (#errConnectionException << #database >> 'Connection Exception'); nameClass: self message: #connectionExceptionSignal. ConnectionNotOpen notifierString: (#connectionNotOpen << #database >> 'Connection Exception--connection not open'); nameClass: self message: #connectionNotOpenSignal. CouldNotResolveServiceName notifierString: (#couldNotResolveServiceName << #database >> 'Connection Exception--Could not resolve service name.'); nameClass: self message: #couldNotResolveServiceNameSignal. DuplicateIndexesError notifierString: (#duplicateIndex << #database >> 'Attempting to create a duplicate index'); nameClass: self message: #duplicateIndexesErrorSignal. DynamicSQLError notifierString: (#errDynamicSQL << #database >> 'Dynamic SQL Error'); nameClass: self message: #dynamicSQLErrorSignal. ExternalDatabaseException notifierString: (#errExternalDatabase << #database >> 'External Database Error'); nameClass: self message: #externalDatabaseErrorSignal. ExternalDatabaseResumableException notifierString: (#errInformation << #database >> 'External Database Information'); nameClass: self message: #externalDatabaseInformationSignal. ExternalDatabaseLibraryInaccessible notifierString: (#databaseClientInacessilbe << #database >> 'Database client libraries are inaccessible. Either the Object Engine has not been linked with the required libraries, or the DLLs for those libraries are not in your search path. For more information, consult the release notes for this Connect product.' ); nameClass: self message: #externalDatabaseLibraryInaccessibleSignal. ExternalDatabaseTransactionError notifierString: (#errCommitRollbackFailed << #database >> 'An attempt to commit/rollback a database transaction failed.'); nameClass: self message: #externalDatabaseTransactionErrorSignal. IndexConflict notifierString: (#errUpdatePrimaryKey << #database >> 'You cannot update the primary key of an existing row or insert a new row if this would result in more than one row with the same primary key.'); nameClass: self message: #indexConflictSignal. InvalidConnectionState notifierString: (#errConnectionState << #database >> 'Invalid Connection State'); nameClass: self message: #invalidConnectionStateSignal. InvalidDescriptorCount notifierString: (#errDescriptorCount << #database >> 'Dynamic SQL Error--invalid descriptor count'); nameClass: self message: #invalidDescriptorCountSignal. InvalidParameterMarker notifierString: (#errParameterMarker << #database >> 'Dynamic SQL Error--invalid parameter marker'); nameClass: self message: #invalidParameterMarkerSignal. InvalidSessionState notifierString: (#errSessionState << #database >> 'Invalid Session State'); nameClass: self message: #invalidSessionStateSignal. InvalidTableName notifierString: (#errTableName << #database >> 'Invalid table name in query'); nameClass: self message: #invalidTableNameSignal. InvalidTransactionState notifierString: (#errTransactionState << #database >> 'Invalid Transaction State'); nameClass: self message: #invalidTransactionStateSignal. MissingBindVariable notifierString: (#missingBindVariable << #database >> 'Missing bind variable.'); nameClass: self message: #missingBindVariableSignal. NoDefaultConnection notifierString: (#errDefaultConnection1 << #database >> 'There is no default Connection to provide a connection'); nameClass: self message: #noDefaultConnectionSignal. ObjectLocked notifierString: (#alreadyLockedObject << #database >> 'Attempting to lock a locked object'); nameClass: self message: #objectLockedSignal. RequiredEnvironment notifierString: (#errEnvironment << #database >> 'No environment was specified and there is no default defined'); nameClass: self message: #requiredEnvironmentSignal. RequiredPassword notifierString: (#passwordRequired << #database >> 'A password is required'); nameClass: self message: #requiredPasswordSignal. RequiredUsername notifierString: (#userNameRequired << #database >> 'A user name is required'); nameClass: self message: #requiredUsernameSignal. RowIsReferencedError notifierString: (#errPrimaryKey << #database >> 'You cannot change the primary key of<n>or delete a row which is referenced in another table.') expandMacros; nameClass: self message: #rowIsReferencedErrorSignal. SQLSyntaxError notifierString: (#errSQLSyntax << #database >> 'Syntax error or access rule violation in SQL dynamic statement'); nameClass: self message: #syntaxErrorSignal. TooManyActiveConnections notifierString: (#errConnectionMaxDriver << #database >> 'The maximum number of connections are already active for this driver'); nameClass: self message: #tooManyActiveConnectionsSignal. TooManyActiveSessions notifierString: (#errMaxSessionsPerConnection << #database >> 'The maximum number of sessions are already active in this connection'); nameClass: self message: #tooManyActiveSessionsSignal. TooManyActiveTransactions notifierString: (#errMaxTransactionsDriver << #database >> 'The maximum number of transactions are already active for this driver'); nameClass: self message: #tooManyActiveTransactionsSignal. TransactionException notifierString: (#errTransactionException << #database >> 'Transaction Exception'); nameClass: self message: #transactionExceptionSignal. TransactionPhase2Fatal notifierString: (#err2phaseCommit << #database >> 'Failure to complete database commit or rollback.<n>Inform your Database Administrator.') expandMacros; nameClass: self message: #transactionPhase2FatalSignal. UnableToAllocateHandle notifierString: (#errHandleAllocation << #database >> 'Unable to allocate a handle.'); nameClass: self message: #unableToAllocateHandleSignal. UnableToBind notifierString: (#errVariableBufferAssocation << #database >> 'Unable to associate buffer with bind variable'); nameClass: self message: #unableToBindSignal. UnableToCancelCursor notifierString: (#errCursorCancel << #database >> 'The database cursor could not be canceled.'); nameClass: self message: #unableToCancelCursorSignal. UnableToCloseCursor notifierString: (#errCursorClosed << #database >> 'The database cursor could not be closed.'); nameClass: self message: #unableToCloseCursorSignal. UnableToConnectToSQLenvironment notifierString: (#errDatabaseEvironment << #database >> 'Connection Exception--unable to connect to database environment'); nameClass: self message: #unableToConnectToSQLenvironmentSignal. UnableToConnectToSQLserver notifierString: (#errDatabaseSeverConnection << #database >> 'Connection Exception--unable to connect to database server'); nameClass: self message: #unableToConnectToSQLserverSignal. UnableToDescribe notifierString: (#errObtainDescription << #database >> 'Unable to obtain description'); nameClass: self message: #unableToDescribeSignal. UnableToDisconnect notifierString: (#errServerDisconnect << #database >> 'Unable to disconnect from SQL-server'); nameClass: self message: #unableToDisconnectSignal. UnableToExecuteSQL notifierString: (#errExecuteSQL << #database >> 'Unable to execute the prepared SQL text'); nameClass: self message: #unableToExecuteSQLSignal. UnableToFetchData notifierString: (#errUnableToFetch << #database >> 'Unable to fetch one or more rows of data'); nameClass: self message: #unableToFetchDataSignal. UnableToFreeResource notifierString: (#errFreeResource << #database >> 'Unable to free an external resource.'); nameClass: self message: #unableToFreeResourceSignal. UnableToOpenCursor notifierString: (#errCursorOpened << #database >> 'The database cursor could not be opened.'); nameClass: self message: #unableToOpenCursorSignal. UnableToPrepare notifierString: (#errPrepareSQL << #database >> 'Unable to prepare SQL statement.'); nameClass: self message: #unableToPrepareSignal. UnableToQueryDriverInformation notifierString: (#errQueryDriver << #database >> 'Unable to query driver information.'); nameClass: self message: #unableToQueryDriverInformationSignal. UnableToQueryHandleInformation notifierString: (#errQueryHandle << #database >> 'Unable to query handle information.'); nameClass: self message: #unableToQueryHandleInformationSignal. UnsupportedDriverFunctionality notifierString: (#externalDBError << #database >> 'An attempt was made to use a feature which the API is not available in the current configuration.'); nameClass: self message: #unsupportedDriverFunctionalitySignal. UnsupportedIsolationLevel notifierString: (#unsupportedIsolation << #database >> 'An attempt was made to set an unsupported isolation level.'); nameClass: self message: #unsupportedIsolationLevelSignal.
obsolete "This class is being removed from the system." (ObjectMemory dependents includes: self) ifTrue: [ ObjectMemory removeDependent: self ]. super obsolete
</methods> <methods> Database.ExternalDatabaseConnection class <category>instance creation</category>
new "Create a valid, but empty, connection object." | defaultName defaultClass | self == ExternalDatabaseConnection ifTrue: [((defaultName := self defaultConnection) isNil or: [(defaultClass := ((defaultName asQualifiedReference) home: self environment; yourself) valueOrDo: [nil]) isNil]) ifTrue: [defaultClass := self noDefaultConnectionSignal raiseRequest]. ^defaultClass new] ifFalse: [^self basicNew initialize]
</methods> <methods> Database.ExternalDatabaseConnection class <category>accessing</category>
defaultConnection "Answer the class name for the default Connection to use when creating connections." ^DefaultConnection
defaultConnection: aClassName "Set the class name for the default Connection to use when creating connections." DefaultConnection := aClassName
defaultEnvironment "Answer the default logical environment to use when creating connections." ^DefaultEnvironment
defaultEnvironment: aString "Set the default logical environment to use when creating connections." DefaultEnvironment := aString
kind "Answer a symbol representing the type of DMBS the receiver provides services for." ^self subclassResponsibility
version ^(#EXDIversion << #database >> 'External Database Interface - Release 7.0') asString
</methods> <methods> Database.ExternalDatabaseConnection class <category>activation</category>
pause "Direct this driver (or all drivers if receiver is ExternalDatabaseConnection) to indefinitely suspend operations." "Subclasses must override to provide driver-specific behavior." self == ExternalDatabaseConnection ifTrue: [ self subclasses do: [ :each | each pause ]. ] ifFalse: [ self subclassResponsibility ].
resume "Direct this driver (or all drivers if receiver is ExternalDatabaseConnection) to resume suspended operations." "Subclasses must override to provide driver-specific behavior." self == ExternalDatabaseConnection ifTrue: [ self subclasses do: [ :each | each resume ]. ] ifFalse: [ self subclassResponsibility ].
</methods> <methods> Database.ExternalDatabaseConnection class <category>environment mapping</category>
addLogical: aLogicalEnvironmentString environment: anEnvironmentSpecificationString "Add a new entry in the logical environment map which associates aLogicalEnvironmentString as the logical name for the environment and anEnvironmentSpecificationString as the value to use when connecting." | theClass | self == ExternalDatabaseConnection ifTrue: [DefaultConnection isNil ifTrue: [self error: #errDefaultConnection << #database >> 'Establish a defaultConnection: first'. ^self]. theClass := self environment at: DefaultConnection] ifFalse: [theClass := self]. theClass environments at: aLogicalEnvironmentString put: anEnvironmentSpecificationString
environments "Answer dictionary containing all logical name -> SQL-environment string mappings." "Lazy initialization" environmentMap isNil ifTrue: [ environmentMap := Dictionary new ]. "Answer the dictionary." ^environmentMap
mapLogical: aLogicalEnvironmentString "Answer the string to use for the environment in making a connection. Answer aLogicalEnvironmentString if it does not appearin the map." "This is only sent from subclasses, so their distinct class-side instance environments variable will be used." ^self environments at: aLogicalEnvironmentString ifAbsent: [ aLogicalEnvironmentString ]
removeLogical: aLogicalEnvironmentString "Remove an entry from the logical environment map." | theClass | self == ExternalDatabaseConnection ifTrue: [DefaultConnection isNil ifTrue: [^self]. theClass := self environment at: DefaultConnection] ifFalse: [theClass := self]. theClass environments removeKey: aLogicalEnvironmentString ifAbsent: []
</methods> <methods> Database.ExternalDatabaseConnection class <category>signal constants</category>
authenticationFailureSignal "Answer the signal used to indicate that the server failed to authenticate the username and/or password." ^AuthenticationFailure
connectionExceptionSignal "Answer the parent for signals used to indicate problems in the ANSI-2 exception class named connection exception." ^ConnectionException
connectionNotOpenSignal "Answer the signal used to indicate that the connection does not have a connection to the SQL-environment." ^ConnectionNotOpen
couldNotResolveServiceNameSignal "Answer the signal used to indicate that the service name could not be resolved." ^CouldNotResolveServiceName
duplicateIndexesErrorSignal "Answer the signal used to indicate attempting to add an index having the same columns as an existing index." ^DuplicateIndexesError
dynamicSQLErrorSignal "Answer the parent for signals used to indicate problems in the ANSI-2 exception class named dynamic SQL error." ^DynamicSQLError
externalDatabaseErrorSignal "Answer the most general external database error signal. This signal and its descendents are not proceedable. External database error signals may have parameters defined. Read the method which returns each signal for a definition." ^ExternalDatabaseException
externalDatabaseInformationSignal "Answer the most general external database information signal. This signal and its descendents are proceedable as they are usually used to collect missing information or report conditions that the handler should be able to correct. External database information signals may have parameters defined. Read the method which returns each signal for a definition." ^ExternalDatabaseResumableException
externalDatabaseLibraryInaccessibleSignal "Answer the signal used to indicate that a driver is not able to access the database library. Either the OE does not contain the database library or it cannot be found in the search path for dynamic link libraries." ^ExternalDatabaseLibraryInaccessible
externalDatabaseTransactionErrorSignal "An attempt to commit/rollback a database transaction failed." ^ExternalDatabaseTransactionError
indexConflictSignal "Answer the signal indicating attempt to insert or update an object so that it has the same index value as another object." ^IndexConflict
invalidConnectionStateSignal "Answer the signal used to indicate that the application cannot use a function at a given time." ^InvalidConnectionState
invalidDescriptorCountSignal "Answer the signal used to indicate that there are more input variables in an SQL statement than are found in the bind object." ^InvalidDescriptorCount
invalidParameterMarkerSignal "Answer the signal used to indicate that the parameter marker is incorrect." ^InvalidParameterMarker
invalidSessionStateSignal "Answer the signal used to indicate that the application cannot use a function at a given time." ^InvalidSessionState
invalidTableNameSignal "The query specified an invalid table name" ^InvalidTableName
invalidTransactionStateSignal "Answer the signal used to indicate that the application cannot use a function at a given time." ^InvalidTransactionState
missingBindVariableSignal "Answer the signal used to indicate that a bind variable is missing." ^MissingBindVariable
noDefaultConnectionSignal "Answer the signal to report that ExternalDatabaseConnection doesn't know which Connection to use for a new connection." ^NoDefaultConnection
objectLockedSignal "Answer the signal indicating that an object is locked when attempting to change it in the database." ^ObjectLocked
requiredEnvironmentSignal "Answer the signal to report that the environment is a required parameter by this driver and no default was specified." ^RequiredEnvironment
requiredPasswordSignal "Answer the signal used to indicate that a password is required in order to connect. This signal is proceedable and expects a password string as the proceedWith: value." ^RequiredPassword
requiredUsernameSignal "Answer the signal used to indicate that a username is required in order to connect. This signal is proceedable and expects a username string as the proceedWith: value." ^RequiredUsername
rowIsReferencedErrorSignal "Answer the signal indicating that a row may not be deleted nor the primary key changed because it is still referenced." ^RowIsReferencedError
syntaxErrorSignal "Answer the signal used to indicate that the SQL text could not be prepared." ^SQLSyntaxError
tooManyActiveConnectionsSignal "Answer the signal used to indicate that the driver for this connection already has the maximum number of active connections." ^TooManyActiveConnections
tooManyActiveSessionsSignal "Answer the signal used to indicate that the connection already has the maximum number of active sessions." ^TooManyActiveSessions
tooManyActiveTransactionsSignal "Answer the signal used to indicate that the driver for this connection already has the maximum number of active transactions." ^TooManyActiveTransactions
transactionExceptionSignal "Answer the signal used to indicate an error in transaction processing." ^TransactionException
transactionPhase2FatalSignal "Answer the signal used to indicate a fatal error in the second phase of a two-phase commit or rollback. This usually means that manual recovery will be required to complete the transaction." ^TransactionPhase2Fatal
unableToAllocateHandleSignal "A handle could not be allocated." ^UnableToAllocateHandle
unableToBindSignal "Answer the signal used to indicate that the input or output bind was unsuccessful." ^UnableToBind
unableToCancelCursorSignal "The database cursor (statement) could not be canceled. This signal is not proceedable." ^UnableToCancelCursor
unableToCloseCursorSignal "The database cursor could not be closed. This signal is proceedable." ^UnableToCloseCursor
unableToConnectToSQLenvironmentSignal "Answer the signal used to indicate that the connection cannot be made to the database environment for some reason other than the server itself. This signal is used when it is possible to segregate the error causes, otherwise unableToConnectToSQLserverSignal should be used." ^UnableToConnectToSQLenvironment
unableToConnectToSQLserverSignal "Answer the signal used to indicate that the connection cannot be made to the database server. This signal is used when it is the server that is the cause of the failure. If it is possible to segregate the errors, an unableToConnectToSQLEnvironmentSignal should be used." ^UnableToConnectToSQLserver
unableToCreateConnectionPoolSignal "The database cursor could not be opened." ^UnableToCreateConnectionPool
unableToDescribeSignal "Answer the signal used to indicate that description of a input variable or an output column could not be acquired." ^UnableToDescribe
unableToDestroyConnectionPoolSignal "The database cursor could not be opened." ^UnableToDestroyConnectionPool
unableToDisconnectSignal "Answer the signal used to indicate that an error occurred when trying to end the connection. This signal is proceedable." ^UnableToDisconnect
unableToExecuteSQLSignal "Answer the signal used to indicate that the prepared SQL text could not be executed." ^UnableToExecuteSQL
unableToFetchDataSignal "Answer the signal used to indicate that the row or rows could not be fetched." ^UnableToFetchData
unableToFreeResourceSignal "An external resource could not be released/dropped/free'd." ^UnableToFreeResource
unableToOpenCursorSignal "The database cursor could not be opened." ^UnableToOpenCursor
unableToPrepareSignal "Unable to prepare an SQL statement." ^UnableToPrepare
unableToQueryDriverInformationSignal "Driver information could not be queried." ^UnableToQueryDriverInformation
unableToQueryHandleInformationSignal "Driver information could not be queried." ^UnableToQueryHandleInformation
unableToSetEnvironmentAttributeSignal "The database cursor could not be opened." ^UnableToSetEnvironmentAttribute
unsupportedCursorTypeSignal "Answer the signal to report that the loaded client library does not support scrollable cursors." ^UnsupportedCursorType
unsupportedDriverFunctionalitySignal "Answer the signal indicating an attempt was made to use functionality which is not available from the underlying API due to the current execution circumstances." ^UnsupportedDriverFunctionality
unsupportedIsolationLevelSignal "Answer the signal indicating an attempt was made to set an unsupported isolation level." ^UnsupportedIsolationLevel
</methods> <methods> Database.ExternalDatabaseConnection class <category>tracing</category>
toggleTracing "Enable/disable a coarse level of tracing" "ExternalDatabaseConnection toggleTracing" Transcript cr; show: (#databaseTracing << #database >> 'Database tracing '). ( TraceLevel isNil or: [ TraceLevel == 0 ] ) ifTrue: [ self traceCollector: Transcript. self traceLevel: 1. Transcript show: (#enabled << #database >> 'enabled') asString ] ifFalse: [ self traceLevel: 0. Transcript show: (#disabled << #database >> 'disabled') asString ]. Transcript flush.
traceCollector "Answer the stream currently receiving any trace output." ^TraceCollector
traceCollector: aWriteStream "Setup a stream to receive any trace output." TraceCollector := aWriteStream
traceLevel: anInteger "Set the level of tracing that is enabled for this class to anInteger." TraceLevel := anInteger
</methods> <methods> Database.ExternalDatabaseConnection class <category>private-accessing</category>
columnDescriptionClass "Answer the class to use for column description objects associated with receiver." ^ExternalDatabaseColumnDescription
connectionClass ^self
myDependents "Answer the receiver's dependents or nil." ^dependents
myDependents: dependentsOrNil "Set the receivers dependents." dependents := dependentsOrNil
platformType "Answer the current platform type." PlatformType isNil ifTrue: [ PlatformType := self determinePlatformType ]. ^PlatformType
sessionClass "Answer the class to use for session objects associated with receiver." ^self subclassResponsibility
transactionClass "Answer the class to use for transaction objects associated with receiver." ^self subclassResponsibility
xif "Answer the ExternalInterface subclass instance to use." ^self subclassResponsibility
xif: anExternalInterface "Set the ExternalInterface subclass instance to use." xif := anExternalInterface
</methods> <methods> Database.ExternalDatabaseConnection class <category>private-activation</category>
determineMacPlatformFrom: osNameString "Answer a symbol representing the current platform type." "ExternalInterface must complete its #returnFromSnapshot processing before this method can be safely invoked." "Power Mac ^#powermac Mac 68K ^#mac" | tokens | tokens := osNameString tokensBasedOn: Character space. (tokens includes: 'Power') ifTrue: [^#powermac]. ^#mac.
determinePlatformType "Answer a symbol representing the current platform type." "ExternalInterface must complete its #returnFromSnapshot processing before this method can be safely invoked." | platformArray platformSymbol osNameString | platformArray := ExternalInterface currentPlatform. platformSymbol := platformArray at: 1. osNameString := platformArray at: 2. #unix == platformSymbol ifTrue: [^self determineUnixPlatformFrom: osNameString]. #os2 == platformSymbol ifTrue: [ ^#os2 ]. #win32 == platformSymbol ifTrue: [^self determineWinTelPlatformFrom: osNameString]. #mac == platformSymbol ifTrue: [^self determineMacPlatformFrom: osNameString]. ^#unknown.
determineUnixPlatformFrom: unixOSNameString "Answer a symbol representing the current platform type." "ExternalInterface must complete its #returnFromSnapshot processing before this method can be safely invoked." "Digital Unix ^#alpha_unix HP Unix ^#hp_unix IBM Aix ^#aix_unix Sun Solaris ^#sun5_unix Sun SunOS ^#sun4_unix" | tokens | tokens := unixOSNameString tokensBasedOn: Character space. (tokens includes: 'osf1') ifTrue: [^#alpha_unix]. (tokens includes: 'hp-ux') ifTrue: [^#hp_unix]. (tokens includes: 'aix') ifTrue: [^#aix_unix]. (tokens includes: 'solaris') ifTrue: [^#sun5_unix]. ((tokens includes: 'bsd') and: [tokens includes: 'sun']) ifTrue: [^#sun4_unix]. (tokens includes: 'solaris64') ifTrue:[^#unix_sysV_sun_solaris64]. ((tokens includes: 'I386') and: [tokens includes: 'linux']) ifTrue: [^#linux_i386_unix]. ((tokens includes: 'x86_64') and: [tokens includes: 'linux']) ifTrue: [^#linux_x86_64_unix]. ((tokens includes: 'Power') and: [tokens includes: 'MacOSX']) ifTrue: [^#Power_MacOSX]. ^#unknown
determineWinTelPlatformFrom: osNameString "Answer a symbol representing the current platform type." "ExternalInterface must complete its #returnFromSnapshot processing before this method can be safely invoked." "WinNT ^#nt Win95 ^#win95 Win3.1 ^#win32s" | tokens | tokens := osNameString tokensBasedOn: Character space. (tokens includes: 'nt') ifTrue: [^#nt]. (tokens includes: '95') ifTrue: [^#win95]. ^#win32s
install "Direct this driver (or all drivers if receiver is ExternalDatabaseConnection) to take the necessary steps for returning from a snapshot. Notify dependents when fully installed so that appropriate action may be taken." "ExternalDatabaseConnection install" PlatformType := nil. self == ExternalDatabaseConnection ifTrue: [ self subclasses do: [ :each | each install ] ] ifFalse: [ self subclassResponsibility ]. "Driver implementations should arrange for each class with a registry to perform returnFromSnapshot (and anything else important, of course)."
</methods> <methods> Database.ExternalDatabaseConnection class <category>private-updating</category>
update: anAspectSymbol with: aParameter from: aSender "In order to aid in sequencing of activities, clients may become dependents of ExternalDatabaseConnection rather than ObjectMemory. All notifications from ObjectMemory are passed on as if they came from the receiver." aSender == ObjectMemory ifTrue: [ "Sometimes the notice should be sent out first so dependents can act before we do." anAspectSymbol == #aboutToQuit ifTrue: [ self changed: anAspectSymbol with: aParameter. ^self pause ]. "In other cases, we need to act before notifying the dependents. Note: fall through to the notification." anAspectSymbol == #returnFromSnapshot ifTrue: [ self install ]. "And sometimes we're just sending it on." self changed: anAspectSymbol with: aParameter ]
</methods> <methods> Database.ConnectionProfile <category>accessing</category>
asConnection ^self driverClass new environment: self environment; username: self userName; yourself
displayString ^name isNil ifTrue: [String new] ifFalse: [name]
driverClass ^self driverClassName asQualifiedReference value
driverClassName ^driverClassName
driverClassName: aString driverClassName := aString
environment ^environment
environment: aString environment := aString
name ^name
name: aString name := aString. originalName := aString
originalName ^originalName isNil ifTrue: [String new] ifFalse: [originalName]
password ^password
password: aString password := aString
resetName name := nil
userName ^userName
userName: aString userName := aString
</methods> <methods> Database.ConnectionProfile <category>comparing</category>
= anObject ^(anObject isKindOf: ConnectionProfile) and: [self name = anObject name]
hash ^name hash
</methods> <methods> Database.ConnectionProfile <category>private</category>
addXmlElementsTo: anElement anElement addNode: (self elementFor: 'driver-class-name' with: self driverClassName); addNode: (self elementFor: 'environment' with: self environment); addNode: (self elementFor: 'user-name' with: self userName); addNode: (self elementFor: 'password' with: self password)
asXmlNode | root | root := XML.Element tag: 'database-profile' attributes: (Array with: (XML.Attribute name: 'name' value: name)) elements: nil. self addXmlElementsTo: root. ^root
elementFor: tagString with: contentsString ^(XML.Element tag: tagString) addNode: (XML.Text text: contentsString)
isSpecified: anObject ^anObject notNil and: [anObject isEmpty not]
valueOf: anElement childNamed: aString | children textElement | children := (anElement elementNamed: aString) children. children isEmpty ifTrue: [^String new]. textElement := children first. textElement isText ifFalse: [self error: #invalidFileFormat << #database >> 'invalid file format']. ^textElement text
</methods> <methods> Database.ConnectionProfile <category>initialize-release</category>
initialize environment := String new. password := String new
initializeFromXml: anElement name := anElement valueOfAttribute: 'name' ifAbsent: [self error: (#invalidFileFormat << #database >> 'invalid file format') asString]. driverClassName := self valueOf: anElement childNamed: 'driver-class-name'. environment := self valueOf: anElement childNamed: 'environment'. userName := self valueOf: anElement childNamed: 'user-name'. password := self valueOf: anElement childNamed: 'password'. self isValid ifFalse: [self error: #invalidAttributesSpecifiedInTheFile << #database >> 'invalid attributes specified in the file']
</methods> <methods> Database.ConnectionProfile <category>testing</category>
isConnectable "Answer if the receiver can be used to open a connection right now." ^self isValid and: [self driverClassName asQualifiedReference isDefined]
isValid "A valid profile is one with enough data to open a connection in principle, assuming the necessary driver class is present in the image." ^(self isSpecified: driverClassName) and: [self isSpecified: userName]
</methods> <methods> Database.ConnectionProfile class <category>instance creation</category>
fromXmlElement: anElement ^self new initializeFromXml: anElement
new ^super new initialize
</methods> <methods> Database.ExternalDatabaseError <category>accessing</category>
dbmsErrorCode "Answer the error code used by the dbms api which lead to this error report." ^dbmsErrorCode
dbmsErrorString "Answer the text associated with the code value returned from the dbms api. Not all dbms api make this information available." ^dbmsErrorString
osErrorCode "Answer the error code provided by the dbms api which is attributed to the underlying operating system. This is usually just detail information about the dbmsErrorCode." ^osErrorCode
osErrorString "Answer the text associated with the osErrorCode returned from the dbms api. Not all systems make this information available." ^osErrorString
</methods> <methods> Database.ExternalDatabaseError <category>private-accessing</category>
dbmsErrorCode: aSmallInteger dbmsErrorCode := aSmallInteger
dbmsErrorString: aString dbmsErrorString := aString
osErrorCode: aSmallInteger osErrorCode := aSmallInteger
osErrorString: aString osErrorString := aString
</methods> <methods> Database.ExternalDatabaseColumnDescription <category>accessing</category>
index "Answer the ordinal number of the column, or nil if unknown." ^index
maxColumnConstraint "Answer the size of the buffer required to hold data for the column, or nil if unknown." ^length
name "Answer the name of the column, or nil if unknown." ^name
nullable "Answer true or false to indicate whether the column admits NULL, or nil if unknown." ^nullable
precision "Answer the decimal precision of the column, or nil if unknown." ^precision
scale "Answer the decimal scale of the column, or nil if unknown." ^scale
type "Answer the Smalltalk class which will be used to hold data from the column, or nil if unknown." ^type
</methods> <methods> Database.ExternalDatabaseColumnDescription <category>printing</category>
printOn: aStream "Append to the argument aStream a sequence of characters that identifies the receiver." | colName colType | super printOn: aStream. aStream nextPut: $(. (colName := self name) notNil ifTrue: [ aStream nextPutAll: (#Name << #database >> ' name=') asString; nextPutAll: colName]. (colType := self type) notNil ifTrue: [ aStream nextPutAll: (#Type << #database >> ' type=') asString. colType printOn: aStream ]. aStream nextPutAll: ' )'
</methods> <methods> Database.ExternalDatabaseColumnDescription <category>private-accessing</category>
index: aNumber index := aNumber
maxColumnConstraint: anInteger length := anInteger
name: aString name := aString
nullable: aBoolean nullable := aBoolean
precision: anInteger precision := anInteger
scale: anInteger scale := anInteger
type: aString type := aString
</methods> <methods> Database.ExternalDatabaseTransaction <category>initialize-release</category>
initialize "Establish instance variables that require special handling." super initialize. self state: #xactNo. self memberCountHolder: 0 asValue. self remainingCountHolder: 0 asValue
</methods> <methods> Database.ExternalDatabaseTransaction <category>testing</category>
inTransactionMode "Answer true if a transaction has been started." | s | ^((s := self state) == #xactYes or: [ s == #committing ]) or: [ s == #aborting ]
</methods> <methods> Database.ExternalDatabaseTransaction <category>transactions</category>
begin "Mark the beginning of a transaction. If an error occurs, prevent any further activity on any of the participanting connections. This is achieved by disconnecting without further transaction actions and letting the database manager take whatever action as the disconnects occur." self state == #xactNo ifFalse: [ self class connectionClass invalidTransactionStateSignal raise ]. "If we can't begin successfully, the only response is to refuse to do any work." [ self state: #xactYes. self remainingCount: self memberCount. self beginExternal. self participantsDo: [ :each | each beginExternal ] ] ifCurtailed: [ self state: #xactNo. "Will prevent connections from trying to do xact termination." self participantsDo: [ :each | each disconnect ] ]
commit "Coordinate the commit for all related connections. If an individual connection can't do its part, go on to the others and reraise an exception when all have tried. The parameter to the exception will be all the exception's parameters aggregated." ^self finishTransaction: #committing method: #commitExternal
rollback "Coordinate the rollback for all related connections. If an individual connection can't do its part, go on to the others and reraise an exception when all have tried. The parameter to the exception will be all the exception's parameters aggregated." ^self finishTransaction: #aborting method: #rollbackExternal
</methods> <methods> Database.ExternalDatabaseTransaction <category>private-accessing</category>
acquireTrigger "Answer number of participants required to trigger acquire/dismiss." ^nil "never acquire"
memberCount "Answer the number of members in a coordinated transaction." ^self memberCountHolder value
memberCount: aSmallInteger "Set the number of members in a coordinated transaction." self memberCountHolder value: aSmallInteger
memberCountHolder "Answer the holder for the number of members in a coordinated transaction." ^memberCountHolder
memberCountHolder: anExternalDatabaseValueHolder "Set the holder for the number of members in a coordinated transaction." memberCountHolder := anExternalDatabaseValueHolder
remainingCount "Answer the number of members remaining in a coordinated transaction." ^self remainingCountHolder value
remainingCount: aSmallInteger "Set the number of members remaining in a coordinated transaction." self remainingCountHolder value: aSmallInteger
remainingCountHolder "Answer the holder for the number of members remaining in a coordinated transaction." ^remainingCountHolder
remainingCountHolder: anExternalDatabaseValueHolder "Set the holder for the number of members remaining in a coordinated transaction." remainingCountHolder := anExternalDatabaseValueHolder
</methods> <methods> Database.ExternalDatabaseTransaction <category>private-activation</category>
acquire "Record existence of active member of this coordinated transaction." self memberCount: self memberCount + 1
activate super activate. self state: #xactNo
dismiss "Record departure of active member of this coordinated transaction." self memberCount: self memberCount - 1
</methods> <methods> Database.ExternalDatabaseTransaction <category>private-finalization</category>
executor "Answer with the executor." "Subclassess which want to override to add information to the executor should use super executor to create the executor initially." | ex | ex := super executor. ex memberCountHolder: self memberCountHolder. ex remainingCountHolder: self remainingCountHolder. ^ex
</methods> <methods> Database.ExternalDatabaseTransaction <category>private-library calls</category>
beginExternal "Perform driver-specific work at the beginning of a transaction." ^self subclassResponsibility
commitExternal "Perform driver-specific work at the completion of a transaction." ^self subclassResponsibility
rollbackExternal "Perform driver-specific work at the completion of a transaction." ^self subclassResponsibility
</methods> <methods> Database.ExternalDatabaseTransaction <category>private-transactions</category>
executorFinishingTransaction | action s | ( traceLevel >= 1 ) ifTrue: [ (self traceStream) nextPutAll: (#state << #database >> 'state: ') asString; print: self state. self class trace: self emitTrace ]. "If nobody else has tried to finish up the transaction, we need to roll it back." (s := self state) == #xactYes ifTrue: [ ^self rollback ]. "We're finishing up the transaction, but due to garbage collection, the executor which sent this message didn't hear about it. Carry on with what we're doing." s == #committing ifTrue: [ action := #commitExternal ]. s == #aborting ifTrue: [ action := #rollbackExternal ]. self participantsDo: [ :each | each state == #xactYes ifTrue: [ each perform: action. self remainingCount: (self remainingCount - 1) ] ]. self remainingCount == 0 ifTrue: [ self state: #xactNo ]
finishTransaction: finishingState method: selector "Coordinate the completion of the transaction for all related connections. The finishingState is used until all of the transaction members have done their part of finishing the transaction. The selector is the method to use to invoke the driver-specific action. If an individual connection can't do its part, go on to the others and reraise an exception when all have tried. The parameter to the exception will be all the exception's parameters aggregated. Errors while finishing a transaction lead to all participating connections being prevented from any further work (they are disconnected)." | exParams | self state == #xactYes ifFalse: [^self class connectionClass invalidTransactionStateSignal raise]. exParams := nil. "The finishingState will remain until all participants (including any being finalized) check in and complete their part." self state: finishingState. "Phase 1 is performed by the driver's transaction implementation of commitExternal or rollbackExternal. If an error occurs here, the unwind block will render each of the participants unable to do further processing." [self perform: selector] ifCurtailed: [self state: #xactNo. self participantsDo: [:each | each disconnect]]. "Phase 2 is performed by each participant's implementation of commitExternal or rollbackExternal. In systems that do not support a 2-phase commit, this provides the serial broadcast form of commit or rollback. Capture any errors that occur here, but attempt to finish the remaining transactions. In any event, manual intervention will be required to complete the transaction." self participantsDo: [:each | [each perform: selector] on: self class connectionClass externalDatabaseErrorSignal do: [:ex | exParams isNil ifTrue: [exParams := OrderedCollection new]. ex parameter notNil ifTrue: [exParams addAll: ex parameter]. ex return]. "Accumulate the exception parameters" self remainingCount: self remainingCount - 1]. self remainingCount == 0 ifTrue: [self state: #xactNo]. exParams notNil ifTrue: [self state: #xactNo. self participantsDo: [:each | each disconnect]. exParams isEmpty ifTrue: [ self class connectionClass transactionPhase2FatalSignal raiseSignal: nil ] ifFalse: [ self class connectionClass transactionPhase2FatalSignal raiseWith: exParams errorString: exParams first dbmsErrorString ]]
</methods> <methods> Database.ExternalDatabaseTransaction class <category>instance creation</category>
new "Applications never use transaction objects directly." ^super new initialize.
</methods> <methods> Database.UnsupportedCursorType class <category>class initialization</category>
initialize "Set the default notification message for the receiver" self notifierString: (#unsupportedCursorType << #database >> 'The loaded Client Library does not support scrollable cursors.')
</methods> <methods> Database.DBProfileManager <category>private</category>
connectedProfileIcon ^connectedIcon ifNil: [connectedIcon := ToolbarIconLibrary visualFor: #database]
refreshProfileView (self widgetAt: #profileDataset) invalidate
setProfileList: aList self profileListHolder list: Profiles
statusColumnSpec ^ArbitraryViewSpec new source: #statusColumnVisual:; flags: 0
statusColumnVisual: isConnected ^isConnected ifTrue: [self connectedProfileIcon] ifFalse: [VisualPart new]
updateToolbar (self widgetAt: #toolbarMenu) updateMenu
</methods> <methods> Database.DBProfileManager <category>initialize-release</category>
initialize super initialize. "DbRegistry connectedProfileHolder onChangeSend: #connectedProfileChanged to: self"
on: aProfileCollection self setProfileList: aProfileCollection
postBuildWith: aBuilder | descriptors | descriptors := (self widgetAt: #profileDataset) columnDescriptors. descriptors first rendererSpec: self statusColumnSpec.
release super release. "DbRegistry connectedProfileHolder retractInterestsFor: self"
</methods> <methods> Database.DBProfileManager <category>actions</category>
fileClose self closeRequest
fileImport self class importProfilesFromFile
fileSave self class saveProfilesToFile
helpAbout AboutVisualWorksDialog open
profileNew DBProfileManager addProfileFromUser ifNotNil: [:newProfile | self profileListHolder selection: newProfile]
profileProperties self profileListHolder selectionDo: [:selection | DBProfilePropertiesDialog openOn: selection. self class updateProfile: selection]
profileRemove self profileListHolder selectionDo: [:selection | (Dialog confirm: #repmanRemoveProfileQuestion << #labels >> 'Remove the selected profile?') ifTrue: [self class removeProfile: selection]]
</methods> <methods> Database.DBProfileManager <category>notifications</category>
connectedProfileChanged self refreshProfileView
noticeOfWindowClose: aWindow self release. ^super noticeOfWindowClose: aWindow
profileListDoubleClicked self profileToggleConnection
profileSelected self updateToolbar
</methods> <methods> Database.DBProfileManager <category>aspects</category>
profileListHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^profileListHolder isNil ifTrue: [profileListHolder := SelectionInList new] ifFalse: [profileListHolder]
selectedProfileHolder ^self profileListHolder selectionHolder
</methods> <methods> Database.DBProfileManager <category>menus</category>
menuBar | menu | menu := self class menuBar. menu augmentFrom: self class to: DBProfileManager menuName: #menuBar for: self. "(menu atNameKey: #profileToggleConnection) rawLabel: [self profileToggleConnectionItemLabel]." ^menu
profileListMenu | menu | menu := self class profileListMenu. menu augmentFrom: self class to: DBProfileManager menuName: #listMenu for: self. "(menu atNameKey: #profileToggleConnection) rawLabel: [self profileToggleConnectionItemLabel]." ^menu
</methods> <methods> Database.DBProfileManager <category>testing</category>
isProfileSelected ^self profileListHolder selectionIndex ~= 0
</methods> <methods> Database.DBProfileManager class <category>instance creation</category>
new ^super new on: self profiles
open "Override to use the currently-open manager, if one exists." ^self raiseSingleInstance ifNil: [super open]
</methods> <methods> Database.DBProfileManager class <category>private</category>
addProfiles: aCollection Profiles removeAllSuchThat: [:existingProfile | aCollection anySatisfy: [:newProfile| newProfile = existingProfile]]; addAll: aCollection; sortWith: [:a :b | a name < b name]
importProfilesFromXmlOn: aStream | loadedProfiles | loadedProfiles := self profilesFromXmlOn: aStream. self addProfiles: loadedProfiles
printProfilesAsXmlOn: aStream | writer | aStream nextPutAll: '<?xml version="1.0"?>'; cr. writer := SAXWriter new output: aStream. self profilesAsXmlDocument saxDo: writer
profilesAsXmlDocument | document root | document := Document new. root := Element tag: 'store-profiles'. document addNode: root. Profiles do: [:each | root addNode: each asXmlNode]. ^document
profilesFromXmlOn: aStream | parser document loadedProfiles | parser := XMLParser new. parser validate: false. document := parser parse: aStream. document root tag type = 'store-profiles' ifFalse: [self error: 'invalid file format']. loadedProfiles := document root children collect: [:each | ConnectionProfile fromXmlElement: each]. ^loadedProfiles
replaceProfilesWith: aCollection Profiles removeAllSuchThat: [:anything | true]; addAll: aCollection; sortWith: [:a :b | a name < b name]
</methods> <methods> Database.DBProfileManager class <category>utilities</category>
addProfileFromUser | newProfile | newProfile := Database.ConnectionProfile new. newProfile name: (#Profile1p << #database >> 'Profile <1p>' expandMacrosWith: Profiles size + 1). ^(ConnectionDialog openOn: newProfile) ifTrue: [self addProfile: newProfile. newProfile] ifFalse: [nil]
importProfilesFromFile | stream dialog filename | dialog := OpenFileDialog new. dialog windowTitle: (#importProfilesFilesNamed1C >> 'Import profiles file named:' << #dialogs); acceptButtonLabel: #import >> 'Import' << #dialogs; addFileFilter: 'XML file (*.xml)' pattern: '*.xml'; defaultFilename: 'profiles.xml'; fileCondition: #mustBeOld. filename := dialog select ifNil: [^self]. stream := filename readStream. [self importProfilesFromXmlOn: stream] ensure: [stream close]
saveProfilesToFile | filenameString output | filenameString := Dialog requestFileName: #SaveProfilesToFileNamed << #database >> 'Save profiles to file named:' default: 'profiles.xml'. filenameString isEmpty ifTrue: [^self]. output := filenameString asFilename writeStream. [self printProfilesAsXmlOn: output] ensure: [output close]
</methods> <methods> Database.DBProfileManager class <category>accessing</category>
addProfile: aProfile Profiles add: aProfile; sortWith: [:a :b | a name < b name]
profiles ^Profiles
removeProfile: aProfile Profiles remove: aProfile
sortProfileList Profiles sortWith: [:a :b | a name < b name]
updateProfile: aProfile | index | index := Profiles indexOf: aProfile. index = 0 ifFalse: [Profiles changed: #at: with: index]. Store.DbRegistry ifDefinedDo: [:registry| registry connectedProfileHolder value = aProfile ifTrue: [registry connectedProfileHolder changed: #value]]
</methods> <methods> Tools.DBProfileListSetting <category>persistence</category>
addStateXmlElementsTo: anElement profiles do: [:each | anElement addNode: each asXmlNode]
restoreFrom: aSettingSnapshot | newProfiles | newProfiles := OrderedCollection new. aSettingSnapshot stateNodes do: [:each | | profile | profile := ConnectionProfile fromXmlElement: each. newProfiles add: profile]. profiles := newProfiles. self installProfiles
</methods> <methods> Tools.DBProfileListSetting <category>initialize-release</category>
initialize super initialize. profiles := DBProfileManager profiles copy asList
</methods> <methods> Tools.DBProfileListSetting <category>actions</category>
installProfiles DBProfileManager replaceProfilesWith: profiles
profiles ^profiles
resetProfiles profiles := DBProfileManager profiles copy asList
</methods> <methods> Tools.DBProfileListSetting class <category>instance creation</category>
new ^super new initialize
</methods> <methods> Tools.DBProfilePropertiesDialog <category>aspects</category>
databaseHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^databaseHolder isNil ifTrue: [databaseHolder := String new asValue] ifFalse: [databaseHolder]
databaseListHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^databaseListHolder isNil ifTrue: [databaseListHolder := List new asValue] ifFalse: [databaseListHolder]
environmentHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^environmentHolder isNil ifTrue: [environmentHolder := String new asValue] ifFalse: [environmentHolder]
nameHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^nameHolder isNil ifTrue: [nameHolder := String new asValue] ifFalse: [nameHolder]
passwordHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^passwordHolder isNil ifTrue: [passwordHolder := String new asValue] ifFalse: [passwordHolder]
userNameHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^userNameHolder isNil ifTrue: [userNameHolder := String new asValue] ifFalse: [userNameHolder]
</methods> <methods> Tools.DBProfilePropertiesDialog <category>private</category>
canAccept ^self validateRequiredValues and: [self validateName]
hasRequiredValues ^(self isProvided: self nameHolder value) and: [(self isProvided: self databaseHolder value) and: [self isProvided: self userNameHolder value]]
initializeAspects profileHolder := ValueHolder new. acceptTrigger := false asValue. nameHolder := self profileAspect: #name. databaseHolder := self profileAspect: #driverClassName. environmentHolder := self profileAspect: #environment. userNameHolder := self profileAspect: #userName. passwordHolder := self profileAspect: #password.
isProvided: anObject ^anObject notNil and: [anObject notEmpty]
knownDatabaseInterfaces ^((ExternalDatabaseConnection allSubclasses select: [:cl | cl kind notNil]) asSortedCollection: [:a :b | a kind <= b kind]) collect: [:each | each name]
nameIsUnique | name | name := self nameHolder value. ^(DBProfileManager profiles anySatisfy: [:any | any name = name]) not or: [profileHolder value name = name]
profileAspect: aSymbol | aspect | aspect := (AspectAdaptor forAspect: aSymbol) subjectChannel: profileHolder; yourself. ^BufferedValueHolder subject: aspect triggerChannel: acceptTrigger
validateName ^self nameIsUnique ifTrue: [true] ifFalse: [Dialog warn: ((#nameXIsAlreadyInUsePleaseChooseAnother << #dialogs >> 'The name "<1s>" is already in use. Please choose a different name.') expandMacrosWith: self nameHolder value). false]
validateRequiredValues ^self hasRequiredValues ifTrue: [true] ifFalse: [Dialog warn: #aBunchOfValuesAreRequired << #dialogs >> 'Name, interface, and a user name are required'. false]
</methods> <methods> Tools.DBProfilePropertiesDialog <category>initialize-release</category>
initialize super initialize. self initializeAspects. self databaseListHolder value: self knownDatabaseInterfaces
profile: aConnectionProfile profileHolder value: aConnectionProfile
</methods> <methods> Tools.DBProfilePropertiesDialog <category>actions</category>
ok self canAccept ifTrue: [acceptTrigger value: true. self accept value: true]
</methods> <methods> Tools.DBProfilePropertiesDialog class <category>instance creation</category>
openOn: aConnectionProfile ^self new profile: aConnectionProfile; open
</methods> <methods> Database.ByteFieldDescriptor <category>initialize-release</category>
template: aTemplate max: anInteger template := aTemplate. max := anInteger
</methods> <methods> Database.ByteFieldDescriptor <category>accessing</category>
MaxColumnConstraint ^max
Template ^template
Type ^template class maxColumnConstraint: max
yourself ^template
</methods> <methods> Database.ByteFieldDescriptor <category>testing</category>
includes: string ^false
isKindOf: aClass "Answer a Boolean as to whether the class, aClass, is a superclass or class of the receiver." template class == aClass ifTrue: [^true] ifFalse: [^template class inheritsFrom: aClass]
</methods> <methods> Database.ByteFieldDescriptor <category>printing</category>
do: block '<byte field>' do: [:c | block value: c]
printOn: stream super printOn: stream. max notNil ifTrue: [stream nextPutAll: (#Max << #database >> ' (max=') asString. max printOn: stream. stream nextPut: $)]
</methods> <methods> Database.UnableToDestroyConnectionPool class <category>class initialization</category>
initialize "Set the default notification message for the receiver" self notifierString: (#errConnectionPoolDestroy << #database >> 'unable to destroy connection pool.')
</methods> <methods> Database.ConnectionDialog <category>aspects</category>
connectionProfileHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^connectionProfileHolder isNil ifTrue: [connectionProfileHolder := String new asValue] ifFalse: [connectionProfileHolder]
connectionProfileListHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^connectionProfileListHolder isNil ifTrue: [connectionProfileListHolder := List new asValue] ifFalse: [connectionProfileListHolder]
databaseHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^databaseHolder isNil ifTrue: [databaseHolder := String new asValue] ifFalse: [databaseHolder]
databaseListHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^databaseListHolder isNil ifTrue: [databaseListHolder := List new asValue] ifFalse: [databaseListHolder]
environmentHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^environmentHolder isNil ifTrue: [environmentHolder := String new asValue] ifFalse: [environmentHolder]
environmentListHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^environmentListHolder isNil ifTrue: [environmentListHolder := List new asValue] ifFalse: [environmentListHolder]
passwordHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^passwordHolder isNil ifTrue: [passwordHolder := String new asValue] ifFalse: [passwordHolder]
userNameHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^userNameHolder isNil ifTrue: [userNameHolder := String new asValue] ifFalse: [userNameHolder]
userNameListHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^userNameListHolder isNil ifTrue: [userNameListHolder := List new asValue] ifFalse: [userNameListHolder]
</methods> <methods> Database.ConnectionDialog <category>private-profile list</category>
addOrReplaceProfile: aProfile "If there is a profile with the same name as that of the argument, replace it with the argument." (self class profiles includes: aProfile) ifTrue: [self class profiles remove: aProfile]. self class profiles add: aProfile.
allProfiles ^self class profiles copyWith: self lastUsedProfile
currentProfile ^currentProfileHolder value
currentProfile: aProfile currentProfileHolder value: aProfile. self connectionProfileHolder value: ((self class profiles anySatisfy: [:some | some name = aProfile name]) ifTrue: [aProfile name] ifFalse: [nil])
deleteProfileNamed: aString | profile | profile := self class profiles detect: [:some | some name = aString]. self class profiles remove: profile
lastUsedProfile self class lastUsedProfile isNil ifTrue: [self class lastUsedProfile: self createNewProfile]. ^self class lastUsedProfile
updateProfileList self connectionProfileListHolder value: self knownProfileNames
</methods> <methods> Database.ConnectionDialog <category>private</category>
createNewProfile | profile databaseNames | profile := ConnectionProfile new. databaseNames := self knownDatabases. databaseNames isEmpty ifFalse: [profile driverClassName: databaseNames first]. ^profile
knownDatabases ^((ExternalDatabaseConnection allSubclasses select: [:cl | cl kind notNil]) asSortedCollection: [:a :b | a kind <= b kind]) collect: [:each | each name]
knownEnvironmentStrings ^(self allProfiles collect: [:each | each environment]) asSet
knownProfileNames ^(self class profiles collect: [:each | each name]) asSortedCollection
knownUserNames "Collect user names used in the existing connection profiles." ^(self allProfiles collect: [:each | each userName]) asSet
resetProfileName self currentProfile resetName. self connectionProfileHolder value: nil. self profileChanged
</methods> <methods> Database.ConnectionDialog <category>actions</category>
connect self class lastUsedProfile: self currentProfile. self accept value: true
deleteProfile | nameToDelete | nameToDelete := self connectionProfileHolder value. nameToDelete isNil ifTrue: [^self]. (Dialog confirm: (#GenKeyDeleteProfile << #database >> 'Are you sure you want to delete this connection profile?')) ifFalse: [^self]. self deleteProfileNamed: nameToDelete; currentProfile: self createNewProfile; updateProfileList
saveProfile | name savedProfile | name := Dialog request: (#ProfileName << #database >> 'Profile name:') initialAnswer: self currentProfile originalName. name isEmpty ifTrue: [^self]. self currentProfile name: name. savedProfile := self currentProfile copy. self addOrReplaceProfile: savedProfile; currentProfile: self currentProfile; updateProfileList
</methods> <methods> Database.ConnectionDialog <category>notifications</category>
databaseChanged self resetProfileName
environmentChanged self resetProfileName
passwordChanged self resetProfileName
profileChanged | hasName | hasName := self currentProfile name notNil. self builder window notNil ifTrue: [(self builder componentAt: #saveProfile) isEnabled: hasName not. (self builder componentAt: #deleteProfile) isEnabled: hasName. (self builder componentAt: #connect) isEnabled: self currentProfile isValid]
profileSelected | name profile | name := self connectionProfileHolder value. name isNil ifTrue: [^self]. profile := self class profiles detect: [:some | some name = name]. currentProfileHolder value: profile copy
userNameChanged self resetProfileName
</methods> <methods> Database.ConnectionDialog <category>initialize-release</category>
initialize super initialize. self initializeAspects. self updateProfileList; currentProfile: self lastUsedProfile copy. self databaseListHolder value: self knownDatabases. self environmentListHolder value: self knownEnvironmentStrings asSortedCollection. self userNameListHolder value: self knownUserNames asSortedCollection. self connectionProfileHolder onChangeSend: #profileSelected to: self. currentProfileHolder onChangeSend: #profileChanged to: self
initializeAspects currentProfileHolder := ValueHolder new. databaseHolder := self profileAspect: #driverClassName. environmentHolder := self profileAspect: #environment. userNameHolder := self profileAspect: #userName. passwordHolder := self profileAspect: #password
postBuildWith: aBuilder #(databaseCombo environmentCombo userNameCombo passwordField) do: [:widgetName | (builder componentAt: widgetName) widget controller continuousAccept: true]. self profileChanged "cause update"
profileAspect: aSymbol ^(AspectAdaptor forAspect: aSymbol) subjectChannel: currentProfileHolder; yourself
</methods> <methods> Database.ConnectionDialog class <category>utilities</category>
connect: aProfile "Connect a ConnectionProfile (presumably selected using the dialog) and answer the resulting connection or nil if connection fails. In case of failure, show a dialog box. See also #unsafeConnect:." ^Cursor database showWhile: [[self unsafeConnect: aProfile] on: ExternalDatabaseConnection externalDatabaseErrorSignal do: [:ex | Dialog warn: (self messageFor: ex from: aProfile). ex return: nil]]
messageFor: exception from: aProfile "Answer a suitable message to display to the user (a String) to explain the exception." | parameter message | (exception isMemberOf: (aProfile driverClass authenticationFailureSignal)) ifTrue: [^exception errorString]. ((parameter := exception parameter) notNil and: [parameter isEmpty not and: [(message := (parameter at: 1) dbmsErrorString) notNil "ugh" and: [message isEmpty not]]]) ifTrue: [^message] ifFalse: [^exception errorString]
unsafeConnect: aProfile "Similar to #connect: but without the error handling. Connection exceptions are not intercepted and are available for the client code to take care of." | connection | connection := aProfile asConnection. connection connect: aProfile password. ^connection
</methods> <methods> Database.ConnectionDialog class <category>accessing</category>
chooseProfile "Open the connection dialog. After it is closed answer either the connection profile with parameters selected by the user if it was accepted or nil if the dialog was cancelled." | instance | instance := self new. ^instance open ifTrue: [instance currentProfile] ifFalse: [nil]
chooseProfileInitially: aProfileOrNil "Open the connection dialog. After it is closed answer either the connection profile with parameters selected by the user if it was accepted or nil if the dialog was cancelled." | instance | instance := self new. aProfileOrNil notNil ifTrue: [instance currentProfile: aProfileOrNil]. ^instance open ifTrue: [instance currentProfile] ifFalse: [nil]
lastUsedProfile ^lastUsedProfile
lastUsedProfile: aProfile lastUsedProfile := aProfile
profiles ^DBProfileManager profiles
</methods> <methods> Database.ConnectionDialog class <category>convenience</category>
openConnection "Open the dialog and then open the database connection that was selected. Answer the opened connection or nil if either the dialog was cancelled or the connection failed." | profile | profile := self chooseProfile. ^profile isNil ifTrue: [nil] ifFalse: [self connect: profile]
openConnectionIfCancelled: aBlock "Open the dialog and then open the database connection that was selected. Answer the opened connection or nil if the connection failed. Evaluate aBlock if the dialog was cancelled." | profile | profile := self chooseProfile. ^profile isNil ifTrue: [aBlock value] ifFalse: [self connect: profile]
</methods> <methods> Tools.DBProfileListPage <category>notifications</category>
profileSelectionChanged | hasSelection | builder isNil ifTrue: [^self]. hasSelection := self profileListHolder selection notNil. #(removeButton propertiesButton) do: [:each | (self wrapperAt: each) isEnabled: hasSelection]
triggered manager triggerChannel value ifTrue: [self accept] ifFalse: [self reset]
</methods> <methods> Tools.DBProfileListPage <category>private</category>
accept setting installProfiles
reset setting resetProfiles. self profileListHolder list: setting profiles
</methods> <methods> Tools.DBProfileListPage <category>actions</category>
addProfile | newProfile | newProfile := ConnectionProfile new. newProfile name: (#Profile1p << #database >> 'Profile <1p>' expandMacrosWith: self profileListHolder list size + 1). (DBProfilePropertiesDialog openOn: newProfile) ifTrue: [(self profileListHolder list) add: newProfile; sortWith: [:a :b | a name < b name]. self profileListHolder selection: newProfile. manager tickle]
importSnapshots: aCollection | snapshot newProfiles | snapshot := aCollection detect: [:some | some id = setting id] ifNone: [^self]. newProfiles := List new. snapshot stateNodes do: [:each | newProfiles add: (ConnectionProfile fromXmlElement: each)]. self profileListHolder list removeAllSuchThat: [:each | true]; addAll: newProfiles. self tickle
profileProperties self profileListHolder selectionDo: [:selection | DBProfilePropertiesDialog openOn: selection. manager tickle]
removeProfile self profileListHolder selectionDo: [:selection | (Dialog confirm: #RemoveThisProfileQ << #labels >> 'Remove this profile?') ifTrue: [self profileListHolder list remove: selection. manager tickle]]
</methods> <methods> Tools.DBProfileListPage <category>initialize-release</category>
manager: aManager super manager: aManager. manager triggerChannel onChangeSend: #triggered to: self
postBuildWith: aBuilder super postBuildWith: aBuilder. self profileSelectionChanged
setting: aDBProfileListSetting setting := aDBProfileListSetting. self profileListHolder list: setting profiles. self profileListHolder selectionIndexHolder onChangeSend: #profileSelectionChanged to: self.
</methods> <methods> Tools.DBProfileListPage <category>accessing</category>
helpText "This message shows the help text for the database profiles setting page. In order to provide bold emphasis whilst still using message catalogs, the button and field names were extracted and put into a separate usermessage." | args argEmphases msg | args := (#databaseProfilesHelpItems << #dialogs >> 'Add... Remove... Properties... Name Interface Environment Username Password') asString tokensBasedOn: Character space. argEmphases := Array new: args size withAll: #bold. msg := #databaseProfilesHelp << #dialogs >> 'To create a new database profile, click <1s>. To delete a profile, select it and click <2s>. To edit a profile, select it and click <3s>. A profile setting consists of the following properties. <4s> - Name of the profile setting, so you can remember it. <5s> - Database vendor connection type (eg., OracleConnection). <6s> - Database server indicator, called an environment string. <7s> - Database user name. <8s> - Database password.'. ^msg expandMacrosWithEmphasis: #normal arguments: args emphases: argEmphases
settings ^Array with: setting
</methods> <methods> Tools.DBProfileListPage <category>aspects</category>
profileHolder ^nil asValue
profileListHolder "This method was generated by UIDefiner. Any edits made here may be lost whenever methods are automatically defined. The initialization provided below may have been preempted by an initialize method." ^profileListHolder isNil ifTrue: [profileListHolder := SelectionInListSortAware new. profileListHolder selectionIndexHolder compute: [:v | self profileHolder value: profileListHolder selection]. profileListHolder] ifFalse: [profileListHolder]
</methods> <methods> Database.ExternalDatabaseSession <category>initialize-release</category>
initialize super initialize. traceLevel := self class traceLevel. self state: #new. connection := nil. self releaseBindings. allocateForEachRow := true. useNamedOutputBinding := false. blockFactor := 1. rowBuffersHolder := nil asValue. self scrollable: false.
</methods> <methods> Database.ExternalDatabaseSession <category>accessing</category>
allocateForEachRow "Answer whether the answer stream should create a copy of the output bind object to hold each row." ^allocateForEachRow
allocateForEachRow: aBoolean "Specify whether the answer stream should create a copy of the output bind object to hold each row." allocateForEachRow := aBoolean
bindInput "Answer the object from which input values will be obtained for host variable references in the SQL text." ^bindInput
bindInput: aBindObject "Supply aBindObject as the object from which input values should be obtained for host variable references in the SQL text. Host variables may be specified using either a positional or a named notation. The driver may limit to only one form. When using the positional form (a ?), all host variable references (including the named ones) are implicitly ordered by their position in the SQL-text. The n-th variable of aBindObject is used for the n-th host variable reference. If aBindObject has both instance variables and indexed variables, only the indexed variables will be used. When using the named form, the leading colon is removed and the name is expected to be an accessing method on aBindObject (i.e. aBindObject is sent perform: with the name converted to a symbol as the argument)." bindInput := aBindObject
bindOutput "Answer the bind object used for returned rows." ^bindOutput
bindOutput: aBindObject "Specify the bind object used for returned rows." self bindOutputIndexed: aBindObject
bindOutputIndexed: aBindObject "Specify the bind object used for returned rows. aBindObject may have either instance variables or indexed variables; if both are present, the indexed variables are used. Rows are mapped into aBindObject using positional correspondence between the row's columns and aBindObject's variables (i.e., column 1 goes into variable 1, etc.). Variables in aBindObject may be skipped in the positional mapping if they contain an instance of Object. This is useful when only a few columns of a table are needed." bindOutput := aBindObject. useNamedOutputBinding := false. self rowAdaptors: nil.
bindOutputNamed: aBindObject "Specify the bind object used for returned rows. Rows are mapped into aBindObject using the column names, postfixed with a colon, as mutator messages. Thus, each column must have a name that is suitable for conversion to a symbol, and aBindObject must respond to such a message." bindOutput := aBindObject. useNamedOutputBinding := true. self rowAdaptors: nil.
blockFactor "Answer the blocking factor for using buffers to accelerate fetching of row data." ^blockFactor
blockFactor: aSmallInteger "Specify the blocking factor to use when fetching of row data. This may improve application performance at the expense of memory. The blocking factor is optional and will be ignored if the driver does not support fetching multiple rows at a time. The application still uses next to obtain a single row at a time. However, the use of WHERE CURRENT OF may not be allowed as the database system cannot be sure of which row the application is referring to." blockFactor := aSmallInteger
query "Answer SQL text for this session." ^query
scrollable "Determins whether the cursor is scrollable or not." ^scrollable
scrollable: aBoolean "Determins whether the cursor is scrollable or not." scrollable := aBoolean
</methods> <methods> Database.ExternalDatabaseSession <category>data processing</category>
answer "Wait for the currently executing SQL statement to complete processing. Exceptions are raised for any errors. The value answered will be an answer stream, #noAnswerStream or #noMoreAnswers. #noAnswerStream is used to indicate successful processing, but no answer stream was generated. In order to maintain application portability with database libraries that allow multiple SQL statements in one prepare:, this message should be sent until it returns #noMoreAnswers" ( self state == #executing ) ifTrue: [ self delayUntilReady ]. ^self answerOfClass: self class answerStreamClass
cancel "Interrupt the processing of the prepared SQL text or stored procedure." self isExecuting ifFalse: [ self class connectionClass invalidSessionStateSignal raise ]. answerStream notNil ifTrue: [ answerStream dismiss ]. ( self state == #fetchingData ) ifTrue: [ self cancelAnswerSetExternal ]. self cancelExternal. self state: #prepared
connect "Optional: gives direct control over when external resources are acquired. Will be done automatically when prepare: is invoked." ( self state == #new ) ifFalse: [ self class connectionClass invalidSessionStateSignal raise ]. ( connection isNil or: [ connection isConnected not ] ) ifTrue: [ self class connectionClass connectionNotOpenSignal raise ]. self acquire. self state: #connected
disconnect "Optional: gives direct control over when external resources are dismissed." ( self state == #new ) ifTrue: [ ^self ]. self dismiss. self state: #new
execute "Execute the prepared SQL statement." "Should we clean up after any previous work?" self isExecuting ifTrue: [ self cancel ]. ( self state == #prepared ) ifFalse: [ self class connectionClass invalidSessionStateSignal raise ]. [ "Begin unwind protection." self bindExternal. self state: #executing. self executeExternal. "End unwind protection." ] ifCurtailed: [ self state: #prepared ]
prepare: aString "Prepare aString for processing." self startPrepare. "Save the query, and prepare it for parameter binding." self setupQuery: aString. "We're finally ready to prepare the SQL. If there is a problem, make sure the state is appropriate." [ "Begin unwind protection." self state: #prepared. self prepareExternal. "End unwind protection." ] ifCurtailed: [ self state: #connected ]
rowCount "Answer an Integer representing the number of rows affected by the previous query. Valid only after the query has been answered." ^self subclassResponsibility
</methods> <methods> Database.ExternalDatabaseSession <category>testing</category>
isReady "Answer a boolean for whether processing has completed and an answer is ready." | stateTemp | (stateTemp := self state) == #executing ifTrue: [ (self readyExternal) ifTrue: [ self state: #ready. ^true ] ] ifFalse: [ (stateTemp == #ready or: [ stateTemp == #validResults or: [ stateTemp == #fetchingData ] ] ) ifFalse: [ self class connectionClass invalidSessionStateSignal raise ]. ^true ]. ^false
useNamedOutputBinding "Answer true if the session is using named output binding" ^useNamedOutputBinding
</methods> <methods> Database.ExternalDatabaseSession <category>private-accessing</category>
answerStream: anAnswerStreamOrNil "Set the session's answer stream." answerStream := anAnswerStreamOrNil
columnDescriptions "Answer the column descriptions array" ^columnDescriptions
columnDescriptions: anArray "Set the column descriptions array" columnDescriptions := anArray
connection "Answer the connection in which receiver executes." ^connection
connection: aConnection "Set the connection in which receiver should execute." connection := aConnection
numColumns "Answer the number of columns" ^numColumns
numColumns: anInteger "Save the number of columns" numColumns := anInteger
rowAdaptors: aSequenceableCollection rowAdaptors := aSequenceableCollection
rowBuffers ^rowBuffersHolder value
rowBuffers: aSequenceableCollection rowBuffersHolder value: aSequenceableCollection
rowBuffersHolder ^rowBuffersHolder
rowBuffersHolder: aValueHolder rowBuffersHolder := aValueHolder
</methods> <methods> Database.ExternalDatabaseSession <category>private-activation</category>
acquire "Acquire resources necessary to execute SQL, and register as a participant of our connect." connection addParticipant: self. [ self acquireExternal notNil ifTrue: [ "Assert: external resource held." self class register: self ] ] ifCurtailed: [ connection removeParticipant: self ]
activate "Don't bother reconnecting now." connection removeParticipant: self. self class unregister: self. self state: #new
dismiss self isExecuting ifTrue: [ self cancel ]. self releaseBuffersAndAdaptors. self releaseBindings. super dismiss. connection removeParticipant: self
quiesce "Quiesce all connections to external resources." self state == #paused ifTrue: [ ^self ]. answerStream notNil ifTrue: [ answerStream dismiss ]. [ self dismissExternal ] ensure: [ self state: #paused ]
</methods> <methods> Database.ExternalDatabaseSession <category>private-answer set</category>
aboutToAnswer "Do any final work before fetching results from an answer set." ^self
acquireBuffers "Acquire buffers for fetching the answer set from the server." | buffers | "Buffers will only exist here if they're OK to reuse." self rowBuffers notNil ifTrue: [ ^self ]. buffers := Array new: numColumns. [ "Begin unwind protection." 1 to: numColumns do: [ :column | buffers at: column put: (self allocateRowBufferExternal: column) ]. "End unwind protection." ] ifCurtailed: [ "give back any pointers we might have acquired as none will be used." 1 to: numColumns do: [ :col | | buf | (buf := buffers at: col) notNil ifTrue: [ buf free ] ] ]. self rowBuffers: buffers
advanceExternal "Advance the current row. If blockFactor is supported, this may entail fetching many rows but doing it infrequently. If there are no more rows, answer nil. Otherwise, answering self is sufficient." ^self subclassResponsibility
allocateRowBufferExternal: aColumn "Answer an object describing space allocated for holding one column's worth of information as returned by the dbms api. The driver is responsible for defining the structure of the object returned." ^self subclassResponsibility
answerOfClass: anAnswerStreamClass "Answer an instance of the given subclass of ExternalDatabaseAnswerStream" "Assert: anAnswerStreamClass isKindOf: ExternalDatabaseAnswerStream" | initialAnswer | initialAnswer := ( self state == #ready ). self state: #validResults. initialAnswer ifTrue: [ "Verify that the query executed without error." self resultsExternal ] ifFalse: [ "If we're still holding on to a prior answer stream, dismiss it." answerStream notNil ifTrue: [ answerStream close ]. "Assert: self state == #validResults" self moreResultsExternal ifFalse: [ self state: #prepared. ^#noMoreAnswers ] ]. self hasAnswerSetExternal ifTrue: [ | answer | initialAnswer ifFalse: [ "Previous descriptions/buffers are no longer valid" self releaseBuffers. self releaseAdaptors. self columnDescriptions: nil ]. self getColumnDescriptions. self acquireBuffers. self setupAdaptors. self aboutToAnswer. answer := anAnswerStreamClass newForSession: self. self answerStream: answer. self state: #fetchingData. ^answer ]. ^#noAnswerStream.
answerStreamDismissed "Note that the answer stream has dismissed itself." self answerStream: nil
cancelAnswerSet "Cancel an answer set. Used to release server resources." self cancelAnswerSetExternal. self state: #validResults.
cancelAnswerSetExternal "Cancel any resources associated with the current answer set" self subclassResponsibility
describeAnswerColumns "Fill in the columnDescriptions array." | descrs index temp | descrs := Array new writeStream. index := 0. [ ( temp := self getColumnDescriptionExternal: (index := index + 1) ) notNil ] whileTrue: [ descrs nextPut: temp ]. self columnDescriptions: (index > 1 ifTrue: [ descrs contents ] ifFalse: [ nil ]). self numColumns: (index - 1).
getColumnDescriptionExternal: aColumn ^self subclassResponsibility
getColumnDescriptions "Get descriptions for the columns in the answer set" "If column descriptions exist, they're safe to re-use." ( columnDescriptions == nil ) ifFalse: [ ^self ]. ( resultTemplate == nil ) ifTrue: [ self describeAnswerColumns ] ifFalse: [ self answerColumnsFromTemplate ]
getFieldExternal: aColumn ^self subclassResponsibility
getRowExternal: fetchOrientation offset: fetchOffset "Answer with the next row of data. Answer nil at end" | currentRowCopy | ( (self advanceExternal: fetchOrientation offset: fetchOffset) == nil ) ifTrue: [ "We've exhausted the answer set. No DBMS cancel is necessary." self state: #validResults. ^nil ]. "If we have a resultTemplate, use it to provide the answer." ( resultTemplate == nil ) ifFalse: [ bufferIndex := 1. ^self nextViaTemplate: resultTemplate ]. currentRowCopy := allocateForEachRow ifTrue: [ currentRow copy ] ifFalse: [ currentRow ]. 1 to: numColumns do: [ :index | (rowAdaptors at: index) value: currentRowCopy value: (self getFieldExternal: index) ]. ^currentRowCopy
hasAnswerSetExternal "Answer true if the SQL-statement (batch) being processed returns an answer set." ^self subclassResponsibility
nextRowExternal "Answer with the next row of data. Answer nil at end" | currentRowCopy | ( self advanceExternal == nil ) ifTrue: [ "We've exhausted the answer set. No DBMS cancel is necessary." self state: #validResults. ^nil ]. "If we have a resultTemplate, use it to provide the answer." ( resultTemplate == nil ) ifFalse: [ bufferIndex := 1. ^self nextViaTemplate: resultTemplate ]. currentRowCopy := allocateForEachRow ifTrue: [ currentRow copy ] ifFalse: [ currentRow ]. 1 to: numColumns do: [ :index | (rowAdaptors at: index) value: currentRowCopy value: (self getFieldExternal: index) ]. ^currentRowCopy
releaseAdaptors "Release existing adaptors." "Subclasses may release subclass-specific resources before invoking this method." self rowAdaptors: nil
releaseBuffers "Release buffers and their associated resources." "Subclasses may release subclass-specific resources before invoking this method." self rowBuffers: nil
releaseBuffersAndAdaptors "Release buffers, adaptors, and their associated resources." "Subclasses may release subclass-specific resources before invoking this method." "Discard previous buffers, descriptors, and adaptors." self releaseBuffers. self releaseAdaptors. self columnDescriptions: nil. self numColumns: nil.
setupAdaptors "Setup adaptors for populating the bindOutput object" | adaptors bind directInstVarAccess bindSize adaptorIndex currentValue | "Adaptors may already be set up." rowAdaptors notNil ifTrue: [ ^self ]. adaptors := Array new: numColumns. "If no template was specified we'll reify fetched rows as Arrays" ( bind := self bindOutput ) isNil ifTrue: [ bind := Array new: numColumns ]. currentRow := bind. "Determine which type of adaptor to build" directInstVarAccess := false. ( bind class isVariable ) ifTrue: [ bindSize := bind size ] ifFalse: [ bindSize := bind class instSize. directInstVarAccess := true ]. useNamedOutputBinding ifTrue: [ bindSize := numColumns ]. "Make a block to insert new values for each slot in the bind object. This exploits the concept of copying-blocks. It is assumed that the local variables referenced in the blocks used below as the putAdaptor will be copied on the block and thus be frozen at the time the execution path passes thru the creation of the block." adaptorIndex := 0. 1 to: bindSize do: [ :bindIndex | | putAdaptor | useNamedOutputBinding ifTrue: [ | colName putSelector | ( colName := (columnDescriptions at: bindIndex) name ) isNil ifTrue: [ self class connectionClass invalidDescriptorCountSignal raise ]. currentValue := bind perform: colName asSymbol. putSelector := (colName , ':') asSymbol. putAdaptor := [ :subj :value | subj perform: putSelector with: value ] ] ifFalse: [ directInstVarAccess ifTrue: [ currentValue := bind instVarAt: bindIndex. putAdaptor := [ :subj :value | subj instVarAt: bindIndex put: value ] ] ifFalse: [ currentValue := bind at: bindIndex. putAdaptor := [ :subj :value | subj at: bindIndex put: value ] ] ]. "Skip slots in the bind object that contain instances of Object." ( currentValue class == Object ) ifFalse: [ adaptorIndex := adaptorIndex + 1. ( adaptorIndex > numColumns ) ifTrue: [ self class connectionClass invalidDescriptorCountSignal raise ]. adaptors at: adaptorIndex put: putAdaptor ] ]. "We must bind exactly as many columns as there are non-skipped slots in the bind object." useNamedOutputBinding ifFalse: [ ( adaptorIndex == numColumns ) ifFalse: [ self class connectionClass invalidDescriptorCountSignal raise ] ]. self rowAdaptors: adaptors.
</methods> <methods> Database.ExternalDatabaseSession <category>private-binding</category>
bindExternal "Bind values to parameters in the query, avoiding unnecessary rebinding where possible." "Subclasses that do not support binding must override this method to provide a substitute." "For each bind marker in the query fragments, get the corresponding value from the bindInput object. If the value isn't already bound, bind and remember it." 2 to: queryFragments size by: 2 do: [ :index | | bindMarker value | bindMarker := queryFragments at: index. value := self inBindInputAt: bindMarker. ( self boundValueAt: bindMarker is: value ) ifFalse: [ self bindValue: value at: bindMarker. self bindValues at: bindMarker put: value. ] ].
bindValue: aValue at: aPosition "Bind aValue at aPosition." ^self subclassResponsibility
bindValues "Answer with the receiver's bind value dictionary." ^bindValues notNil ifTrue: [ bindValues ] ifFalse: [ bindValues := IdentityDictionary new ]
boundValueAt: aPosition is: aValue "Answer true if there is a parameter bound at aPosition, and if its value is the same as aValue. Otherwise, answer false." | boundValue | boundValue := self bindValues at: aPosition ifAbsent: [ ^false ]. boundValue = aValue ifTrue: [ ^true ]. self bindValues removeKey: aPosition. ^false
inBindInputAt: bindMarker "Answer the value in bindInput that corresponds to the bindMarker. If the bindMarker is an integer, the value will be in an instance variable or indexed variable index. If the bindMarker is a symbol, bindInput is assumed to respond to the bindMarker as a message with the value." ^bindMarker isInteger ifTrue: [ bindInput class isVariable ifTrue: [ bindMarker > bindInput size ifTrue: [ self class connectionClass invalidDescriptorCountSignal raise ]. bindInput at: bindMarker ] ifFalse: [ bindMarker > bindInput class instSize ifTrue: [ self class connectionClass invalidDescriptorCountSignal raise ]. bindInput instVarAt: bindMarker ] ] ifFalse: [ bindInput perform: bindMarker ]
prepareExternal "Send the query text to the external DBMS to be prepared." ^self subclassResponsibility
releaseBindings "Release bind values." bindValues := nil.
scanMarkerFrom: aStream "Scan a parameter marker from aStream." ^self scanNumberOrTokenFrom: aStream doing: [:number :tokenStream | number == nil ifTrue: [| token | tokenStream isNil ifTrue: [nil] ifFalse: [token := tokenStream contents. token isEmpty ifTrue: [self class invalidParameterMarkerSignal raise]. token asSymbol]] ifFalse: [number]].
scanNumberOrTokenFrom: aStream doing: aBlock "Scan a parameter marker from aStream." | ch rule number tokenStream | aStream atEnd ifTrue: [^aBlock value: nil value: #() readStream]. ( ch := aStream next ) isDigit ifTrue: [ rule := [ :c | c isDigit ]. number := 0 ] ifFalse: [ rule := [ :c | c isAlphaNumeric or: [ c == $_ ] ]. tokenStream := WriteStream on: (String new: 16). number := nil ]. [ ch notNil and: [ rule value: ch ] ] whileTrue: [ number == nil ifTrue: [ tokenStream nextPut: ch ] ifFalse: [ number := (number * 10) + ch digitValue ]. ch := aStream atEnd ifTrue: [nil] ifFalse: [aStream next] ]. ch notNil ifTrue: [ aStream skip: -1 ]. ^aBlock value: number value: tokenStream.
setupQuery: aString "Save the query. Break the query into an Array of fragments, isolating each parameter marker. Save the fragmented form." "The size of the fragment array will always be odd, with parameter markers at even positions. Markers of the form '?' and ':number' are converted to index-into-bindInput-object form. Markers of the form ':name' are converted to #name." | stream fragmentStream collection markerCount ch prevCh marker cr tab space | query := aString. stream := query readStream. fragmentStream := WriteStream on: (aString class new: query size). collection := OrderedCollection new: 13. markerCount := 0. ch := $?. cr := Character cr. tab := Character tab. space := Character space. [ stream atEnd ] whileFalse: [ prevCh := ch. ch := stream next. ( ch == $' or: [ ch == $" ] ) ifTrue: [ fragmentStream nextPut: ch; nextPutAll: (stream through: ch) ] ifFalse: [ ( ch == $? or: [ (ch == $:) and: [ prevCh isAlphaNumeric not and: [ stream atEnd not and: [stream peek isAlphaNumeric ]] ] ] ) ifTrue: [ markerCount := markerCount + 1. collection add: fragmentStream contents. fragmentStream reset. ( ch == $? ) ifTrue: [ collection add: markerCount ] ifFalse: [ marker := self scanMarkerFrom: stream. "ch does not reflect that last character, but that's O.K." collection add: marker ] ] ifFalse: [ (ch == cr or: [ ch == tab]) ifTrue: [ ch := space ]. fragmentStream nextPut: ch ] ] ]. collection add: fragmentStream contents. queryFragments := collection.
startPrepare "Get the receiver into a reasonable state to prepare a new SQL statement." | stateTemp | "Should we clean up after any previous work?" self isExecuting ifTrue: [ self cancel ]. "If not already held, acquire the right to execute SQL statements." ( self state == #new ) ifTrue: [ self connect ] . "Enforce: we're in a legal state to prepare new SQL text." ( (stateTemp := self state) == #connected or: [ stateTemp == #prepared ] ) ifFalse: [ self class connectionClass invalidSessionStateSignal raise ]. "Release any previously held buffers and adaptors." self releaseBuffersAndAdaptors. "Previous bind parameters are now invalid." self releaseBindings. "Drop the old query texts." query := nil. queryFragments := nil. "Default to a connected state" self state: #connected
</methods> <methods> Database.ExternalDatabaseSession <category>private-execution</category>
cancelExternal ^self subclassResponsibility
delayUntilReady "Delay until the server is ready." "Assert: self state == #executing" | ticks | ticks := 1. [ self isReady ] whileFalse: [ (Delay forMilliseconds: ticks) wait. ticks < 1000 ifTrue: [ ticks := ticks + ticks ] ]. "Assert: self state == #ready"
executeExternal "Execute the prepared query." "Subclasses that don't support query preparation will need to assemble the query in the overriding method." ^self subclassResponsibility
moreResultsExternal "Answer true if there are more results available, otherwise answer false. Raise an exception if there are errors." ^self subclassResponsibility
readyExternal "Answer whether or not the dbms has processed the SQL statement (batch)." ^self subclassResponsibility
resultsExternal "Examine the outcome of executing an SQL statement and raise exceptions for any errors. Answer a boolean indicating the presense of an answer." ^self subclassResponsibility
</methods> <methods> Database.ExternalDatabaseSession <category>private-finalization</category>
executor "Answer with an executor for this session." "Subclassess will want to override to add information to the executor. The subclass method should use super executor to create the executor initially." | ex | ex := super executor. ex connection: connection. ex rowBuffersHolder: self rowBuffersHolder. ^ex
finalizeExternal "Release all external resource." ( traceLevel >= 1 ) ifTrue: [ self class trace: nil ]. self isExecuting ifTrue: [ self cancelExternal ]. super finalizeExternal
</methods> <methods> Database.ExternalDatabaseSession <category>private-testing</category>
isExecuting "Answer true if receiver is in an executing state." | state | ^(state := self state) == #executing or: [state == #ready or: [state == #validResults or: [state == #fetchingData]]]
</methods> <methods> Database.ExternalDatabaseSession class <category>instance creation</category>
new ^self error: (#errNewExternalDatabaseSession << #database >> 'An ExternalDatabaseSession is obtained from an instance of ExternalDatabaseConnection.')
</methods> <methods> Database.ExternalDatabaseSession class <category>accessing</category>
answerStreamClass ^ExternalDatabaseAnswerStream
xif "Answer the ExternalInterface subclass instance in use." ^self connectionClass xif
</methods> <methods> Database.ExternalDatabaseSession class <category>private-instance creation</category>
newForConnection: aConnection "Answer a new ExternalDatabaseSession associated with aConnection." | req | (req := self basicNew) initialize. req connection: aConnection. ^req
</methods> <methods> Database.ExternalDatabaseAnswerStream <category>initialize-release</category>
initialize ^self
</methods> <methods> Database.ExternalDatabaseAnswerStream <category>accessing</category>
columnDescriptions "Describe the column structure of the answer set for the (current) SQL statement or stored procedure. Answers an instance of ExternalDatabaseColumnDescription for each column of the answer set." ^self session columnDescriptions
columns "Answer the number of columns in the answer set." ^self session numColumns
contents "The contents are not accessible as a complete unit since they are not stored in the image. Use upToEnd to return all (remaining) rows." ^self shouldNotImplement
flush ^self shouldNotImplement
moveTo: anInteger "Answer the row at cursor position anInteger." | row | ( nextRow == nil ) ifTrue: [ self getRowAtAbsolutePosition: anInteger ]. ( session == nil ) ifTrue: [ ^self class endOfStreamSignal raise ]. row := nextRow. nextRow := nil. ^row
next "Answer the next row from the answer stream." | row | ( nextRow == nil ) ifTrue: [ self getNextRow ]. ( session == nil ) ifTrue: [ ^self class endOfStreamSignal raise ]. row := nextRow. nextRow := nil. ^row
next: anInteger into: aSequenceableCollection startingAt: startIndex "Store the next anInteger elements of the receiver into aSequenceableCollection starting at startIndex in aSequenceableCollection. Answer aSequenceableCollection. Since there must be a unique object for every entry of the set, the allocateForEachRow control in the session is ignored and a copy of the bindOutput object is always made." | index stopIndex | index := startIndex. stopIndex := index + anInteger. [ | getRow | session allocateForEachRow ifTrue: [ getRow := [ self next ] "next made the copy" ] ifFalse: [ getRow := [ self next copy ] "next didn't make the copy" ]. [ index < stopIndex ] whileTrue: [ "Collect the next row by executing the getRow block from above and then insert into the collection." aSequenceableCollection at: index put: getRow value. index := index + 1 ] ] on: Stream endOfStreamSignal do: [:ex | ex isResumable ifTrue: [ex resume] ifFalse: [ex restartDo: [(Stream incompleteNextCountSignal newExceptionFrom: self) parameter: index - startIndex; raiseRequest]]]. ^aSequenceableCollection
nextPut: anObject self shouldNotImplement
peek "Answer the next row from the answer stream without consuming the row. If the end of the answer stream has been reached, answer nil. Applications should be aware that this method may cause the current row to advance in order to detect the existence of an additional row. If the application is dependent on a consistent view of the current row (perhaps for WHERE CURRENT OF operations), peek should not be used after a next until completing all processing of the current row." nextRow isNil ifTrue: [ self getNextRow ]. ^session isNil ifTrue: [ nil ] ifFalse: [ nextRow ]
previous "Answer the previous row from the answer stream." | row | ( nextRow == nil ) ifTrue: [ self getPriorRow ]. ( session == nil ) ifTrue: [ ^self class endOfStreamSignal raise ]. row := nextRow. nextRow := nil. ^row
skip: anInteger "Answer the row at current cursor position+anInteger." | row | ( nextRow == nil ) ifTrue: [ self getRowAtRelativePosition: anInteger ]. ( session == nil ) ifTrue: [ ^self class endOfStreamSignal raise ]. row := nextRow. nextRow := nil. ^row
upToEnd "Answer the current contents of the receiver's input stream. All rows of the answer set are fetched. Since there must be a unique object for every entry of the set, the allocateForEachRow control in the session is ignored and a copy of the bindOutput object is always made." | cont getRow | ( session == nil ) "No more answers." ifTrue: [ self class endOfStreamSignal raiseSignal. ^#().]. cont := WriteStream on: (self contentsSpecies new: 512). session allocateForEachRow ifTrue: [ getRow := [ self next ] "next made the copy" ] ifFalse: [ getRow := [ self next copy ] "next didn't make the copy" ]. [ self atEnd ] whileFalse: [ cont nextPut: getRow value ]. ^cont contents
</methods> <methods> Database.ExternalDatabaseAnswerStream <category>status</category>
close "Sets the status of the stream to be closed." session notNil ifTrue: [ session cancelAnswerSet. self dismiss ].
</methods> <methods> Database.ExternalDatabaseAnswerStream <category>testing</category>
atEnd "Answer whether there are any more rows to be processed. Applications should be aware that this method may cause the current row to advance in order to detect the existence of additional rows. If the application is dependent on a consistent view of the current row (perhaps for WHERE CURRENT OF operations), atEnd should not be used after a next until completing all processing of the row returned." ( nextRow == nil ) ifTrue: [ self getNextRow ]. ^session == nil
</methods> <methods> Database.ExternalDatabaseAnswerStream <category>private-accessing</category>
getNextRow "Get the next row of data into nextRow. If no more rows, dismiss the receiver." | row | ( session == nil ) ifTrue: [ ^self ]. row := session nextRowExternal. ( row == nil ) ifTrue: [ self dismiss ] ifFalse: [ nextRow := row ]
getPriorRow "Get the previous row of data into nextRow. If no more rows, dismiss the receiver." | row | ( session == nil ) ifTrue: [ ^self ]. row := session getRowExternal: session fetchPriorMode offset: 0. ( row == nil ) ifTrue: [ self dismiss ] ifFalse: [ nextRow := row ]
getRowAtAbsolutePosition: anInteger "Get the next row of data into nextRow. If no more rows, dismiss the receiver." | row | ( session == nil ) ifTrue: [ ^self ]. row := session getRowExternal: session fetchAbsoluteMode offset: anInteger. ( row == nil ) ifTrue: [ self dismiss ] ifFalse: [ nextRow := row ]
getRowAtRelativePosition: anInteger "Get the next row of data into nextRow. If no more rows, dismiss the receiver." | row | ( session == nil ) ifTrue: [ ^self ]. row := session getRowExternal: session fetchRelativeMode offset: anInteger. ( row == nil ) ifTrue: [ self dismiss ] ifFalse: [ nextRow := row ]
session ^session
session: aSession session := aSession
</methods> <methods> Database.ExternalDatabaseAnswerStream <category>private-activation</category>
activate "Should never be sent because answer streams do not remain a participant when quiesced so no parent will retain a reference and send activate." ^self shouldNotImplement
dismiss session isNil ifTrue: [^self]. session answerStreamDismissed. self session: nil
quiesce "Answer streams cannot be reactivated so quiesce is the same as dismiss." self dismiss
</methods> <methods> Database.ExternalDatabaseAnswerStream <category>private-testing</category>
isExecutor "Answer true if the receiver is really an executor, not the primary object." "AnswerStreams never hold external resources themselves and so will never have executors." ^false
</methods> <methods> Database.ExternalDatabaseAnswerStream class <category>instance creation</category>
new ^self error: (#errNewAnswerStream << #database >> 'An ExternalDatabaseAnswerStream is obtained from an instance of ExternalDatabaseSession')
</methods> <methods> Database.ExternalDatabaseAnswerStream class <category>private-instance creation</category>
newForSession: aSession "Create a new ExternalDatabaseAnswerStream instance associated with the session aSession." | ans | (ans := self basicNew) initialize; session: aSession. ^ans
</methods> <methods> Database.ExternalDatabaseBuffer <category>initialize-release</category>
elementSize: anElementSize count: aCount databaseType: aDatabaseType elementSize := anElementSize. count := aCount. databaseType := aDatabaseType
initialize "Initialize an instance of the receiver." encoding := #default
</methods> <methods> Database.ExternalDatabaseBuffer <category>allocation</category>
free "Free the receiver." bufferPointer notNil ifTrue: [ bufferPointer freePointer. bufferPointer := nil ]
mallocUsingSelector: mallocSelector "Assert: mallocSelector is either #malloc: or #malloc16:" bufferPointer := self pointerType perform: mallocSelector with: (count max: 1)
</methods> <methods> Database.ExternalDatabaseBuffer <category>accessing</category>
at: anIndex "Answer the object in the buffer at anIndex." ^self subclassResponsibility
at: anIndex put: anObject "Store anObject into the buffer at anIndex." ^self subclassResponsibility
count "Answer the receiver's cardinality" ^count
databaseType "Answer the receiver's database type." ^databaseType
elementSize "Answer the receiver's length" ^elementSize
encoding "Answer the encoding" ^encoding
encoding: aSymbol "Set the encoding type" encoding := aSymbol
pointer "Answer the receiver's buffer pointer." ^bufferPointer
size "Answer the receiver's size" ^(count max: 1) * elementSize
value "Answer the value (or values) held in the buffer" | array | count == 0 ifTrue: [ ^self at: 1 ]. array := Array new: count. 1 to: count do: [ :index | array at: index put: (self at: index) ]. ^array
value: aValueOrArray "Store aValueOrArray into the receiver." | size | count == 0 ifTrue: [ ^self at: 1 put: aValueOrArray ]. size := aValueOrArray size. size > count ifTrue: [ ^self error: (#errTooBigForBuffer << #database >> 'too big for buffer') ]. 1 to: size do: [ :index | self at: index put: (aValueOrArray at: index) ]. size < count ifTrue: [ (size + 1) to: count do: [ :index | self at: index put: nil ] ]
</methods> <methods> Database.ExternalDatabaseBuffer <category>private</category>
pointerType "Answer the pointer type to use for buffer allocation." ^CArrayType defaultPointer referentType: CIntegerType char; numElements: self elementSize.
</methods> <methods> Database.ExternalDatabaseBuffer class <category>instance creation</category>
new "Answer an initialized instance of the receiver" ^super new initialize
</methods> <methods> Database.UnableToSetEnvironmentAttribute class <category>class initialization</category>
initialize "Set the default notification message for the receiver" self notifierString: (#errSetEnvironmentAttribute << #database >> 'unable to set environment attribute.')
</methods> <methods> Database.UnableToCreateConnectionPool class <category>class initialization</category>
initialize "Set the default notification message for the receiver" self notifierString: (#errConnectionPoolCreation << #database >> 'unable to create connection pool.')
</methods> <methods> UI.TableAdaptor <category>accessing</category>
elementSize ^baseCollection size
</methods> <methods> Database.AdHocQueryTool class <category>interface specs</category>
buffersSpec "UIPainter new openOnClass: self andSelector: #buffersSpec" <resource: #canvas> ^#(#FullSpec #window: #(#WindowSpec #label: '' #min: #(#Point 317 76 ) #max: #(#Point 317 76 ) #bounds: #(#Rectangle 326 467 643 543 ) ) #component: #(#SpecCollection #collection: #( #(#InputFieldSpec #layout: #(#LayoutFrame -64 1 8 0 -24 1 32 0 ) #model: #blockFactorModel #alignment: #right #type: #number ) #(#ActionButtonSpec #layout: #(#LayoutFrame -82 0.5 -35 1 -8 0.5 -4 1 ) #model: #accept #label: #(#{UserMessage} #key: #OK #catalogID: #database #defaultString: 'OK' ) #isDefault: true ) #(#ActionButtonSpec #layout: #(#LayoutFrame 16 0.5 -35 1 89 0.5 -4 1 ) #model: #cancel #label: #(#{UserMessage} #key: #Cancel #catalogID: #database #defaultString: 'Cancel' ) #defaultable: true ) #(#LabelSpec #layout: #(#AlignmentOrigin -66 1 32 0 1 1 ) #label: #(#{UserMessage} #key: #bufferRows #catalogID: #database #defaultString: 'Number of rows to buffer internally:') ) ) ) )
reportErrorSpec "UIPainter new openOnClass: self andSelector: #reportErrorSpec" <resource: #canvas> ^#(#FullSpec #window: #(#WindowSpec #label: '' #min: #(#Point 313 200 ) #max: #(#Point 313 200 ) #bounds: #(#Rectangle 267 274 580 474 ) ) #component: #(#SpecCollection #collection: #( #(#TextEditorSpec #layout: #(#LayoutFrame 0 0 0 0 0 1 -40 1 ) #name: #errorText #model: #errorText #tabable: true #menu: #errorTextMenu #isReadOnly: false ) #(#ActionButtonSpec #layout: #(#LayoutFrame -25 0.5 -35 1 25 0.5 -5 1 ) #model: #accept #label: #(#{Kernel.UserMessage} #key: #OK #defaultString: 'OK' #catalogID: #database) #isDefault: true #defaultable: true ) ) ) )
windowSpec "UIPainter new openOnClass: self andSelector: #windowSpec" <resource: #canvas> ^#(#FullSpec #window: #(#WindowSpec #label: #(#{UserMessage} #key: #adHocSQL #catalogID: #database #defaultString: 'Ad Hoc SQL' ) #min: #(#Point 458 317 ) #max: #(#Point 1152 900 ) #bounds: #(#Rectangle 86 132 544 449 ) #flags: 4 #menu: #menuBar ) #component: #(#SpecCollection #collection: #( #(#ActionButtonSpec #layout: #(#Rectangle 10 5 90 35 ) #name: #connect #model: #connect #label: #(#{UserMessage} #key: #Connect #catalogID: #database #defaultString: 'Connect' ) #isDefault: false ) #(#ActionButtonSpec #layout: #(#Rectangle 100 5 200 35 ) #name: #disconnect #flags: 40 #model: #disconnect #label: #(#{UserMessage} #key: #disconnect1 #catalogID: #database #defaultString: 'Disconnect') ) #(#ActionButtonSpec #layout: #(#Rectangle 210 5 300 35 ) #name: #execute #flags: 40 #model: #execute #label: #(#{UserMessage} #key: #execute #catalogID: #database #defaultString: 'Execute') ) #(#ActionButtonSpec #layout: #(#Rectangle 310 5 420 35 ) #name: #nextAnswer #flags: 40 #model: #nextAnswer #label: #(#{UserMessage} #key: #nextAnswer1 #catalogID: #database #defaultString: 'Next Answer') ) #(#TextEditorSpec #layout: #(#LayoutFrame 0 0 40 0 0 1 -3 0.33 ) #name: #query #model: #queryModel ) #(#TableViewSpec #layout: #(#LayoutFrame 0 0 0 0.33 0 1 0 1 ) #model: #tableModel #showHGrid: true #showVGrid: true #selectionStyle: #row ) ) ) )
</methods> <methods> Database.AdHocQueryTool class <category>resources</category>
errorTextMenu "MenuEditor new openOnClass: self andSelector: #errorTextMenu" <resource: #menu> ^#(#Menu #( #(#MenuItem #rawLabel: #(#{UserMessage} #key: #copy #catalogID: #database #defaultString: 'copy' ) #value: #copySelection ) ) #(1 ) nil ) decodeAsLiteralArray
menuBar "MenuEditor new openOnClass: self andSelector: #menuBar" <resource: #menu> ^#(#Menu #( #(#MenuItem #rawLabel: #(#{UserMessage} #key: #connection #catalogID: #database #defaultString: '&Connection' ) #submenu: #(#Menu #( #(#MenuItem #rawLabel: #(#{UserMessage} #key: #connect #catalogID: #database #defaultString: '&Connect...' ) #nameKey: #connect #value: #connect ) #(#MenuItem #rawLabel: #(#{UserMessage} #key: #disconnect #catalogID: #database #defaultString: '&Disconnect' ) #enabled: false #nameKey: #disconnect #value: #disconnect ) #(#MenuItem #rawLabel: #(#{UserMessage} #key: #Exit #catalogID: #database #defaultString: 'E&xit' ) #value: #closeRequest ) ) #(3 ) nil ) ) #(#MenuItem #rawLabel: #(#{UserMessage} #key: #Execution #catalogID: #database #defaultString: '&Execution' ) #submenu: #(#Menu #( #(#MenuItem #rawLabel: #(#{UserMessage} #key: #Execute #catalogID: #database #defaultString: '&Execute' ) #enabled: false #nameKey: #execute #value: #execute ) #(#MenuItem #rawLabel: #(#{UserMessage} #key: #nextAnswer #catalogID: #database #defaultString: '&Next Answer' ) #enabled: false #nameKey: #nextAnswer #value: #nextAnswer ) #(#MenuItem #rawLabel: #(#{UserMessage} #key: #buffers #catalogID: #database #defaultString: '&Buffers...' ) #nameKey: #fetchBuffers #value: #fetchBuffers ) ) #(3 ) nil ) ) ) #(2 ) nil ) decodeAsLiteralArray
</methods> <methods> Tools.DBProfilePropertiesDialog class <category>interface specs</category>
windowSpec "Tools.UIPainter new openOnClass: self andSelector: #windowSpec" <resource: #canvas> ^#(#{UI.FullSpec} #window: #(#{UI.WindowSpec} #label: #(#{Kernel.UserMessage} #key: #DBProfileProperties #defaultString: 'DBProfile Properties' #catalogID: #store ) #min: #(#{Core.Point} 410 201 ) #max: #(#{Core.Point} 410 201 ) #bounds: #(#{Graphics.Rectangle} 512 384 922 585 ) ) #component: #(#{UI.SpecCollection} #collection: #( #(#{UI.InputFieldSpec} #layout: #(#{Graphics.Rectangle} 130 15 300 40 ) #name: #nameField #model: #nameHolder ) #(#{UI.ComboBoxSpec} #layout: #(#{Graphics.Rectangle} 130 45 300 70 ) #name: #databaseCombo #model: #databaseHolder #type: #string #comboList: #databaseListHolder ) #(#{UI.InputFieldSpec} #layout: #(#{Graphics.Rectangle} 130 75 300 100 ) #name: #environmentField #model: #environmentHolder ) #(#{UI.InputFieldSpec} #layout: #(#{Graphics.Rectangle} 130 105 300 130 ) #name: #userNameField #model: #userNameHolder ) #(#{UI.InputFieldSpec} #layout: #(#{Graphics.Rectangle} 130 135 300 160 ) #name: #passwordField #model: #passwordHolder #type: #password ) #(#{UI.ActionButtonSpec} #layout: #(#{Graphics.LayoutFrame} -90 1 14 0 -10 1 39 0 ) #name: #accept #model: #ok #label: #(#{Kernel.UserMessage} #key: #OK #defaultString: 'OK' #catalogID: #database ) #isDefault: true ) #(#{UI.ActionButtonSpec} #layout: #(#{Graphics.LayoutFrame} -90 1 46 0 -10 1 71 0 ) #name: #cancel #model: #cancel #label: #(#{Kernel.UserMessage} #key: #Cancel #defaultString: 'Cancel' #catalogID: #database ) #defaultable: true ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 10 0 40 0 0 1 ) #name: #Label1 #label: #(#{Kernel.UserMessage} #key: #NameC #defaultString: 'Name:' #catalogID: #store ) ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 10 0 70 0 0 1 ) #label: #(#{Kernel.UserMessage} #key: #interface #defaultString: 'Interface:' #catalogID: #database ) ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 10 0 130 0 0 1 ) #label: #(#{Kernel.UserMessage} #key: #userName #defaultString: 'User Name:' #catalogID: #database ) ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 10 0 160 0 0 1 ) #label: #(#{Kernel.UserMessage} #key: #password #defaultString: 'Password:' #catalogID: #database ) ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 10 0 100 0 0 1 ) #label: #(#{Kernel.UserMessage} #key: #environment #defaultString: 'Environment:' #catalogID: #database ) ) ) ) )
</methods> <methods> Database.ConnectionDialog class <category>interface specs</category>
windowSpec "UIPainter new openOnClass: self andSelector: #windowSpec" <resource: #canvas> ^#(#{UI.FullSpec} #window: #(#{UI.WindowSpec} #label: #(#{Kernel.UserMessage} #key: #ConnectToDatabase #defaultString: 'Connect to Database' #catalogID: #database) #min: #(#{Core.Point} 426 216 ) #max: #(#{Core.Point} 426 216 ) #bounds: #(#{Graphics.Rectangle} 512 384 938 600 ) ) #component: #(#{UI.SpecCollection} #collection: #( #(#{UI.ComboBoxSpec} #layout: #(#{Graphics.Rectangle} 140 14 320 38 ) #name: #connectionProfile #model: #connectionProfileHolder #type: #string #comboList: #connectionProfileListHolder ) #(#{UI.ComboBoxSpec} #layout: #(#{Graphics.Rectangle} 140 56 310 79 ) #name: #databaseCombo #model: #databaseHolder #callbacksSpec: #(#{UI.UIEventCallbackSubSpec} #valueChangeSelector: #databaseChanged ) #type: #string #comboList: #databaseListHolder ) #(#{UI.ComboBoxSpec} #layout: #(#{Graphics.Rectangle} 140 85 310 109 ) #name: #environmentCombo #model: #environmentHolder #callbacksSpec: #(#{UI.UIEventCallbackSubSpec} #valueChangeSelector: #environmentChanged ) #isReadOnly: false #comboList: #environmentListHolder ) #(#{UI.ComboBoxSpec} #layout: #(#{Graphics.Rectangle} 140 114 310 138 ) #name: #userNameCombo #model: #userNameHolder #callbacksSpec: #(#{UI.UIEventCallbackSubSpec} #valueChangeSelector: #userNameChanged ) #isReadOnly: false #comboList: #userNameListHolder ) #(#{UI.InputFieldSpec} #layout: #(#{Graphics.Rectangle} 140 143 310 167 ) #name: #passwordField #model: #passwordHolder #callbacksSpec: #(#{UI.UIEventCallbackSubSpec} #valueChangeSelector: #passwordChanged ) #type: #password ) #(#{UI.ActionButtonSpec} #layout: #(#{Graphics.Rectangle} 140 175 220 198 ) #name: #saveProfile #model: #saveProfile #label: #(#{Kernel.UserMessage} #key: #Save #defaultString: 'Save...' #catalogID: #database) ) #(#{UI.ActionButtonSpec} #layout: #(#{Graphics.Rectangle} 230 175 310 198 ) #name: #deleteProfile #model: #deleteProfile #label: #(#{Kernel.UserMessage} #key: #Delete #defaultString: 'Delete' #catalogID: #database) ) #(#{UI.ActionButtonSpec} #layout: #(#{Graphics.LayoutFrame} -90 1 14 0 -10 1 39 0 ) #name: #connect #model: #connect #label: #(#{Kernel.UserMessage} #key: #Connect #defaultString: 'Connect' #catalogID: #database ) #isDefault: true ) #(#{UI.ActionButtonSpec} #layout: #(#{Graphics.LayoutFrame} -90 1 46 0 -10 1 71 0 ) #name: #cancel #model: #cancel #label: #(#{Kernel.UserMessage} #key: #Cancel #defaultString: 'Cancel' #catalogID: #database ) #defaultable: true ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 20 0 80 0 0 1 ) #label: #(#{Kernel.UserMessage} #key: #interface #defaultString: 'Interface:' #catalogID: #database ) ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 20 0 138 0 0 1 ) #label: #(#{Kernel.UserMessage} #key: #userName #defaultString: 'User Name:' #catalogID: #database ) ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 20 0 167 0 0 1 ) #label: #(#{Kernel.UserMessage} #key: #password #defaultString: 'Password:' #catalogID: #database ) ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 20 0 109 0 0 1 ) #label: #(#{Kernel.UserMessage} #key: #environment #defaultString: 'Environment:' #catalogID: #database ) ) #(#{UI.LabelSpec} #layout: #(#{UI.AlignmentOrigin} 9 0 38 0 0 1 ) #label: #(#{Kernel.UserMessage} #key: #profile #defaultString: 'Connection Profile:' #catalogID: #database ) ) #(#{UI.GroupBoxSpec} #layout: #(#{Graphics.Rectangle} 10 46 320 210 ) ) ) ) )
</methods> <methods> Tools.DBProfileListPage class <category>interface specs</category>
windowSpec "Tools.UIPainter new openOnClass: self andSelector: #windowSpec" <resource: #canvas> ^#(#{UI.FullSpec} #window: #(#{UI.WindowSpec} #label: #(#{UserMessage} #key: #UnlabeledCanvas #catalogID: #database #defaultString: 'Unlabeled Canvas') #min: #(#{Core.Point} 20 20 ) #max: #(#{Core.Point} 1024 768 ) #bounds: #(#{Graphics.Rectangle} 512 384 850 672 ) ) #component: #(#{UI.SpecCollection} #collection: #( #(#{UI.DataSetSpec} #properties: #(#{UI.PropertyListDictionary} #showHorizontalLines false #allowColumnResizing true #rowSize 25 #showVerticalLines false #allowColumnReordering false ) #layout: #(#{Graphics.LayoutFrame} 0 0 0 0 0 1 -30 1 ) #name: #profileListDataset #flags: 13 #model: #profileListHolder #columns: #( #(#{UI.DataSetColumnSpec} #properties: #(#{UI.PropertyListDictionary} #labelFromApplication false #allowSorting false #allowResizing false ) #model: #'profileHolder name' #label: #(#{UserMessage} #key: #Name #catalogID: #database #defaultString: 'Name') #labelIsImage: false #width: 100 #rendererType: #Text #editorType: #None #noScroll: false ) #(#{UI.DataSetColumnSpec} #properties: #(#{UI.PropertyListDictionary} #allowSorting false #labelFromApplication false ) #model: #'profileHolder environment' #label: #(#{UserMessage} #key: #Environment #catalogID: #database #defaultString: 'Environment') #labelIsImage: false #width: 200 #rendererType: #Text #editorType: #None #noScroll: false ) ) #labelsAsButtons: true ) #(#{UI.ActionButtonSpec} #layout: #(#{Graphics.LayoutFrame} 0 0 -25 1 -3 0.333333 0 1 ) #name: #addButton #model: #addProfile #label: #(#{UserMessage} #key: #AddDots #catalogID: #database #defaultString: 'Add...') #defaultable: true ) #(#{UI.ActionButtonSpec} #layout: #(#{Graphics.LayoutFrame} 2 0.333333 -25 1 -2 0.666666 0 1 ) #name: #removeButton #model: #removeProfile #label: #(#{UserMessage} #key: #RemoveDots #catalogID: #database #defaultString: 'Remove...') #defaultable: true ) #(#{UI.ActionButtonSpec} #layout: #(#{Graphics.LayoutFrame} 3 0.666666 -25 1 0 1 0 1 ) #name: #propertiesButton #model: #profileProperties #label: #(#{UserMessage} #key: #PropertiesDots #catalogID: #database #defaultString: 'Properties...') #defaultable: true ) ) ) )
</methods> <methods> Tools.VisualWorksSettings class <category>settings-database</category>
databaseProfiles <setting: #(tools dbprofiles)> ^DBProfileListSetting new
</methods> <methods> Tools.VisualWorksSettings class <category>pages</category>
databaseProfilesPage <settingsPage: #(tools dbprofiles)> ^DBProfileListPage new label: #DBProfiles << #labels >> 'Database - Profiles'; icon: (ListIconLibrary visualFor: #database); setting: (self settingWithId: #(tools dbprofiles))
</methods> <initialize> Database.ExternalDatabaseFramework </initialize> <initialize> Database.ExternalDatabaseConnection </initialize> <initialize> Database.UnsupportedCursorType </initialize> <initialize> Database.UnableToDestroyConnectionPool </initialize> <initialize> Database.UnableToSetEnvironmentAttribute </initialize> <initialize> Database.UnableToCreateConnectionPool </initialize> "Imported Classes:" self error: 'Attempting to file-in parcel imports. Choose terminate or close' <class> <name>Object</name> <environment>Core</environment> <super></super> <private>false</private> none <imports></imports> <category>Kernel-Objects</category> <attributes> <package>Kernel-Objects</package> </attributes> </class> <class> <name>GenericSettingDescriptor</name> <environment>Tools</environment> <super>UI.Model</super> <private>false</private> none id position definingMethod <imports> XML.Element XML.Attribute </imports> <category>Tools-Settings</category> <attributes> <package>Tools-Settings</package> </attributes> </class> <class> <name>ApplicationModel</name> <environment>UI</environment> <super>UI.Model</super> <private>false</private> none builder uiSession eventHandlers savedWindowInformation <imports></imports> <category>UIBuilder-Framework</category> <attributes> <package>UIBuilder-Framework</package> </attributes> </class> <class> <name>SettingsManagerPage</name> <environment>Tools</environment> <super>UI.ApplicationModel</super> <private>false</private> none manager id position label icon children definingMethod <imports></imports> <category>Tools-Settings-UI</category> <attributes> <package>Tools-Settings</package> </attributes> </class> <class> <name>Stream</name> <environment>Core</environment> <super>Core.Object</super> <private>false</private> none <imports> private IOConstants.* </imports> <category>Collections-Streams</category> <attributes> <package>Collections-Streams</package> </attributes> </class> <class> <name>SimpleDialog</name> <environment>UI</environment> <super>UI.ApplicationModel</super> <private>false</private> none close accept cancel preBuildBlock postBuildBlock postOpenBlock escapeIsCancel parentView <imports></imports> <category>Interface-Dialogs</category> <attributes> <package>Interface-Dialogs</package> </attributes> </class> <class> <name>TableAdaptor</name> <environment>UI</environment> <super>Core.ArrayedCollection</super> <private>false</private> none dependents baseCollection adaptors columnSize transposed <imports></imports> <category>UIBasics-Collections</category> <attributes> <package>UIBasics-Collections</package> </attributes> </class> <class> <name>Error</name> <environment>Core</environment> <super>Core.Exception</super> <private>false</private> none <imports></imports> <category>Kernel-Exception Handling</category> <attributes> <package>Kernel-Exception Handling</package> </attributes> </class>