VisualAge for Smalltalk Database-related FAQs

The following Frequently Asked Questions (FAQ) focus on databases and VisualAge for Smalltalk:

What databases are supported by VisualAge?
VisualAge for Smalltalk supports a wide variety of database systems including: The DB2 family. On the client: DB2/2 for OS/2, DB2/6000 for AIX, and on Windows using CAE client support. Through connectivity services of DDCS, VisualAge for Smalltalk can access the DB2 family (including DB2 and SQL/DS and access to the AS/400). ORACLE ODBC (with industry standard drivers such as Sybase, SQL Server, Informix) IBM intends to respond to additional customer needs for native support for other databases.
Is ODBC fully supported by VisualAge?
Yes, all the capabilities in the ODBC standard are supported starting with VA 3.0.
Does VA support ODBMSs?
Versant Versant is an IBM Object Connection partner. They provide their Argos development environment and OODBMS (Release 4) which can be used with IBM Smalltalk and IBM's VisualAge for Smalltalk. Argos is a modeling tool and is described in Section XVII. Versant's OODBMS is a leading object database management system for multi-user, distributed applications. Versant can be reached at 1-800-VERSANT.

Gemstone Gemstone Systems is also an IBM Object Connection partner. They provide their Gemstone Object Application Server for VisualAge which allows VisualAge applications to take advantage of GemStone's three-tier application partitioning capabilities for business-critical enterprise-wide deployment. Gemstone can be reached at 1-800-243-9369.

Tensegrity Polymorphic Software, Inc., also and Object Connection partner, has announced plans to make their Tensegrity OODBMS available for IBM Smalltalk. Polymorphic can be reached at 415-592-6301.

ODI IBM is working with ODI to enable their ObjectStore OODBMS to IBM Smalltalk. This support is currently planned for VisualAge for Smalltalk V4.0.
Explain the use of multirow query settings.
Maximum number of rows to fetch - used with a one-time query to limit the rows returned Enable packeting - for DB2/2, quick forms, and containers, return up to the number of rows that will fit on the display area; get more rows as needed to satisfy the user actions (e.g. scrolling) Enable blocked fetches - for ODBC, get up to the number of rows that you specify in the Blocked fetch size for each request.
What would cause my database query to show no fields?
One of two things, either

(1) the database is not set up and/or connected to properly.
See pp.12 - 18 of the VA User's Guide for connecting to a DB. If you're using DB2, make sure you also bind to the DB (pp. 421-3). Use your DBMS tools to set up the DB schema

or

(2) the query is not set up properly.
The DB query part has a settings popup. In the resulting dialog, define your query - see pp. 19 - 28 of the VA User's Guide.
Can I connect to two data sources concurrently?
If you have VisualAge 3.0 or later, then you can create multiple connection specs, and connect to all of them simultaneously. The number of connections vary by database vendors.
Can I disable the AbtError message from appearing from queries so I can handle them myself?
What you can do is the following:
- extend the AbtDatabasePart class into your application
- add an #initialize instance method setting the (individual) errorBlock to whatever you want
- just make sure you have "super initialize" as the first statement
Can I have more than one connection to DB2 using ODBC?
You can connect to DB2 via ODBC as many times as the driver permits, however the DB2 driver that we ship with the ODBC support only supports 1 connect at a time. The DB2 CLI driver can be used as an ODBC driver, but this driver is not fully ODBC compliant, and you will have problems using our SQL editor.
How do I asynchronously access a DB2 database?
The Database tab of the VisualAge preferences notebook contains a check box 'Thread all database calls'. This feature is currently operational on OS/2 only. Setting this option causes external database calls to execute on a separate Smalltalk thread.

To view the preferences page, go to the VisualAge Organizer view, select Options->Preferences. Any change to this option will become effective when you click 'Apply'.
How can I check to see if a database is available before I send it a request?
Sending AbtDbmSystem activeDatabaseMgr will do the job. If you get nil back then you are not connected.
Why can't I delete rows using the ODBC text driver?
The ODBC text driver supplied with VisualAge 3.0 does not support deletes or updates. Additional info can be found in the 'VisualAge OBDC Support Drivers Reference'.
How do I find out what a SQL error message means?
Try looking in the VisualAge for Smalltalk online Features Class Guide and Reference in section 1.4.4 titled Error Detection and other tips.
Can I use stored procedures?
Version 3.0 now supports Stored Procedures with our ODBC feature and our Native Oracle feature. If you are connecting to Sybase through ODBC, then you should be able to use stored procedures. This information and more is available in the VisualAge for Smalltalk User's Guide on page 205 Using stored procedures.
Why do I get the error "Undefined object does not understand contents"?
Try changing the "widget notNil" test in AbtTextViewFormatManager>>userInputString to "self isWidgetUsable".
How do I convert my queries to another database?
A tool is provided in VisualAge Version 3 which helps users migrate their Version 2 database parts to Version3. This tool also helps users to migrate their query parts to use different connection specifications. See p.429 of the VisualAge User's Guide for additional information about this tool. The general steps for migrating your query parts (for cases a and b) would be as follows:

1) Modify an existing connection specification for your application (or create a new specification) so that it contains information about the desired (target) database connection

2) Follow instructions on p. 429 to execute the migration tool for the parts that require migration

Migration will be possible if the table names and column names for your target database connection match those for your original connection.
Is there an ability for the end user application to cancel a database call?
Native Oracle support contains an API called 'break' which will asynchronously terminate any long running operations for a database connection. This method can be executed as follows:
   (AbtDbmSystem activeDatabaseConnectionWithAlias: 'Oracle' ) break
ODBC and IBM database support do not currently implement any similar functionality. In answer to your question regarding threads, threaded database calls are executed with a 'threadKey' equivalent to theAbtDatabaseConnection instance that executes the DB call. Therefore, a thread could be terminated by executing the following code:
   AbtThreadManager terminateThread:
   (AbtDbmSystem activeDatabaseConnectionWithAlias: 'x').
Does VA support multiple database connections per process?
In Version 3, multiple database connections are permissable. VisualAge manages these multiple connections by retaining connection 'aliases' which map to actual connections.

Below is an example of the recommended V3 approach for establishing a database connection via Smalltalk code. (Notice that the recommended steps forestablishing a database connection have changed. The old technique for connecting is still supported, but is slightly less flexible )
  | dbSpec1 dbConnection1  |
 
  dbSpec1 := AbtDatabaseConnectionSpec 
   forDbmClass: AbtOdbcDatabaseManager 
   dataSourceName: 'Local'.
 
  " activate the connection described by dbSpec1 passing in required 
   logon information " 
  dbConnection1 :=
  dbSpec1 connectUsingAlias: 'Local'
   logonSpec: ( AbtDatabaseLogonSpec new id: 'USERID' ; 
        password: 'PASSWORD' ; 
        server: 'Local' ; 
        yourself ).
The approach above is useful if you are using Smalltalk code to connect. However, the VisualAge visual database parts are designed to prompt for logon information each time a new connection is established. There is a simple way to override this behavior.

A programmer can 'register' logon information which remains active for as long as the image is active ( the information is cleared when the image is re-started). ie)
  AbtDbmSystem registerLogonSpec:
  logonSpec: ( AbtDatabaseLogonSpec new id: 'USERID' ; 
        password: 'PASSWORD' ; 
        server: 'Local' ; 
        yourself ) withAlias: 'Local'.
After the above statement is executed, the supplied logon spec will be used any time you attempt to activate the connection with alias 'Local'. The #removeLogonSpecWithAlias: can be used to undo the above action.
What should I do if I'm having packaging and runtime problems with DB2?
VisualAge V3 stores each individual query as a separate method within your access set.

The runtime packager algorithm is designed to eliminate unreferenced selectors from your packaged image. I suspect that you are setting your querySpecName: to a String containing the name of a query specification. The packager does not recognize Strings as selector names; therefore, query names set using a String will not be included in the packaged image unless referenced elsewhere by your application. However, if you set your querySpecName using a hardcoded Symbol, the packager WILL include the runtime selector for your query.

You have at least 2 options for correcting this problem...
1) Change all references to query spec names from Strings to Symbols.
ie) dbPart querySpecName: 'MyQuery'
- changed to -
dbPart querySpecName: #MyQuery
-OR-
2) Implement a method called #packagerIncludeSelectors in your accessSetClass.
This method answers an Array containing the names of selectors that you wish to include in the package image. This method is only necessary for cases where you wish to include a selector which is not directly referenced by the application.

Example - To package runtime selectors for all querySpecs contained within MyAccessSet, I would create a class method called #packagerIncludeSelectors in class MyAccessSet. The code would look like :
 packagerIncludeSelectors 
 
 ( self registeredQuerySpecNames 
  collect: [:specName ] specName asSymbol ] ) asArray 
To force queries 'Abc' and 'Def' to be packaged, the #packagerIncludeSelectors method would look like:
 packagerIncludeSelectors 
     #( Abc Def ) 
There is additional packaging information on p333 of the IBM ST User's Guide.
Can VA be used to generate non-ANSI SQL?
The VA SQL Editor was built based on ANSI SQL and cannot be used to build non-ANSI SQL. Yes, one can be created manually. We know of no limitations in allowable syntax for SQL statements. In some cases, it may be possible for you to build your initial 'ANSI' query using the SQL Editor, then manually edit the query to add any 'non-ANSI' functionality. VA merely passes your query string to the database connection. No syntax validation is done within VA itself.
What do I have to do to provide a BLOB object to a column of the currentRow?
The SQL statements generated by an APPLY upon a updated query result table includes the values as litterals (which is obviously difficult for a BLOB). INSERT or UPDATE SQL statements created by an SqlStatement part can include values as hostvariables. Using this way, I'm able to insert BLOB in the database.
What should I do if I cannot retrieve a BLOB using DB2?
When VisualAge retrieves a BLOB from DB2/2, it does not have a concept of the class that was used to store the data. If you would like to create a new instance of your OSObject subclass using the ByteArray from your retrieved BLOB, you can do so as follows:
  MyOSObjectSubclass reference: theBlobByteArray 
OSObjects contain an instance variable called reference which can contain a ByteArray or an address to OSMemory. The code above instantiates the OSObject subclass and sets the 'reference' to the BLOB ByteArray.
How do we prevent the error prompter from being displayed?
Each query part has its own #errorBlock attribute which can be individually set prior to query execution. The query parts circumvent the default error block set in the active database manager instance by passing in an errorBlock when executing database API calls. Prior to executing a query, you can set its errorBlock in a script. ie)
  (self subpartNamed: 'Multiple Row Query1') errorBlock:  [ your BLOCK ].
Or, you can create a VisualAge event-to-script connection to a method which returns the errorBlock and connect the 'result' of the connection to the #errorBlock attribute of your query part.
Where can I get information about CLI?
The IBM CLI Database feature is a reimplementation of the IBM Database Manager, bringing our database manager count to four:

1. IBM Database 2 - "original"
2. IBM Database 2 - CLI
3. ODBC
4. Oracle - Native

Our original DB2 support used a DLL that we provided. That DLL used embedded SQL. It had some shortcomings. It didn't support multiple connections, and it didn't handle concurrent applications well. It needed to be ported to Windows 95 and Windows NT. Furthermore, it is not possible to support multiple concurrent connections using embedded SQL (you can have multiple connections, but only one active connection). Faced with these problems, we decided it was time to change interfaces.

DB2 provides a second dynamic interface, the Call Level Interface (CLI). This interface supports multiple concurrent connections. The CLI DLL is shipped with each DB2/2 client, so our customers already have it. It's designed for concurrency of applications. It supports distributed unit of work (multiple connections, one transaction). It's available on all platforms. So,... we now support the CLI.

The CLI should have the same public interface as the original DB2 support, so migration is easy. It is necessary to use AbtEditDatabaseMigrationApp to migrate any of the visual database query parts, however. (This was documented in V3.0, you load the app and execute AbtDatabaseMigrationView new openWidget).

The CLI feature is available on all platforms (the original DB2 support has not been ported to 95 or NT), and it is the implementation that we will be using in the future. The original DB2 support will eventually be dropped.
Why do I get an error of "Connection limit reached"?
From the db2 command line processor enter 'query client'. Take a look at the value for 'MAX_NETBIOS_CONNECTIONS', if this is 1 then use the 'set client' command to increase this value. I'm assuming you're using netbios for communications, if you're not then repost with the sql error number you're receiving.

To prevent the logon prompt for the aliases that you have as prompt no, register a logon spec for each one.
  AbtDbmSystem registerLogonSpec:  (AbtDatabaseLogonSpec new
          id: 'userid'; password: 'password'; server: 'sample')
         withAlias: 'VAIBMSamples'
Why are we having problems with our VA ODBC drivers?
I have been able to get the VisualAge odbc.dll driver manager to work with the db2 odbc driver (db2cli.dll). I did not use the db2 'odbc installer' to install any drivers. Here are the steps I followed:
1. Catalog your database(s)
2. Start the 'CLI-ODBC Administrator' program. From here you can select the database alias and configure the database you want to access via the visualAge odbc feature.
3. From VisualAge you should now be able to create a connection alias using the data source you just configured.
How can I define my script to only read 50 rows?
Try using #for:do:ifError: instead of #do:. the first argument is the number of rows you want, you mentioned 50. Alternatively, you could do something like
   50 timesRepeat: [
         aRow := rows next.
          ..... ].
What is the function of the addRows: method of AbtTableClass?
The #addRows: message can be used for ODBC, IBM CLI, or Native Oracle to add a collection of rows to a database table with one API call. The #addRows: message can be significantly faster for some cases because multiple data rows are added with only one trip to the database server.

The parameter name 'aRowSet' is a bit deceptive. 'aRowSet' should be a collection of AbtRow objects. In fact, 'Set' objects cannot be used for this API.
Is there a way to set the isolation level of a DB2 database connection?
Yes, there are two ways. One way is to change your db2cli.ini file to include 'TXNISOLATION = 1'. This will make all connections to the database use this isolation level by default. The isolation levels are:

1 = Read Uncommitted (Uncommitted read)
2 = Read Committed (Cursor stability) (default)
8 = Serializable (Repeatable read)
16= Repeatable Read (Read Stability)
32= (No Commit, DATABASE 2 for OS/400 only) The words in round brackets are the DB2 equivalents for SQL92 isolation levels." (This is from DB2 Call Level Interface Guide and Reference.)

The other way is to use the set connection option api. VisualAge has a method, #setConnectOption:withHdbc:value:ifError:, that calls this api. For example,
   myConnection 
   setConnectOption: "Sql_Txn_Isolation" 72 
   withHdbc: self hdbc 
   value: "Sql_Txn_Read_Uncommitted" 1 
   ifError: self errorBlock.
Where can I find a list of all values for the constants?
I find them by looking in the C include files, sqlcli.h and sqlcli1.h. They are found in your sqllib\include directory if you have the Software Developers Kit for DB2.
What licenses are needed for VAST developers accessing a DB2 server?
Each VisualAge client image needs a connection to the DB, *if* the design has each directly using the DB. DB2/2 restrictions, if any, are per DB2's design for handling multiple users simultaneously. This is business as usual for DB2. You can also design your client-server app so that only the server app or only some client-side functions need DB access.
Do I have to follow a stored procedure execution with a commit?
There is an auto-commit option that you may like. If you send #autoCommit: true to your connection instance, commits will be done for you.
Why would I set the AbtDatabasePart's "database" attribute to nil?
As the comment states, the intention of setting the 'database' attribute to nil is to "Clear the database connection to force re-validation of settings".

Prior to executing a query, the current algorithm used by database query parts to validate settings will only execute if the 'database' attribute is nil. For typical usages of the query parts, settings validation only occurs the first time the part is executed in order to validate the pre-saved settings. Subsequent query executions would occur without need to validate the part settings. The change that is causing you 'grief' was implemented to prevent walkbacks that occured when an application set the querySpecName to an invalid name, then attempted to execute the query. Setting the 'database' attribute to nil caused the setting validation routine to re-execute and report an error rather than causing a walkback. For your case, there seems to be an undesired side-effect.

Potential solution...
Setting the cached 'database' attribute to nil clears the database connection for the part, but the database connection is still active within the image. When setting the value of the 'database' attribute, VisualAge looks for an active database connection with an 'alias' that matches the connectionAlias for the part. The logon prompt will NOT appear if the connection 'alias' of an active database connection matches the current 'connectionAlias' setting for the database part. In this case, the 'database' attribute for the part is set to the existing database connection instance.

FYI. If the connectionAlias is not supplied on connect, the default is 'DatabaseManagerClass_DatabaseName'. Verify that the connectionAlias for your part matches the desired active database connection.

Alternatively, you can comment out the 'self database: nil' from the VisualAge code to restore the V3.0 behavior. We will look for an alternative approach which does not cause the side effect that you've discovered.
How can I integrate a DB from VA with a DB in Lotus server?
You change the database design:
When you first establish your Notes Database in VisualAge, and in particular when you select the alias for the part, VisualAge takes a "snapshot" of the database to keep track of what the selected view or form looks like in Notes (depending on what VA part we're discussing. As you discovered, if the Notes database subsequently changes this snapshot and the database are out of sync.

You can remedy this by taking the following steps:
1. delete any quick forms related to the part.
2. open the settings for the form or view part and reselect the alias. This creates a new snapshot of the database.
3. recreate any quickforms you had.

Note that this is no different than the relational database parts. If the design of the relational database changes you may need to take these same steps with regard to your VA relational db parts.

- You change the contents of the database:
Although you're generally unaware of this, this is exactly how Notes works. Each client has their own view of the database and the documents in it. When you select refresh in the client (or when you reopen the datase) this view is reconstructed and changes that other users made to the database now become visible to you. The way you update this view in VA is to trigger the update action on the view. I generally do this by connecting a Refresh menu item's clicked event to the update action. Unlike the notes client, we do not automatically update a view when you open the database for performance reasons. So, if you want the view automatically refreshed when you open the database you will need to trigger the update action there as well. This is discussed in section 8.7.1.2.1.1 of the online documentation (search on update).

Home Page

Copyright 1997 Hatteras Software. Some portions copyright IBM.