Cincom Smalltalk. ObjectStudio. Database User s Guide P ObjectStudio 8.3

Size: px
Start display at page:

Download "Cincom Smalltalk. ObjectStudio. Database User s Guide P ObjectStudio 8.3"

Transcription

1 Cincom Smalltalk ObjectStudio Database User s Guide P ObjectStudio 8.3

2 Cincom Smalltalk ObjectStudio Database User s Guide Publication Number P , Cincom Systems, Inc. All Rights Reserved CINCOM SYSTEMS, INC. MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THE MATERIAL CONTAINED IN THIS MANUAL, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. The information contained in this manual is subject to change without notice. This manual contains proprietary information that is protected by copyright. All rights are reserved. It may not be photocopied, reproduced, or translated, in whole or in part, without the prior express written consent of Cincom Systems, Inc. See for a list of Cincom trademarks and other trademarks that may appear in Cincom product documentation. All other trademarks are trademarks or registered trademarks of their respective companies. Cincom Systems, Inc. 55 Merchant Street Cincinnati, Ohio USA PHONE: (513) FAX: (513) WORLD WIDE WEB: Attention: Some Cincom products, programs, or services referred to in this publication may not be available in all countries in which Cincom does business. Additionally, some Cincom products, programs, or services may not be available for all operating systems or all product releases. Contact your Cincom representative to be certain the items are available to you.

3 Release information for this manual Cincom Smalltalk ObjectStudio Database User's Guide, P , is dated February 16, This document supports Release 8.3 of ObjectStudio. Cincom Technical Support for ObjectStudio All customers Web: USA customers Phone: Fax: (513) Attn: ObjectStudio Support Mail: Cincom Systems, Inc. Attn: ObjectStudio Support 55 Merchant Street Cincinnati, OH USA Outside of USA All: Visit the support links at to find contact information for your nearest Customer Service Center. Document description This guide is for database application developers. It discusses Smalltalk classes and methods used in ObjectStudio to support database access. It also describes the tools in the ObjectStudio development environment that are relevant to creating database access. As a prerequisite, you should be familiar with relational database theory, the object-oriented approach to software development, and the ObjectStudio Smalltalk development environment.

4 Contents 1. Overview of database support How ObjectStudio supports databases What s new in ObjectStudio 8.x database support Objectives for rewriting the database wrappers Areas for improvement in Classic ObjectStudio Steps taken to address existing issues Improvements and new features Database classifications Database object framework Database objects Table objects Query objects Cursor objects Database tools How ObjectStudio implements database support Introduction Supported databases ODBC-compatible databases Oracle database IBM DB2 database Sybase database Internal Database Database classes Database class hierarchy Database class ExternalDatabase class ODBCDatabase class OracleDatabase class ESDatabase class (note that this is the class that supports DB2) SybaseDatabase class LocalDatabase class InternalDatabase class Table classes Table class hierarchy Table class ExternalTable class VectorTable class Database User s Guide, P Contents

5 Cursor classes Cursor class hierarchy Cursor class Nonscrollable cursors Scrollable cursors LocalCursor class Query classes Query class SqlDirect class SqlParse class SQL Query classes SqlSelect class SqlSubSelect class SqlUpdate class Working with databases Introduction Loading external database support Step-by-step instructions for alternative ways of loading a database application Connecting to a DBMS Connecting options Suppressing the default login screen for any database wrapper Database-specific connection information Accessing a database accessname: directory visibletablesat:put: Performing transactions Using SQL to query databases Methods for executing SQL statements Creating strings containing SQL code Using SQL versus using cursors Executing SQL with a local database Working with cursors Data format returned Cursor messages Methods for cursor support Types of cursors Using cursors with ODBC Using cursors with SQL Server Selecting multiple tables to create a cursor Working with tables Linking to cursors and tables Types of links Creating a normal link Creating an update link Enhancing performance Database User s Guide, P Contents

6 Handling errors Packaging applications Including login controllers in the image Delaying a database login ODBC Introduction ODBC database wrapper compatibility What s new in the ObjectStudio 8.x ODBC database wrapper Database logon authentication Domain authentication and database logon Database authentication and the new database logon dialog box Database authentication and the new database logon method ODBC elements ODBC conformance levels API conformance levels ODBC SQL grammar conformance levels ObjectStudio supports all ODBC conformance levels ObjectStudio ODBCDatabase and driver conformance-level dependencies Low-level ODBC support Additional ODBC classes Typical session Data type mapping System catalog access Example of using stored procedures Using stored procedures with an ODBCDatabase instance Parametric SQL statements Cursors and scrollable cursors Setting and getting connection options Using Multiple Active Result Sets (MARS) support in SQL Server's SQL Native Client Code samples Working with Binary Large Objects (BLOBs) Enabling ODBC Support Using chunks Handling errors DB Introduction What s new in the ObjectStudio 8.x DB2 database wrapper Connecting to a DB2 database Table information loaded when you access a DB2 database Using cursors and scrollable cursors Introduction to using cursors and scrollable cursors Scrollable cursors supported by the DB2 CLI Types of cursors supported by the ObjectStudio 8.x DB2 wrapper Example of non-scrollable and scrollable cursors Database User s Guide, P Contents

7 Executing stored procedures Introduction to executing stored procedures Methods to execute DB2 procedures Considerations for parameters used by stored procedures Examples of DB2 stored procedures Working with LOBs Introduction to working with LOBs General example for working with LOBs Working with LOBs in cursors and scrollable cursors Working with LOBs and files Oracle Introduction What s new in the ObjectStudio 8.x Oracle database wrapper Connecting to an Oracle database Getting version information for the Oracle client and server Table information loaded when you access an Oracle database Introduction to loaded table information Changing the table-loading SQL and reloading the table information Accessing tables in an OracleDatabase instance Using cursors and scrollable cursors Working with host variables Binding arrays Binding Class Instances Defining class TestBind Defining the instance methods for class TestBind Defining the class method for class TestBind Inserting the TestBind instances into the test table Binding arrays using an instance of the TestBind class Executing Oracle PL/SQL procedures Introduction to executing Oracle PL/SQL procedures Example of working with Oracle stored procedures Executing Oracle PL/SQL functions Introduction to executing Oracle PL/SQL functions Examples of calling Oracle PL/SQL functions Support for Oracle Nested Tables and Oracle PL/SQL REF Cursors Introduction Two alternative approaches to retrieving Oracle Nested Table information Using Oracle PL/SQL REF Cursors with Oracle Nested Tables, in Oracle functions and procedures Code sample for retrieving Oracle Nested Tables and for using Oracle REF Cursors in Oracle functions and procedures Array fetch Prefetching rows Introduction to prefetching rows Appropriately allocating memory for prefetching rows Workspace example for prefetching rows Database User s Guide, P Contents

8 Using LOB proxies Introduction to using LOB proxies Method for returning LOBs by proxy or by value Processing LOBs after they have been returned by proxy Using LOB insert/retrieval/write Making adjustments to improve LOB performance Introduction to making adjustments to improve LOB performance Changing the size of the LOB buffer Changing the size of the returned LOB values Example for changing the LOB buffer size and changing the size of returned LOB values Using statement caching Introduction to using statement caching Turning on statement caching Sybase Introduction What s new in the ObjectStudio 8.x Sybase database wrapper Connecting to a Sybase server Using Sybase default client password encryption Table information loaded when you access a Sybase database Sybase wrapper functionality example A complete code example Variables in queries Creating and invoking Sybase stored procedures Database Notebook Introduction Using the Database Notebook Database Notebook pop-up menu Creating a new database Creating and modifying a table Saving changes to the Internal Database Entering data Accessing the default data entry form Customizing the Data Entry dialog box Managing data Opening the default Data Manager Customizing the Data Manager Form Creating a SQL query Using the SQL tools Using the SQL Browser SQL tools Introduction Database User s Guide, P Contents

9 SQL Editor Creating an SQL statement Using the Selection dialog box Executing a statement Defining a WHERE clause Defining a JOIN clause Defining a GROUP BY clause Defining a HAVING clause Defining an ORDER BY clause Creating parametric SQL statements Committing changes Rolling back changes Importing and exporting statements Creating a report for the statement SQL Window File menu Actions menu Creating an SQL statement Loading an ASCII text file into the SQL Window Report Editor Using the Report Editor Creating a report Saving reports Working with report sections Level breaks Adding or removing sections Formatting sections Using level breaks Working with report items Adding report items Resizing report items Deleting report items Copying or moving report items Formatting report items Formatting multi-line string items Formatting graphic items Formatting lines and topic boxes Creating and formatting bitmapped images Registering a graphics file Defining and formatting graphs and graph legends Placing a graphics field Defining a graphics field Formatting graphics fields Formatting graphics legends Database User s Guide, P Contents

10 Formatting, previewing, and printing a report Formatting report pages Previewing a report Printing from the Report Preview Setting the report timer Setting output options Printing or previewing a report A. Cross-platform development Windows character set conversion Index Database User s Guide, P Contents

11 1. Overview of database support How ObjectStudio supports databases Support for each database is a loadable application (or package, if using the Repository) containing class and method definitions that allow you to work with that specific database. Features of ObjectStudio database support include: Easy porting of an application from one database to another. The ability to access more than one database simultaneously, whether of the same type or of different types. What s new in ObjectStudio 8.x database support Objectives for rewriting the database wrappers In ObjectStudio 8.x, Cincom has rewritten its database wrappers in order to fulfill the following objectives: Make the ObjectStudio 8.x database wrappers compatible with the Classic ObjectStudio wrappers. Remove the C code between the Smalltalk code and the database client libraries. Lift the database wrappers dependency on database client versions. Add more functionality (for example, LOB support, host variable support, and so on). Improve performance. Database User s Guide, P Chapter: 1. Overview of database support Section: How ObjectStudio supports databases

12 Areas for improvement in Classic ObjectStudio Classic ObjectStudio database support has several areas that could be improved. In Classic ObjectStudio: Cincom uses C code as the bridge between Smalltalk code and the database client libraries. For some database wrappers, such as the ones for Oracle and DB2, Cincom uses precompilers. This means that the generated DLLs sometimes work only with the database client versions used to create them. The DB2 wrapper has binding files associated with the DLLs. This approach places limitations on the database wrappers. Users have a hard time adding desired new features because they have no access to the C code. Also, database wrappers are dependent on specific database client versions. These issues cause problems for customers and for Cincom Support. Steps taken to address existing issues Cincom has addressed the issues that exist in Classic ObjectStudio database support. In ObjectStudio 8.x: Users can now easily add new features to database wrappers. This is because there is no C code and no embedded SQL in the ObjectStudio 8.x database wrappers. Cincom uses only Smalltalk code in these wrappers. Cincom has removed the dependency on database client versions. For example, the Oracle database wrapper will work with all Oracle clients, as long as the oci.dll file is in an accessible folder whose path is specified by the PATH environment variable. The same principle applies to the DB2 database wrapper, and to the other database wrappers. There are no DLLs between the Smalltalk code and the database client libraries. Since the Smalltalk code is transparent to users, they can easily add new features themselves. Database User s Guide, P Chapter: 1. Overview of database support Section: What s new in ObjectStudio 8.x database support

13 Improvements and new features In ObjectStudio 8.x, Cincom has added several improvements and new features to the database wrappers. These include (but are not limited to): Improved LOB processing in Oracle and DB2 wrappers Improved stored procedure support in Oracle, DB2, Sybase, and ODBC wrappers Improved host variable support New support of stored procedures with INPUT parameters, OUTPUT parameters, and return values in the ODBC wrapper A number of improvements have already been implemented. Cincom is continuing to improve existing ObjectStudio 8.x features and to add new ones. Therefore, for Classic ObjectStudio users looking for better database support, moving to ObjectStudio 8.x is a smart decision. In the long run, it will save users both time and money. Database classifications ObjectStudio classifies databases as either: Local. There is one local database (the Internal Database) for prototyping. The Internal Database allows you to design and test an application without consuming valuable server resources. The Internal Database is limited in size by the amount of memory in your system. External. There are a number of external databases supported by ObjectStudio. Database User s Guide, P Chapter: 1. Overview of database support Section: Database classifications

14 Database object framework ObjectStudio implements the following classes to support database connections: Database Table Query Cursor This structure matches typical relational database objects and provides a common frame of reference for working with databases. For each supported database, ObjectStudio provides subclasses of each of these classes. Use these classes to define the access layer of an application. For more information, see Database classes on page 20. Database objects Each database that ObjectStudio supports is represented as a subclass of class Database. When you open a connection to a specific database, ObjectStudio creates an instance of the appropriate Database subclass. You can send messages to Database objects to open cursors, execute SQL statements, and begin and end transactions. Database objects also maintain information regarding the differences between database types. Database User s Guide, P Chapter: 1. Overview of database support Section: Database object framework

15 Table objects Databases contain Table objects that represent the structure of each table within a database. A Table object describes a database table s columns and the data type of each column, but it does not contain the actual data. You can query a Table object for its attributes, including column information and records. You can add, remove, and modify records directly through the Table object, or you can perform these functions using a combination of SQL statements and cursors. For external databases, using SQL statements can be more efficient than working with Table objects. Query objects Query objects allow you to save SQL queries as objects. You can create a link to a query, either visually using the Designer, or with a method-based Model View Controller (MVC) interface. You can pass a Query object to a database for execution, or you can use a Query object to open a cursor. Queries can include parameters. Associated with each parameter is a block of Smalltalk code that is executed dynamically to get the parameter value when the query is performed. Cursor objects Cursor objects are used to process a result set, which is the set of records obtained by executing a query. When you work with cursors, the DBMS keeps the result set. This allows ObjectStudio to work with one record at a time. Cursors are useful when you are working with a large result set, enabling you to read, update, and delete individual records. Database User s Guide, P Chapter: 1. Overview of database support Section: Database object framework

16 Database tools ObjectStudio provides database tools for data definition and data manipulation. Use these tools to work with application data after you define the data access layer of an ObjectStudio application. The database tools include: Database Notebook. Data management facility that builds a default form for any Table or Query. Use the default form to perform data manipulation and data entry. You can customize the form for inclusion into an end-user application. SQL Editor. Graphical query builder that allows you to construct Query objects. You can include the Query objects within an application framework. Report Editor. Facility for creating database reports. Database User s Guide, P Chapter: 1. Overview of database support Section: Database tools

17 2. How ObjectStudio implements database support Introduction Supported databases This chapter describes the databases and the classes that ObjectStudio supports. This section provides a brief overview of each database that ObjectStudio supports. Specifications are supplied for each database, including: Loadable application (Package, if using the Repository) Subclass of Database Subclass of Table Subclass of Cursor ObjectStudio uses a common object model to support DBMS and database connections. The model implements abstract classes to support Databases, Tables, Cursors, and Queries. Use these classes to create the database access layer of an application. Support for each database is implemented as a loadable application (or package, if using the Repository). For more information on loading databases, see Loading external database support on page 34. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Introduction

18 ODBC-compatible databases Loadable application/package: Subclass of Database: Subclass of Table: Subclass of Cursor: Note ODBC ODBCDatabase ODBCTable ODBCCursor ODBCScrollableCursor While the ODBC wrapper can theoretically be used to connect to any ODBC-compatible database, the ODBC wrapper is specifically tested, with every release of ObjectStudio 8.x, against only the following four database types: IBM DB2 database Oracle database Microsoft SQL Server database Sybase database In order to access the Microsoft SQL Server database from an ObjectStudio application, you have only the option of using the ODBC wrapper. However, with the DB2, Oracle, and Sybase databases, you have the option of using either the ODBC wrapper or one of the supplied database-specific, native wrappers. The advantage of using one of the native wrappers is that it will offer potentially improved performance over the ODBC wrapper. This is because a native wrapper communicates directly with the database library, without the intermediary of the ODBC library. Oracle database Loadable application/package: Subclass of Database: Subclass of Table: Subclass of Cursor: Oracle Database Client OracleDatabase OracleTable OracleDatabaseCursor OracleScrollableCursor Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Supported databases

19 IBM DB2 database Loadable application/package: Subclass of Database: Subclass of Table: Subclass of Cursor: Sybase database Loadable application/package: Subclass of Database: Subclass of Table: Subclass of Cursor: Internal Database Loadable application/package: Subclass of Database: Subclass of Table: Subclass of Cursor: DB2 Database ESDatabase ESTable ESDatabaseCursor ESScrollableCursor Sybase OpenClient SybaseDatabase SybaseTable SybaseDatabaseCursor SybaseScrollableCursor None (represented by a proxy, loads upon first access) LocalDatabase Not applicable Not applicable Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Supported databases

20 Database classes The database classes have the following features: They implement methods that open cursors, execute SQL statements, and begin and end transactions. They contain Table objects that represent each table within a database. You can retrieve and manipulate these tables within ObjectStudio. ObjectStudio database support is implemented on top of VisualWorks EXDI framework, instead of the DLL mechanism used by earlier version of ObjectStudio. Refer to the VisualWorks Database Application Developer's Guide for additional information about the EXDI. Database class hierarchy The Database class hierarchy is: Database (Abstract) ExternalDatabase (Abstract) ESDatabase ODBCDatabase OracleDatabase SybaseDatabase LocalDatabase (Abstract) InternalDatabase The remainder of this section describes the classes in the Database class hierarchy. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Database classes

21 Database class The Database class is an abstract class, which defines the basic functions for its subclasses. All subclasses of Database inherit the following features from Database: Ability to track all accessible databases Logon and Logoff functions (if they are needed) Ability to track the database types that are loaded in ObjectStudio An instance of the Database class: Contains instances of subclasses of class Table that represent each table in the physical database. Executes an SQL string. Creates a cursor as part of executing an SQL SELECT statement (optionally). The cursor, which is a direct connection to the result set, allows the user to update the database. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Database classes

22 ExternalDatabase class The ExternalDatabase class is an abstract class that implements features specific to external databases. All external database classes are subclasses of this class. The main difference between the ExternalDatabase and LocalDatabase classes is that ExternalDatabase passes SQL statements directly to the physical database. The LocalDatabase class includes a query evaluator. The ExternalDatabase class adds itself to the StartStopAnnouncementList global variable when the class is loaded. If you then save this image with active databases, ObjectStudio will try to reconnect to those databases on startup. For details about how this is implemented, refer to the start and stop class methods in the ExternalDatabase class. For more information about how StartStopAnnouncementList can be used in ObjectStudio, refer to the ObjectStudio User s Guide, P Class ExternalDatabase uses the variable DataLoadLimit to restrict the number of rows returned by an SQL query. The default maximum number of rows is 500. To change the value, send the setdataloadlimitto: class message. ExternalDatabase allows you to use the Visible Tables feature to tell ObjectStudio with which tables you want to work. You can use this feature when the database has a large number of tables to prevent ObjectStudio from querying the physical database to determine the name of each table. For more information on this feature, see Enhancing performance on page 55. ODBCDatabase class The ODBCDatabase class implements the access layer for the complete Microsoft ODBC Version 2.5 Application Programming Interface (API). It provides you with easy access to the X/Open-compliant Call Level Interface (CLI) to SQL databases and to Microsoft extensions to this standard, as specified in the ODBC Version 2.5 specification document. From ObjectStudio, you can use either high-level support or low-level support for ODBC. High-level support works with the ODBCDatabase class. You may want to use high-level support if you have already implemented database code in ObjectStudio. With low-level support, you program directly to the SQL Access Group (SAG) CLI. For more information on low-level support, see Low-level ODBC support on page 62. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Database classes

23 OracleDatabase class The OracleDatabase class implements the access layer for Oracle databases. In addition to the features it inherits, this class supports: Execution of PL/SQL blocks, stored procedures, and functions Setting the number of records retrieved using arrayfetch, with execsql: and loadsql: Setting the maximum number of bytes returned for LOB columns Setting the size of the buffer used to copy data between applications and the database servers, in order to improve performance Setting the maximum number of characters returned for a LONG column Using logon methods Gaining access to an instance of OracleDatabase on login ESDatabase class (note that this is the class that supports DB2) The ESDatabase class implements the access layer for DB2 databases. In addition to the features it inherits, this class supports: Execution of stored procedures Processing DB2 Large Objects (LOBs) Setting the maximum number of bytes returned for LOB columns Setting the size of the buffer used to copy data between applications and the database servers, in order to improve performance Using logon methods Gaining access to an instance of ESDatabase on login Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Database classes

24 SybaseDatabase class The SybaseDatabase class implements the access layer for Sybase databases. In addition to the features it inherits, this class supports: Execution of Sybase stored procedures Using logon methods Gaining access to an instance of SybaseDatabase on login LocalDatabase class The LocalDatabase class is an abstract class that implements features specific to databases that require their own SQL query evaluator. LocalDatabase implements the query evaluator as instance methods, which are inherited by all its subclasses. InternalDatabase class The InternalDatabase class provides a mechanism for treating objects as if they were tables. The Internal Database is extremely useful for prototyping when you are developing an application. You can also use the Internal Database to work with data that resides in more than one database. The Internal Database, however, does not have the features of a real DBMS, such as locking, facilities for multiple users, and transaction control. It also does not save its data to files on disk. To interact with the Internal Database, use the Database Notebook, as described in Using the Database Notebook on page 189. The InternalDatabase class supports a collection of instances of class Table. In every ObjectStudio environment, there is a single instance of the InternalDatabase class, called EnfinInternalDb. If an instance of class Table is a member of this database, it can be included in SQL queries against the Internal Database. The InternalDatabase class implements the tablelocations variable. When an instance of the InternalDatabase class is asked for a particular table, it first looks to see if the table exists. If the table does not exist, it looks in tablelocations to see if the table is referenced there. If it exists, it uses the tablelocations variable to load a class that recreates the table. This variable allows internal tables to be loaded on demand. ObjectStudio supplies several example tables that work with the Internal Database and are handled this way. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Database classes

25 Table classes There is a Table subclass for each type of supported database. For all databases, each Table class maintains information about the external column types supported by the database and can map the column types into ObjectStudio objects. The Table instances for the Internal Database also contain each table s data. The Table classes implement: The dbtablesat: method, which retrieves a Table instance from its associated database Methods that query for attributes, including column information and records Methods that add, remove, and modify records directly Methods that handle SQL statements and cursors Table classes allow you to link to tables using the Designer or using a programmatic Model View Controller (MVC) interface. Table class hierarchy The Table class hierarchy is: Table (ObjectStudio Internal Table) ExternalTable (Abstract Class) ESTable ODBCTable OracleTable SybaseTable VectorTable The remainder of this section describes the classes in the Table class hierarchy. Table class The Table class is an internal ObjectStudio abstract class that supports a table structure. It provides methods for table creation and modification, record insertion, record deletion, and record modification. Tables can also be saved to and loaded from disk. Subclasses of Table inherit its methods. To create a Table, send the execsql: method to an instance of class InternalDatabase or ExternalDatabase. The method returns an instance of Table. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Table classes

26 ExternalTable class The ExternalTable class is an abstract class that provides the framework for tables associated with objects of class ExternalDatabase. It also allows you to manage cursors for use in all record access methods. To use the cursor methods, you first must send the startaccessforupdate: message. The following table lists the subclasses of ExternalTable and the databases to which they correlate: Database DB2 ODBC Oracle Sybase Subclass of ExternalTable ESTable ODBCTable OracleTable SybaseTable VectorTable class The VectorTable class is a special type of internal table class that stores table data by column rather than by row. VectorTable stores numeric columns as vectors and stores nonnumeric columns as arrays. This strategy saves space because numeric columns can be stored as single objects. The interfaces to VectorTable and Table are nearly identical. Therefore, you can use the two classes interchangeably. At times, using VectorTable is more efficient because accessing data by row can be slower than accessing a Table object. This is because the rows must be constructed as needed. One way to create an instance of VectorTable is to use the return value (a VectorTable) of loadsql: (a message that you send to an instance of Database). Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Table classes

27 Cursor classes A cursor is a common DBMS mechanism that returns rows of a result set one row at a time. The result set of a cursor exists on the DBMS. The ObjectStudio Cursor classes allow the control of the cursor object (the result set) that resides on the DBMS. Usually, the cursor mechanism is vendor-specific. ObjectStudio Cursor classes for different DBMSs operate in basically the same manner. You open a cursor by sending a variation of the opencursor message to a database and by providing an SQL SELECT statement. Once a cursor is open, you can use it to position the current row in the result set, to update column values for the current row, and to delete the current row. For more information on using cursors, see Working with cursors on page 47. Cursor class hierarchy The Cursor class hierarchy is: Cursor (Abstract Class) ExternalDatabaseCursor (Abstract Class) ESDatabaseCursor ExtDbScrollableCursor (Abstract Class) ESScrollableCursor ODBCScrollableCursor OracleScrollableCursor SybaseScrollableCursor ODBCCursor ESDatabaseCursor OracleDatabaseCursor SybaseDatabaseCursor LocalCursor (Abstract Class) The remainder of this section describes the classes in the Cursor class hierarchy. Cursor class The Cursor class is an abstract class that provides basic features for all database cursors. The class keeps track of the query that created the cursor, including its field names, types, and formats. It maintains a current position in the result set, and it contains the necessary machinery for ObjectStudio Designer MVC links. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Cursor classes

28 Nonscrollable cursors This section describes classes that implement nonscrollable cursors. ExternalDatabaseCursor class The ExternalDatabaseCursor class is an abstract class that implements features for external database nonscrollable cursors. In addition to the features it inherits, it implements features that: Add records Perform positioned updates and deletes Move the record pointer forward to the next record Other nonscrollable cursor subclasses The following table lists the subclasses of ExternalDatabaseCursor and the databases to which they correlate. Each of these subclasses represents a nonscrollable cursor. Database DB2 ODBC Oracle Sybase Subclass of ExternalDatabaseCursor ESDatabaseCursor ODBCCursor OracleDatabaseCursor SybaseDatabaseCursor Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Cursor classes

29 Scrollable cursors This section describes classes that implement scrollable cursors. ExtDbScrollableCursor class The ExtDbScrollableCursor class is an abstract class that implements features for external database scrollable cursors. In addition to the features it inherits, it implements features that: Add records Perform positioned updates and deletes Ask for the size of the result set Move the record pointer to any position in the result set ODBCScrollableCursor class The ODBCScrollableCursor class uses native scrollable cursors (that is, cursors that are supplied by the database driver) if the data source offers the following features: ODBC API call SQLExtendedFetch Two fetch options: - SQL_FD_FETCH_NEXT - SQL_FD_FETCH_PREV At least one of the following scroll options: - SQL_SO_KEYSET_DRIVEN - SQL_SO_DYNAMIC - SQL_SO_MIXED Otherwise, ObjectStudio provides a simulated scrollable cursor, which is based on native fetch-forward-only cursors. To determine whether the database driver complies with the features described in the previous list, send the message nativescrollablecursors to class ODBCDatabase. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Cursor classes

30 Other scrollable cursor subclasses The following table lists the subclasses of ExtDbScrollableCursor and the databases to which they correlate. Each of these subclasses represents a scrollable cursor. Database DB2 ODBC Oracle Sybase Subclass of ExtDbScrollableCursor ESScrollableCursor ODBCScrollableCursor OracleScrollableCursor SybaseScrollableCursor LocalCursor class The LocalCursor class is an abstract class that implements cursors for local database cursors. The class implements methods that: Add records Perform positioned updates and deletes Move the record pointer to any position in the result set Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Cursor classes

31 Query classes The Query classes provide a mechanism for saving SQL queries and linking to them. You can implement the links either visually, by using the Designer, or programmatically, by working with the MVC interface. You can pass a query object to a database for execution or to open a cursor. The Query class hierarchy is: Query (Abstract Class) SqlDirect SqlParse (Abstract Class) SqlDelete SqlInsert SqlSelect SqlSubSelect SqlUpdate The remainder of this section describes the classes in the Query class hierarchy. Query class The Query class is an abstract class that implements the basic features of queries. Primarily, it keeps track of all instances of its subclasses. SqlDirect class The SqlDirect class provides the ability to create an SQL object for a string that cannot be parsed by ObjectStudio. This includes all non-ansi-standard SQL statements such as stored procedure access for SQL Server and PL/SQL for Oracle. SqlDirect implements a creation routine, the new: class method, which takes the SQL string as a parameter. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Query classes

32 SqlParse class The SqlParse class is an abstract class that provides features for all query types that can be parsed by ObjectStudio. The class includes the query parser and some default behavior. To create an instance of SqlParse (or one of its subclasses), send the parsestring: class method. This method takes an SQL string and, depending on the type of SQL statement, either generates an error or an instance of one of the SqlParse subclasses. SQL Query classes The following table lists the SQL Query classes and the SQL queries that they represent: Query class SqlDelete SqlInsert SqlSelect SqlSubSelect SqlUpdate Note the following about SQL Query classes: Query type SQL DELETE SQL INSERT SQL SELECT SQL SUBSELECT SQL UPDATE The easiest way to create an instance of each of these classes is to use the SQL Editor, which is described in SQL Editor on page 205. You can create an SQL object by sending the parsestring: message to the Query class or to one of its subclasses. The parameter is an SQL string. To execute an SQL query, send execute to an instance of the Query class or one of its subclasses. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Query classes

33 SqlSelect class In addition to using the execute message, you can use one of the opencursor or openscrollablecursor messages to pass an SQL SELECT statement to a DBMS. You can also use the Designer to link to an SqlSelect object. You can associate a cursor with an SqlSelect instance. The first time the startaccessforupdate:scrollable: message is sent to an SqlSelect object, a cursor is opened and returned. You can specify that a cursor is updateable or scrollable in the original startaccess method, or you can change the cursor in subsequent sends. The cursor is shared with all callers of the startaccessforupdate:scrollable: message. Add dependencies to the cursor rather than to the SqlSelect object. This ensures that all objects using the query are using a common cursor and that updates to the cursor are reflected in all objects using it. A refresh message is also supported by SqlSelect objects; it rebuilds the associated cursor and updates all its dependencies. SqlSubSelect class Instances of the SqlSubSelect class provide for subselects within SQL statements. Generally, they are used internally only within other SQL objects. SqlUpdate class Instances of the SqlUpdate class provide for the SQL INSERT statement. Use the execsql: message to pass an SqlUpdate query to a database. Database User s Guide, P Chapter: 2. How ObjectStudio implements database support Section: Query classes

34 3. Working with databases Introduction This chapter provides information on techniques to use when you work with databases. These techniques apply to all database platforms. Where appropriate, there is additional information necessary for working with a specific database. Loading external database support Before you can work with an external database, you must load an application that supports access to a specific DBMS into the ObjectStudio environment. The Internal Database is already loaded into the ObjectStudio environment. For more information on the Internal Database, see Internal Database on page 19 and InternalDatabase class on page 24. After loading the application that supports your underlying database, you have complete access to the databases and tables associated with your database management system (to the limits defined by your database administrator). For a complete list of supported databases and gateways, see Supported databases on page 17. Step-by-step instructions for alternative ways of loading a database application Introduction The following instructions describe alternative ways of loading a database application: Manually. See Loading a database application manually on page 35. Programmatically, from the Workspace. See Loading a database application programmatically, from the Workspace on page 35. From the command line, using the l command-line option. See Loading a database application programmatically, using the l option on page 36. Database User s Guide, P Chapter: 3. Working with databases Section: Introduction

35 Loading a database application manually To load a database application manually, perform the following: 1. Ensure the external database is available, either locally or through a network connection. (See your network administrator if you need help.) 2. Load the database application: A. Select the File > Load application option from the Desktop menu. The Applications dialog opens. B. On the Applications dialog, select the name of the application for the DBMS with which you want to work. C. Click the Load button. As the application loads, ObjectStudio does the following: Creates the subclasses of Database, Table, Cursor, and Query for the DBMS with which you are working Initiates the login procedure, if applicable, to the database 3. If a database logon interface appears, enter the requested information. If your underlying database requires you to log on, ObjectStudio creates a logon interface on the work area of the Desktop. The logon interface opens automatically if you attempt to access the database without logging on. To access your external database every time you start ObjectStudio, save an image file after loading the application. For more information on saving the ObjectStudio image, refer to the ObjectStudio User s Guide, P Loading a database application programmatically, from the Workspace Assume the following for the sample Workspace code: You will be loading the ODBC wrapper. The default US location for the ObjectStudio 8.x database package files is the following directory (with the x in 8.x replaced by the appropriate ObjectStudio version number): C:\Program Files\Cincom\ObjectStudio8.x\ObjectStudio\parcels\database To load the ODBC wrapper programmatically, run the following code in the Workspace: LoadableApplicationDictionary loadosapplication: 'ODBC' from: 'database\objectstudio ODBC Wrapper.pcl' Database User s Guide, P Chapter: 3. Working with databases Section: Loading external database support

36 Loading a database application programmatically, using the l option Assume the following for the sample l command line option: You will be loading the ODBC wrapper. The ObjectStudio files are stored in the following folder, with the x in 8.x replaced by the current ObjectStudio version number:: C:\Program Files\Cincom\ObjectStudio8.x\ObjectStudio\ To load the ODBC wrapper from the command line, using the l command line option, perform the following: 1. Open a command-line window. 2. Set the current directory to the following, with the x in 8.x replaced by the current ObjectStudio version number: "C:\Documents and Settings\All Users\Application Data\Cincom\ObjectStudio8.x\" 3. Run the following command to start ObjectStudio 8.x, with the x in 8.x replaced by the current ObjectStudio version number: "C:\Program Files\Cincom\ObjectStudio8.3\ObjectStudio.exe" Objectstudio.im ostudio " -l'c:\program Files\Cincom\ObjectStudio8.x\ObjectStudio\parcels\database\ ObjectStudio ODBC Wrapper.pcl'" Database User s Guide, P Chapter: 3. Working with databases Section: Loading external database support

37 Connecting to a DBMS This section describes how to log in to a DBMS from ObjectStudio. Logging in involves identifying the server on which the database is installed and initializing communications to that server. Each database has its own login procedure. ObjectStudio provides methods that you can use with most of the databases that ObjectStudio supports. After you log in to a database, select the specific database that you want to access. For a description of this process, see Accessing a database on page 39. You do not need to log in to the Internal Database. For more information on the Internal Database, see Internal Database on page 19 and InternalDatabase class on page 24. Connecting options There are two ways in which you can connect to a database: Programmatically With a controller Connecting programmatically You can log in to a database programmatically, without using the ObjectStudiosupplied login controller. To do so, use the Class Browser to search for the login messages for the database you are using. Connecting with a controller For most DBMSs, you can display a login controller (a user interface) that prompts for a user name, a password, and a server name. ObjectStudio provides the following Database class methods that allow you to work with a login controller for the DBMS with which you are working: haslogonview. Returns a Boolean value indicating whether the database has a controller for logging in associated with it. logonview. Returns the controller that allows a user to log in to a database. Include this controller in the image that you create for the application. initialize. Opens the login controller for the database. When the user clicks OK on the controller, ObjectStudio logs the user in to the database. Database User s Guide, P Chapter: 3. Working with databases Section: Connecting to a DBMS

38 Suppressing the default login screen for any database wrapper It is possible to suppress the default login screen for any ObjectStudio database wrapper. To do so, perform the following: 1. Open the initialize class method in the desired database class. For example, in the case of Oracle, open the OracleDatabaseClass>>initialize method. 2. Comment out the following line: databasenamelogon open In the preceding code, replace databasename with the name of your database. For example, in the case of Oracle, comment out the line consisting of OracleLogon open. 3. Save the modified initialize class method. The next time you open the database whose initialize class method you modified, the default logon screen will be suppressed. Database-specific connection information Each database has a specific login procedure: ODBC. When you log in to an ODBC database, type your user name in the User Name field, your password in the Password field, and an ODBC DSN connect string in the server entry field. If you do not provide a user name and password, Windows authentication is assumed. Oracle. When you log in to an Oracle database, type an SQL*Net connect string in the server entry field. If you do not provide an SQL*Net string, a local connection is assumed. IBM DB2. When you log in to a DB2 database, type your user name in the User ID field, your password in the Password field, and the server name in the Server Name entry field. Sybase. When you log in to a Sybase database, type the server name in the Server entry field, your user name in the User Name field, and your password in the Password field. Internal Database. You do not need to log in to the Internal Database. Database User s Guide, P Chapter: 3. Working with databases Section: Connecting to a DBMS

39 Accessing a database This section describes how to select the specific database with which to work. This process is also called making a database active. In programmatic terms, when you access a database, ObjectStudio creates an instance of the appropriate subclass of Database. ObjectStudio allows you to access one database of a given type at a time. However, you can access more than one database type at a time. For example, you can access only one ODBC database at a time, but you can access an ODBC database and an Oracle database simultaneously. The subclasses of Database support the following class methods that help you access a database. accessname: The parameter is an instance of class Symbol that represents the name of the database you want to access. On success, the method returns an instance of the appropriate subclass of Database. If the method is unsuccessful, it returns an instance of Message, which contains an error message. The accessname: method can place locks on data. After performing an accessname:, you may want to perform the commit method to release those locks. For more information on the commit method, see Performing transactions on page 42. directory Returns an array of symbols representing names of available databases. Usually, you develop an application that uses a specific database, so you do not need to use this method. The Database Notebook is an example of an application that uses this method. Database User s Guide, P Chapter: 3. Working with databases Section: Accessing a database

40 visibletablesat:put: This method is implemented in ExternalDatabase and its subclasses. Use this method when the application is working with a large database but only needs to use some of the data. Perform this method before performing the accessname: method to restrict the tables of a database with which ObjectStudio interacts. You can also perform the method at any time to change the visible tables for the database. For example: ExternalDatabase visibletablesat: databasename put: array where: databasename is an instance of class Symbol that represents the database with which you are working. array is an array of instances of class Symbol that represent qualified or unqualified table names. If the table names are not qualified, the current user is assumed to own the table. If they are qualified, they should be in the form: #'owner.tablename' Database User s Guide, P Chapter: 3. Working with databases Section: Accessing a database

41 The following table lists variations on the array parameter: Variation Array of symbols nil Use Prevents catalog access to the database. It limits tables to those listed in the array. Use this option before accessing the database in order to set initial table access, or at any time to change table access. If the array includes an invalid table name, ObjectStudio creates an empty table with the invalid name. If the Database Notebook displays a table with no column names, or if you attempt to access a table and receive a Table not found message, check that all table names are specified or are qualified correctly. Performs catalog access of the database. Instructs the system to ignore the visible tables list. { } (empty array) Prevents catalog access and sets visibletables to none. Use this option when no Table objects are needed. If you are using execsql:, loadsql:, and cursors, exclusively, you do not need access to Table objects. Table objects are necessary only when you are linking to them, referring to them in code, or using the ObjectStudio Table tools (for example, the Database Notebook). Database User s Guide, P Chapter: 3. Working with databases Section: Accessing a database

42 Performing transactions ObjectStudio supports database transactions, which are units of work that the database can either save or undo. Traditionally, a transaction is performed this way: 1. Begin the transaction. 2. Perform the unit of work. 3. End the transaction (either save it or undo it). Ending a transaction can release data locks. Transactions in ObjectStudio have the following features and restrictions: You can perform several steps before you end the transaction. You cannot nest transactions. Most database servers do not require that transactions be started explicitly. ObjectStudio provides the following instance methods in class Database to support transactions. begintran. Begins a transaction. This method is required for SQL Server and SYBASE OpenClient databases. It is implemented for other database platforms but does nothing. commit. Ends a transaction by saving the work you did since the last commit or rollback. The accessname: and dbtablesat: methods can place locks on data. After performing these methods, you may want to perform the commit method to release those locks. rollback. Ends a transaction by undoing the work you did since the last commit or rollback. Local databases and transactions. Local databases do not perform transactions. For local databases, the transaction methods begintran, commit, and rollback are implemented but do nothing; they are provided for compatibility with external databases. Database User s Guide, P Chapter: 3. Working with databases Section: Performing transactions

43 Using SQL to query databases This section describes how to interact directly with a database through its SQL interface. Methods for executing SQL statements ObjectStudio provides the following instance methods in subclasses of Database that allow you to execute SQL statements on the DBMS: execsql: astring. Executes an SQL statement. The astring parameter is an SQL string. The string can contain any statements that the target accepts. For more information on creating an SQL string, see Creating strings containing SQL code on page 45. If the SQL statement is an INSERT statement, the method returns a small integer representing the return code. If the SQL statement is a SELECT statement, the result of the method is an instance of Table. On some database platforms, an SQL statement can contain multiple clauses. The return value of a multiple-clause statement is an array of tables. You can treat the resulting table like any other Table object in the ObjectStudio environment. You can perform the following tasks with it: - Use the Table method interface. - Add the table to the Internal Database and perform subsequent SQL statements on it. When you use this technique, subsequent SQL statements are performed in memory and do not require additional fetches from the original database. - Link to the table using ObjectStudio TableLinks. The instance of Table has an instance variable, dbrecords, which is an array. Each element of the array is also an array and represents a record in the table: { {Row 1 elements} {Row 2 elements}... } Database User s Guide, P Chapter: 3. Working with databases Section: Using SQL to query databases

44 execsql: astring onerror: ablock. Executes an SQL statement in the same manner as execsql: but also allows you to specify a 1-parameter block. If an error occurs during the execution of the SQL statement, ObjectStudio passes the error code to the block and performs the code in the block. execsql: astring vars: vars. Executes an SQL statement (which cannot, in this case, be a select statement) in the same manner as execsql: but also allows you to specify parameters. These parameters must be bound for execution. The vars array contains the string values to be bound to the SQL statement. Subclasses of ExternalDatabase that support execsql:vars:. Only two subclasses of ExternalDatabase, ESDatabase and OracleDatabase, really support execsql:vars:. Calling this method from other subclasses of ExternalDatabase will result in an error. loadsql: astring. Executes an SQL SELECT statement in the same manner as execsql: and returns an instance of the class VectorTable. VectorTable is a special type of internal table that stores table data by column rather than by row. The dbrecords instance variable has the following format: { {Column 1 elements} {Column 2 elements}... } VectorTable provides an interface that is almost identical to that of internal tables, so that you can use the two interchangeably. The advantage of using a VectorTable is that it stores numeric columns as vectors, rather than as arrays. VectorTable is efficient for dealing with numeric data, because a numeric column is one object. However, VectorTable is slower than regular Tables for working with individual rows. To work with a row in a VectorTable, ObjectStudio must select one element from each column array or vector. loadsql: astring onerror: ablock. Executes an SQL SELECT statement in the same manner as loadsql: and returns an instance of the class VectorTable. It also allows you to specify a 1-parameter block. If an error occurs during the execution of the SQL statement, ObjectStudio passes the error code to the block and performs the code in the block. setdataloadlimitto:. Sets the maximum number of rows to return from an SQL SELECT statement by assigning a value to the variable dataloadlimit. The default value is 500. This method is for subclasses of ExternalDatabase only. Database User s Guide, P Chapter: 3. Working with databases Section: Using SQL to query databases

45 Creating strings containing SQL code The first parameter to the execsql: or loadsql: methods is a string containing SQL code. This section provides information about creating an SQL string. Using standard SQL Recall that some database platforms allow variations in SQL code. If you are writing SQL code that you may want to use on more than one database platform, remember to write SQL code that is standard across platforms. Creating the string An SQL string is a standard Smalltalk string that you create by using standard string-construction methods, for example: str := 'EXEC SQL' + ' SELECT *' Specifying parameters Database platforms can have different requirements for specifying certain types of data. For example, the format for specifying a date within an SQL statement is different for each database platform. Use the method asdbstringfor: to format data into SQL strings for each supported database. When you use this method, you ensure platform independence in the application you are creating. You also ensure that the format of data is acceptable to the database. Use the asdbstringfor: method to format each parameter of an SQL statement. For example, the following code creates and executes an SQL SELECT statement with a date that is formatted correctly for a specific database: result := db execsql: 'select * from Employees where bdate =' + (mydateobj asdbstringfor: db). Database User s Guide, P Chapter: 3. Working with databases Section: Using SQL to query databases

46 Using SQL versus using cursors When you use the execsql: or loadsql: methods, the entire result set resides in memory on the system where the application is running. Result sets containing a large number of records can cause poor performance. If an SQL SELECT statement might return a large result set, consider using cursors instead of the direct SQL methods. When you work with cursors, the result set resides on the system with the database, and the system running the application loads only one record at a time. For more information on cursors, see Working with cursors on page 47. Executing SQL with a local database Local databases use the ObjectStudio SQL evaluator, implemented in the LocalDatabase class. The evaluator supports standard SQL for SELECT, UPDATE, INSERT, and DELETE statements. The following are not supported: Table aliasing SUBSELECT statements Expressions in SELECT clauses Database User s Guide, P Chapter: 3. Working with databases Section: Using SQL to query databases

47 Working with cursors Cursors are more efficient than SQL statements because they do not load the entire result set at one time. They are also useful for maintaining a connection to a database for a positioned UPDATE. The result set stays on the DBMS and allows ObjectStudio to work with one record at a time. When you update a field for the current row of a cursor, the data in the database is also updated. In this way, ObjectStudio maintains consistency between the data on the application system and the data in the database. Data format returned Cursors usually return data in dictionaries where each key is a column name and each value is the column data for that column. Cursor messages Cursors have the same field type and format information as Tables, and cursors and tables respond to many of the same messages. Database User s Guide, P Chapter: 3. Working with databases Section: Working with cursors

48 Methods for cursor support ObjectStudio provides the following methods to support cursors: asinternaltable. Converts a cursor into an internal table. This message creates an instance of class Table and fetches all of the data from the cursor into the rows of the new table. close. Closes a cursor and releases the system resources the cursor was using. copy. Creates a copy of a record in a result set so you can save that record. For example: myrecord := cursor next copy. next. Returns the next record in the result set. opencursorsql: astring forupdateof: anarray. Creates a nonscrollable cursor that returns an instance of class Cursor. The astring parameter is an SQL string, and anarray is an array of field names if the SQL statement is an UPDATE statement. Otherwise, it is nil. For more information on SQL strings, see Creating strings containing SQL code on page 45. If the method fails, it returns an instance of Message, which contains an error message. openscrollablecursorsql: astring forupdateof: anarray. Identical to method opencursorsql:forupdateof: except that it creates a scrollable cursor. You must create a scrollable cursor if you are working with tabular list boxes or reports with header totals. position. Returns an integer representing the current position in the result set. previous. Returns the previous record in the result set. This method is for scrollable cursors only. setpositionto: aninteger. Sets the position of the cursor to a specific record location in the result set specified by aninteger and resets the value of the record instance variable. size. Returns an integer representing the number of records in the result set. This method is for scrollable cursors only. Database User s Guide, P Chapter: 3. Working with databases Section: Working with cursors

49 Types of cursors ObjectStudio supports two types of cursors: Nonscrollable cursors. Can move only forward in a result set. They can never move backward over a result set. Nonscrollable cursors also are called normal or forward-fetching cursors. Scrollable cursors. Can move forward or backward in a result set. They allow you to position the cursor at any record in the result set. Note that scrollable cursors require more system resources than nonscrollable cursors. In most cases, scrollable cursors are supported by means of their native database implementation. When the support is not native, using scrollable cursors can be far less efficient than using nonscrollable cursors. When you create a cursor, ObjectStudio creates an instance of class Cursor and allocates an instance variable record. The record variable is an instance of class Dictionary, which holds the current record in the result set. Using cursors with ODBC To allow the user to update ODBC cursors, the database driver must conform with ODBC SQL core grammar and API Level 1 (positioned UPDATE and DELETE). The database driver must also support at least two concurrently opened statements per connection. (For example, the Microsoft SQL Server driver supports only one open statement per connection and does not support positioned UPDATE and DELETE.) For more information on using cursors with ODBC, see Cursors and scrollable cursors on page 84. Using cursors with SQL Server SQL Server supports updateable cursors only for single table queries against tables that have a timestamp column and a unique index. Database User s Guide, P Chapter: 3. Working with databases Section: Working with cursors

50 Selecting multiple tables to create a cursor If you select multiple tables to create a cursor: in the result set, any column name that is shared by two or more tables will be prefixed by the name of its respective table. For example, consider tables Customer and User. Table Customer contains columns Name and ID, and table User contains columns Name and Address. You select both tables Customer and User, and in the result set: Column Name from table Customer will be referred to as Customer.Name. Column ID from table Customer will be referred to as ID. Column Name from table User will be referred to as User.Name. Column Address from table User will be referred to as Address. If you attempt to access a shared column (such as Name) without using its qualified name (such as User.Name), you will receive the following error: Column name ambiguously defined. However, non-shared column names (such as ID) will not have appended table names. If you attempt to access a non-shared column name (such as ID) using a qualified column name (such as User.ID), you will receive nil. For more detailed information, refer to the online method reference. Database User s Guide, P Chapter: 3. Working with databases Section: Working with cursors

51 Working with tables Use Table objects when you need to fetch information about field names or field types before you can perform a query. This can happen if the table has variable data, or if you have an application like the Database Notebook that looks up table structures before displaying them. Subclasses of the Database class support the following methods for working with tables: add: anarray. Inserts a record into a table. The parameter anarray is an array that contains one element for each field. The order and type of parameters in the array must match those in the table exactly. dbtables. Returns an instance of class Dictionary of all of the tables in a database. The keys represent the names of tables. The values are the database tables. Performing this method can be time-consuming. dbtablesat: atable. Returns a table. The parameter atable is an instance of class Symbol that is the name of the database table. Releasing data locks with the commit method. The dbtables and dbtablesat: methods can place locks on data. After performing one of these methods, you may want to perform the commit method to release those locks. For more information on the commit method, see Performing transactions on page 42. Database User s Guide, P Chapter: 3. Working with databases Section: Working with tables

52 Linking to cursors and tables You can create a link to a table or a cursor, either graphically, using the Designer, or programmatically, using the MVC link interface. To learn more about using the Designer to create links and about MVC, refer to ObjectStudio User Interface Guide, P Types of links ObjectStudio supports the following link types. To understand them, consider the example of linking a form item to a table. Normal. If you create a normal link, the contents of the form item change in response to a change in the table. Update. If you create an update link, the contents of the table change in response to a change in the form item. Two objects can have a normal link and an update link between them, so that updates in either object affect the other object. This section describes how to use the MVC link interface to set up links programmatically. Database User s Guide, P Chapter: 3. Working with databases Section: Linking to cursors and tables

53 Creating a normal link If you want an object (for example, a form item) to be notified whenever a table or cursor changes, add the object as a dependent of the table or cursor. When an object changes, ObjectStudio sends the changed message to all of the object s dependents. To set up an object to receive changed messages from a table or cursor object: 1. Add the object as a dependent of the table or cursor object by sending one of the following messages: objlinkedto adddependent: self. objlinkedto adddependent: self field: #fieldname. In the second message, the object is notified only when the specified field changes. 2. Implement the following method, which is called every time the linked-to object changes: update: objlinkedto with: field with: position with: type The following table describes the parameters in the previous example: Parameter objlinkedto field position type Description The object that is changed. The field that is changed or the symbol #All. The current row position of objlinkedto. The type of change that occurred, as indicated by one of the following symbols: #Add A row was added at this position. #All Assume that the whole table may have changed. #Position The position has changed. #Remove The old row at this position has been removed. #Value The value for this field or row has changed. 3. Start access to the object linked to by sending the following message: objlinkedto startaccessupdatedependent: self field: fieldname. This initializes the object for access, if needed, and sends your object the first update:with:with:with: message, as described in step 2, with the field you pass in and a type of #All. Database User s Guide, P Chapter: 3. Working with databases Section: Linking to cursors and tables

54 Removing a dependency To remove an object from the dependency list of another object, send the following message: objlinkedto removedependent: self. Stopping access To stop access, send the following message: objlinkedto stopaccess. Creating an update link This section shows how to add an update link so that when an object changes, a dependent table or cursor changes accordingly. To add a table or cursor as a dependent of another object: 1. Add the table or cursor as a dependent of the object by sending one of the following messages: myobject adddependent: taborcursobj. myobject adddependent: taborcursobj field: #fieldname. In the second message, the table or cursor is notified only when the specified field changes. 2. When myobject changes, it should send the changed message to itself. The changed method is implemented in class Object, so all objects inherit it. Its interface is: changed: position type: type The following table describes the parameters in the previous example: Parameter position type Description The new position if type is #Position. If type is #Value, the position at which the value is changed (the current position). It is either #Position or #Value. If it is #Value, the following message is sent to the object: valueatfield: fieldname You must implement the changed method to provide the new value to the dependent object. Removing a dependency To remove an object from the dependency list of another object, send the following message: myobject removedependent: taborcursobj. Database User s Guide, P Chapter: 3. Working with databases Section: Linking to cursors and tables

55 Enhancing performance It is important to use techniques that enhance performance when you work with databases and ObjectStudio. You should: Handling errors Restrict the tables that are loaded into memory when you access a database by performing the visibletablesat:put: method. Use cursors to work with one record at a time instead of executing an SQL statement. When you execute an SQL statement, you work with an entire result set. For more information, see Using SQL versus using cursors on page 46. When an error occurs, nearly all ObjectStudio database methods return instances of class Message, which contain the error message. The exceptions are the execsql:onerror: and loadsql:onerror: methods. For more information on these methods, see Using SQL to query databases on page 43. Each database uses a set of numeric return codes specific to that database. All but two of these codes are passed directly through ObjectStudio without translation. For all database types, ObjectStudio intercepts and translates the two numeric codes described in the following table: Code Description 100 End-of-fetch condition for cursors The data load limit has been exceeded while processing either an execsql: or a loadsql: message. You can retrieve the last error message processed by a database or cursor instance at any time by performing the message method. This method returns a Message object containing the text of the last error that occurred. Database User s Guide, P Chapter: 3. Working with databases Section: Enhancing performance

56 Packaging applications This section describes techniques to use when you are packaging an application with database support for delivery to users. Including login controllers in the image When you create an image for an application containing database support, include login controllers for any databases that the application can use. The logonview method returns the login controller for a specific database. To suppress login controllers in a program-generated application, create a secondary class file (or class extension, if using the Repository) for the appropriate database class, and add the following class method: haslogonview ^ false. Delaying a database login This section describes a technique that delays logging in to a database. Default login By default, when you create an image for an application that works with a database, ObjectStudio adds the database to the global variable, StopStartAnnouncementList. When the user starts the image, ObjectStudio tries to log the user in to the database. If the database is still open when the user closes ObjectStudio, StartStopAnnouncementList closes the database. Overriding default login behavior You may want to control when the user logs in to a database. One reason to use non-default login behavior is to save system resources maintaining an idle connection to a database can use system resources. To stop the default login behavior, remove the subclass of Database from the StartStopAnnouncementList global variable and use one of the login techniques described in Connecting to a DBMS on page 37. For more information about how StopStartAnnouncementList is used in ObjectStudio, refer to the ObjectStudio User s Guide, P Database User s Guide, P Chapter: 3. Working with databases Section: Packaging applications

57 4. ODBC Introduction This chapter describes how the support for ODBC differs from the standard ObjectStudio database support. ODBC database wrapper compatibility While the ODBC wrapper can theoretically be used to connect to any ODBCcompatible database, the ODBC wrapper is specifically tested, with every release of ObjectStudio 8.x, against only the following four database types: IBM DB2 database Oracle database Microsoft SQL Server database Sybase database In order to access the Microsoft SQL Server database from an ObjectStudio application, you have only the option of using the ODBC wrapper. However, with the DB2, Oracle, and Sybase databases, you have the option of using either the ODBC wrapper or one of the supplied database-specific, native wrappers. The advantage of using one of the native wrappers is that it will offer potentially improved performance over the ODBC wrapper. This is because a native wrapper communicates directly with the database library, without the intermediary of the ODBC library. What s new in the ObjectStudio 8.x ODBC database wrapper In ObjectStudio 8.x, Cincom has rewritten the ODBC wrapper to eliminate the C code and the ObjectStudio ODBC DLLs. Usage should remain the same as that in Classic ObjectStudio. Here are the highlights of the new ODBC database wrapper: It is compatible with the ODBC wrappers in Classic ObjectStudio. Because the C code and the related DLL have been removed, you can easily add new features. Improved LOB support. Improved host variable support. Improved support of stored procedures with INPUT parameters, OUTPUT parameters, and return values. Database User s Guide, P Chapter: 4. ODBC Section: Introduction

58 Database logon authentication Domain authentication and database logon When domain authentication is used, the database user name and password do not need to be provided to the ODBC wrapper. In this case, it is unnecessary to use either the ODBC database logon dialog box or the ODBC database logon method. Database authentication and the new database logon dialog box When database authentication is used, the user name and password must be provided to the ODBC wrapper and through it, the database. In earlier ObjectStudio releases, if no user name and password were provided, the ODBC wrapper depended on the vendor s database driver to take responsibility for providing a logon dialog box. Some database drivers would provide this dialog box, but others would not; logon proved impossible when a driver did not provide this dialog box. Currently, the ODBC wrapper takes responsibility for providing this logon dialog box, ensuring that it is always available when needed. Database authentication and the new database logon method For database authentication, an optional ObjectStudio method provides the user name and password to the ODBC wrapper. This enables users to skip the ODBC logon dialog box, seamlessly logging on to their database. See below: ODBCDatabase>>logOnServer:user:password: Database User s Guide, P Chapter: 4. ODBC Section: Database logon authentication

59 ODBC elements To understand how to work with ODBC from ObjectStudio, you must know about three important ODBC elements: Environment. The environment establishes the link between the application (ObjectStudio) and the ODBC run-time system. An application usually has one environment link to the ODBC system. Connection. An application uses one or more connections. Each connection is a communication channel to a DBMS and references a particular driver and data source combination. The connection makes it transparent to the application whether data access is local or remote. The database driver in use determines whether multiple connections to the same data source are allowed at one time. Statement. A statement holds all of the information required to execute an SQL command and to process its results. A statement exists in the context of a connection. A connection can have multiple active statements at one time. For SQL SELECT commands, a statement behaves like an embedded SQL cursor. It provides you with a movable pointer into a derived table, by which the application can retrieve, update, and delete rows. For more information on ODBC cursors, see Cursors and scrollable cursors on page 84. Determining maximum active statements per connection. The database driver determines the maximum number of active statements per connection. Minimum active statements for UPDATE and DELETE. A minimum of two active statements is required to perform positioned UPDATE and DELETE SQL statements. Database User s Guide, P Chapter: 4. ODBC Section: ODBC elements

60 ODBC conformance levels ODBC drivers can be classified according to their ODBC conformance levels. A conformance level refers to a general set of capabilities an ODBC database driver supports. Microsoft defines two areas that have levels of ODBC conformance: Application Programming Interface (API) SQL grammar and corresponding ODBC SQL data types The conformance level of the API can differ from the conformance level of the SQL grammar for a particular driver. API conformance levels A database driver conforms to an API level if it supports all of the functions defined for that level. ODBC defines three API conformance levels: Core level. The ODBC core-conformance level is identical to the SAG CLI (SQL Access Group Command Language Interpreter) specification. Therefore, a core-level-compliant driver is automatically a SAG CLIcompliant driver. The classes SAGSqlConnection and SAGSqlStatement implement the core-level API functionality. Level 1. ODBC Conformance Level 1 implements extensions specific to Microsoft, providing the developer with information about the driver, data source, and DBMS in use for a particular connection. It supports functions providing basic data-catalog access for database objects such as tables, views, columns, and synonyms. It also adds more convenient ways to connect to a data source. Level 1 extensions are proprietary extensions of Microsoft and are not standardized. Level 2. ODBC Conformance Level 2 adds functions providing extended data catalog access for key data (primary, foreign, and index keys), data describing stored procedures and their parameters, and user access rights. Also, block data fetching and scrollable cursors are supported. Level 2 extensions are proprietary extensions of Microsoft and are not standardized. Database User s Guide, P Chapter: 4. ODBC Section: ODBC conformance levels

61 ODBC SQL grammar conformance levels ODBC defines the following SQL grammar conformance levels: Minimum SQL grammar. Minimum functionality includes the CHAR data type only, and the basic Data Definition Language (DDL) and Data Manipulation Language (DML) SQL statements. Core and extended SQL grammar. The core and extended SQL grammar conformance levels add more of the following: - DDL statements - Data types - DML statements (such as outer JOIN) Most important are the positioned UPDATE and DELETE statements for cursors. A useful database driver should support at least the core SQL grammar. Most drivers do. ObjectStudio supports all ODBC conformance levels ObjectStudio ODBC support implements the entire Microsoft ODBC Version 2.5 API. Therefore, it conforms to all ODBC API and SQL grammar conformance levels. ObjectStudio ODBCDatabase and driver conformance-level dependencies The ODBCDatabase class is a layer implemented on top of the ODBC class library and generally works with every ODBC driver. Depending on the driver, the ODBCDatabase class can make use of concepts such as true scrollable cursors, Binary Large Objects (BLOBs), stored procedures, and parameterized SQL statements. If you are processing large volumes of data, choose an ODBC database driver that is at least API Level 1 and core SQL grammar compliant. Otherwise, portions of the ObjectStudio external database support will not be available. For example, the data manager will show up in read-only mode and cursors cannot be updated. Database User s Guide, P Chapter: 4. ODBC Section: ODBC conformance levels

62 Low-level ODBC support Low-level ODBC support allows you to program directly to the industry standard CLI for SQL data access, as defined by the SQL Access Group (SAG) and X/Open. (The Microsoft ODBC core set of API calls is a full implementation of the SAG CLI.) Low-level support has the following features: Binds you to the Microsoft Windows operating system. (The SAG CLI is widely accepted and is the emerging API standard.) Handles two-phase commit-related issues (not supported in Microsoft s ODBC implementation) in distributed environments. Allows you to specialize code (for example, you can prepare a statement), and offers additional features not available with high-level support (for example, asynchronous execution of statements). Database User s Guide, P Chapter: 4. ODBC Section: Low-level ODBC support

63 Additional ODBC classes ObjectStudio support for ODBC provides the following classes in addition to those described under How ObjectStudio supports databases on page 11: Class SAGSqlConnection and its subclass ODBCConnection. These classes implement SAG CLI or ODBC compliant connections. Class SAGSqlConnection uses the class variable henv to implement the link to the ODBC system. ObjectStudio establishes the link at load time of the class library and releases it at normal program-termination time. Class SAGSqlStatement and its subclass ODBCStatement. These classes implement SAG CLI or ODBC compliant statements. Because ODBC is an extension to the SAG CLI, the basis of the implementation is made up of the four classes shown in the following figure. Most of the methods found in the classes map almost one-to-one to the SAG CLI API function calls. SAGSqlConnection Has Active Statements SAGSqlStatement Has lasterror Input Parameters ResultSetColumns Has lasterror SAGSqlError SAGSqlColumnDescription The ODBCConnection and ODBCStatement classes implement the Microsoftspecific extensions of the SAG CLI. Therefore, they are subclasses of SAGSqlConnection and SAGSqlStatement as shown here: SAGSqlConnection Has Active Statements SAGSqlStatement ODBCConnection ODBCStatement Database User s Guide, P Chapter: 4. ODBC Section: Additional ODBC classes

64 Typical session The following steps illustrate a typical ODBC support session with ObjectStudio: 1. Allocate the environment by initializing the ODBC interface and allocate the environment handle. 2. Allocate a connection handle. 3. Connect to a database. 4. Allocate statements. 5. Process statements. 6. Receive results. 7. Free statements. 8. Disconnect from the database. The environment handle is freed only when you exit ObjectStudio. Database User s Guide, P Chapter: 4. ODBC Section: Typical session

65 Example. The following example shows how the basic elements are implemented using ObjectStudio s ODBC support: "Establish a connection to a data source." c := ODBCConnection connect: #sample uid: #admin pwd: #school. "Open a statement within the scope of the connection c." s := c addstatement. "Prepare the statement." s prepare: 'select * from Student'. "Assign a cursor name to the statement (optional)." s setcursorname: #StudentCursor. "Send the statement to the data source for execution." s execute. "Fetch one record of the result set at a time and show them in the System Transcript window." [s fetch == 0] whiletrue: [ s recordasarray out. ]. "Close the statement (optional, because the following command implicitly does it)." s close. "Delete the statement from the collection of known statements for the connection." c removestatement: s. "Disconnect from the data source." c disconnect. Database User s Guide, P Chapter: 4. ODBC Section: Typical session

66 Data type mapping ODBC support maps ODBC data types to ObjectStudio classes and vice versa. The following table shows these mappings: ODBC type Type # Smalltalk class SQL_CHAR 1 Symbol SQL_NUMERIC 2 Decimal SQL_DECIMAL 3 Decimal SQL_INTEGER 4 LongInteger SQL_SMALLINT 5 SmallInteger SQL_FLOAT 6 Float SQL_REAL 7 Float SQL_DOUBLE 8 Float SQL_DATE 9 Date SQL_TIME 10 Time SQL_TIMESTAMP 11 Timestamp SQL_VARCHAR 12 Symbol SQL_BIT 7 Boolean SQL_BIGINT 5 LongInteger SQL_TINYINT 6 SmallInteger SQL_LONGVARCHAR 1 ODBCBlob SQL_BINARY 2 ByteArray SQL_VARBINARY 3 ByteArray SQL_LONGVARBINARY 4 ODBCBlob Database User s Guide, P Chapter: 4. ODBC Section: Data type mapping

67 System catalog access Methods in class ODBCTable can retrieve primary key, unique key, foreign key, and index key information from the system catalog. These methods return values only for drivers conforming to ODBC API Level 2. If the drivers do not conform to Level 2, empty IdentitySets are returned. The following table lists the retrieval instance methods in class ODBCTable: Method Returns primarykey The primary key (a specially marked unique key) uniquekeys All unique keys foreignkeys All foreign keys indexkeys All index keys Each method in the previous table returns an IdentitySet of the key objects defined for the Table object. The following key object class hierarchy exists: Class ExternalTableKey ExternalTableIndexKey ExternalTableUniqueKey ExternalTableForeignKey Description Abstract class describing keys Index key Unique keys Foreign key Because the primary key of a table is a specially marked unique key, no separate class exists that describes primary keys. Instead, class ExternalTableUniqueKey has an instance variable indicating whether or not the unique key is also the primary key of the table. Example of using stored procedures This section provides an example of how to use a stored procedure with ODBC and SQL Server. 1. Create a stored procedure for SQL Server (authors and titles are existing database tables in the database). For example: create procedure showall as select * from authors select * from titles Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

68 2. Retrieve all records returned by a call to the stored procedure showall. For example: "Establish a connection to a data source." conn := ODBCConnection connect: #'pubs' uid: #sa #xy. "Open a statement within the scope of the connection." s := conn addstatement: '{call showall}'. pwd: "Set initial value to true for the flag identifying whether there are more result sets." moreresultsets := true. "Get result sets one at a time; loop through the records in the result set and display each record in the System Transcript window." [moreresultsets] whiletrue: [ "Fetch the first record in a result set." rc := s fetch. [rc == 0] whiletrue: [ " display a record in the System Transcript window " s recordasarray out. " fetch the next record " rc := s fetch. ]. "Check if there is another result set available." moreresultsets := s moreresults == 0. ]. "Close a statement." s close. "Disconnect from data source." conn disconnect. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

69 Using stored procedures with an ODBCDatabase instance See the following sample Workspace code, which shows you how to use stored procedures with an ODBCDatabase instance: db res vars sqlstring "Logon to the database server." ODBCDatabase logonserver: #odbcdsn user: #user password: #pwd. "Get access to the database needed." db := ODBCDatabase accessname: #odbcdsn. "Create a test table." db execsql: 'CREATE TABLE TestTable (cid int primary key, cname varchar(100))'. "Insert test data into the test table." sqlstring := 'INSERT INTO TestTable VALUES (?,?)'. 11 to: 20 do: [ :i vars vars := Array with: i with: ('test' + i). db execsql: sqlstring vars: vars. ]. "Create a simple stored procedure." res := db execsql: 'CREATE PROCEDURE testprocedure1 AS SELECT * FROM TestTable'. sqlstring := '{call testprocedure1}'. res := db execproc: sqlstring. "Create a stored procedure with parameters." res := db execsql: 'CREATE PROCEDURE VARCHAR(20) AS SELECT * FROM TestTable WHERE cname "Invoke the stored procedure." sqlstring := '{call testprocedure2(?)}'. vars := {'test12' }. res := db execproc: sqlstring params: vars. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

70 Parametric SQL statements Introduction to parametric SQL statements ODBC support includes the ability to use parametric SQL statements. Parametric statements improve performance, depending on whether the driver compiles the access plan at preparation time. This section contains the following Workspace code samples for parametric SQL statements: Using a parameterized INSERT statement on page 73 Using a parameterized SELECT statement on page 74 Using host variables at the database level on page 76 Calling stored procedures with INPUT and OUTPUT parameters, at the connection level on page 77 Calling stored procedures with INPUT and OUTPUT parameters, at the database level on page 79 Taking advantage of existing methods, to avoid the trouble of manually managing the binding parameters using the ODBCConnection instance on page 80 Calling stored procedures with INPUT and OUTPUT parameters, and with more than one result set, at the connection level on page 81 Calling stored procedures with INPUT and OUTPUT parameters, and with more than one result set, at the database level on page 83 Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

71 Parameter descriptors Formal parameters are represented by the question mark (?) and are substituted at run time using the actual parameter values. Define a parameter descriptor for each parameter. The descriptor sets the ODBC data type, scale and precision, and holds the actual value of the parameter at run time. To describe a parameter: p := SAGSqlColumnDescriptor type: atype precision: aprec scale: ascale nullable: abool. where atype must be one of the ODBC data-type integer values described in Data type mapping on page 66. Some drivers determine the type of parameters and provide those values using the API (for example, Watcom SQL 3.1). In this case, the following method asks the driver to return the parameter descriptor: p := stmt describeparam: 1. Checking to see if the driver supports this function. The program should always determine whether the driver supports this function (see the examples later in this section) before sending this method. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

72 Automatic data-type conversion of parameter values Although the data type specified in the class method type:precision:scale:nullable must match the data type of the table column exactly, ObjectStudio converts actual parameter values at execution time. The following table describes the data types and the conversion that ObjectStudio performs: Data type SQL_TIMESTAMP SQL_DATE SQL_TIME SQL_CHAR SQL_VARCHAR SQL_DOUBLE SQL_REAL SQL_FLOAT SQL_BIT SQL_INTEGER SQL_BIGINT SQL_SMALLINT Action Accepts Timestamp, Date, or Time objects. If a Date object is passed, the time component is set to 12:00. If a Time object is passed, the Date component is set to Accepts Date and Timestamp objects. If a Timestamp object is passed, the time component is ignored. Accepts Time and Timestamp objects. If a Timestamp object is passed, the date component is ignored. Accepts Strings, Symbols, and any type of object responding to the asstring method. Accepts any object responding to the asfloat method. Sets the parameter to false unless it is the true object. Accepts any object responding to the asinteger method. Accepts any object responding to the asinteger method that results in a SmallInteger object after conversion. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

73 Using a parameterized INSERT statement The following sample Workspace code shows how to use a parameterized INSERT statement: "Establish a connection to a data source." conn := ODBCConnection connect: #ODBCTest uid: #OSTUDIO pwd: #OSTUDIO. "Open a statement within the scope of the connection." (stmt := conn addstatement) notnil iftrue: [ "Prepare the statement." stmt prepare: 'insert into ss2 (f1) values (?)'. "Check whether describe parameter function is supported by a driver." (conn functionsupported: #SQL_API_SQLDESCRIBEPARAM) iftrue: [ "Call describe parameter function." p1 := stmt describeparam: 1. ] iffalse: [ ]. "Describe parameter explicitly." p1 := SAGSqlColumnDescriptor type: 1 precision: 30 scale: 0 nullable: true. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

74 "Set parameter description." stmt setparamdescr: 1 to: p1. 1 to: 20 do: [ :idx "Set parameter value." p1 value: 'Record' ++ idx. ]. "Send the statement to the data source for execution." stmt execute. "Remove statement from the collection of known statements for a connection." conn removestatement: stmt. "Commit a connection." conn commit. ]. "Disconnect from the data source." conn disconnect. Using a parameterized SELECT statement The following sample Workspace code shows how to use a parameterized SELECT statement: "Assign parameter value with wildcard." p1val := 'S%'. "Establish connection to a data source." conn := ODBCConnection connect: ''. "Open a statement within the scope of the connection." stmt := conn addstatement. "Prepare the statement." stmt prepare: 'select * from Student where Surname like?'. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

75 "Describe parameter to a statement explicitly." p1 := SAGSqlColumnDescriptor type: 1 precision: 30 scale: 0 nullable: true. "Set parameter description." stmt setparamdescr: 1 to: p1. "Bring up a pop-up menu to enter/edit the parameter value; loop while value is being changed." [(rc := p1val editin: nil) ~~ p1val] whiletrue: [ "Get the user-entered value." p1val := rc. "Set the parameter value." p1 value: p1val. "Send the statement to the data source for execution." stmt execute. "Fetch a statement in a loop." [stmt fetch == 0] whiletrue: [ "Display record in the System Transcript." stmt recordasarray out. ]. ]. "Close a statement." stmt close. "Remove a statement from the collection of known statements for a connection." conn removestatement: stmt. "Disconnect from the data source." conn disconnect. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

76 Using host variables at the database level The following sample Workspace code shows how to use host variables at the database level: db res sqlobj vars sqlstring "Logon to the database server." ODBCDatabase logonserver: #odbcdsn user: #user password: #pwd. "Get access to the database needed." db := ODBCDatabase accessname: #odbcdsn. "Create a test table." res := db execsql: 'CREATE TABLE TestTable (cid int primary key, cname varchar(100))'. "Insert test data into the test table using host variables." sqlstring := 'INSERT INTO TestTable VALUES (?,?)'. 1 to: 10 do: [ :i vars vars := Array with: i with: ('test' + i). db execsql: sqlstring vars: vars. ]. "Select test data using host variables." sqlstring := 'SELECT * FROM TestTable WHERE cid=?'. vars := Array with: 5. res := db execsql: sqlstring vars: vars. "Update test data using host variables." sqlstring := 'UPDATE TestTable SET cname=? WHERE cid=?'. vars := Array with: 'test55' with: 5. res := db execsql: sqlstring vars: vars. "Make sure the test data were indeed updated." sqlstring := 'SELECT * FROM TestTable WHERE cid=?'. vars := Array with: 5. res := db execsql: sqlstring vars: vars. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

77 Calling stored procedures with INPUT and OUTPUT parameters, at the connection level The following sample Workspace code shows how to call stored procedures with INPUT and OUTPUT parameters, at the connection level: "Establish a connection to a data source." conn := ODBCConnection connect: #ODBCTest uid: #OSTUDIO pwd: #OSTUDIO. "Open a statement within the scope of the connection." stmt := conn addstatement. "Create a test stored procedure with INPUT parameters, OUTPUT parameters, and a return value." stmt prepare: 'create procedure varchar(10) output as = ''teststring'' select * from TestTable where cid=@x stmt execute. "Test the stored procedure." stmt prepare: '{? = call demo1(?,?,?)}'. "Check whether the describe parameter function is supported by a driver." (conn functionsupported: #SQL_API_SQLDESCRIBEPARAM) iftrue: [ "Call describe parameter function." p1 := stmt describeparam: 1. p2 := stmt describeparam: 2. p3 := stmt describeparam: 3. p4 := stmt describeparam: 4. ]. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

78 "Set parameter description." p1 value: 1. p2 value: 10. p3 value: 11. p4 value: 'test'. stmt setparamdescr: 1 to: p1 output: true. stmt setparamdescr: 2 to: p2. stmt setparamdescr: 3 to: p3. stmt setparamdescr: 4 to: p4 output: true. stmt execute. "Fetch the result." rc := stmt fetch. [ rc == 0 ] whiletrue: [ stmt recordasarray out. rc := stmt fetch. ]. "Make sure there are no more result sets." rc := stmt moreresults. "Verify the output parameters." rc == 100 iftrue: [ p1 value out. p4 value out. ]. stmt close. "Remove the statement from the collection of known statements for a connection." conn removestatement: stmt. "Disconnect from the data source." conn disconnect. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

79 Calling stored procedures with INPUT and OUTPUT parameters, at the database level The following sample Workspace code shows how to call stored procedures with INPUT and OUTPUT parameters, at the database level: "Logon to the database server." ODBCDatabase logonserver: #ODBCTest user: #OSTUDIO password: #OSTUDIO. "Get access to the database needed." db := ODBCDatabase accessname: #ODBCTest. "Drop the stored procedure if it exists." res := db execsql: 'DROP PROCEDURE demo1'. "Create the test stored procedure." db execsql: 'create procedure varchar(10) output as = ''teststring'' select * from TestTable where cid=@x "Create the binding parameter array with initial values." vars := { 'test'}. "Create the binding parameter option array indicating whether the parameters are for INPUT or OUTPUT." outputparamarray := {true false false true}. "Create an error block." errorblock := [ :error ^ error asmessage. ] "Execute the procedure." resulttable := db execproc: '{? = call demo1(?,?,?)}' params: vars outputparams: outputparamarray onerror: errorblock. "Verify the input and output parameter values." vars out. After running this example in ObjectStudio s Workspace, you will get a returned result table, and the binding parameter array will also be changed. The original OUTPUT parameter values will be replaced by the new returned values. However, the INPUT parameter values will remain unchanged. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

80 Taking advantage of existing methods, to avoid the trouble of manually managing the binding parameters using the ODBCConnection instance If you wish to avoid the trouble of manually managing the binding parameters using the ODBCConnection instance, you can take advantage of some existing methods. See the following sample Workspace code: "Establish a connection to a data source." conn := ODBCConnection connect: #'ylidb' uid: #sa pwd: #test. conn := ODBCConnection connect: #ODBCTest uid: #OSTUDIO pwd: #OSTUDIO. "Create the binding parameter array with initial values." vars := { 'test'}. "Create the binding parameter option array indicating whether the parameters are for INPUT or OUTPUT." outputparamarray := {true false false true}. "Create an error block." errorblock := [ :error ^ error asmessage. ]. "Execute the procedure." resulttable := conn resulttablearrayfrom: '{? = call demo1(?,?,?)}' vars: vars outputparams: outputparamarray onerror: errorblock. "Verify the input and output parameter values." vars out. Calling a stored procedure that has multiple result sets works in a similar way. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

81 Calling stored procedures with INPUT and OUTPUT parameters, and with more than one result set, at the connection level The following sample Workspace code shows how to call stored procedures with INPUT and OUTPUT parameters, and with more than one result set, at the connection level: "Establish a connection to a data source." conn := ODBCConnection connect: #ODBCTest uid: #OSTUDIO pwd: #OSTUDIO. "Open a statement within the scope of the connection." stmt := conn addstatement. "Create a test stored procedure with INPUT parameters, OUTPUT parameters, and a return value." stmt prepare: 'drop procedure demo21'. stmt execute. "Create a test stored procedure with INPUT parameters, OUTPUT parameters, and a return value." stmt prepare: 'create procedure varchar(10) output as = ''teststring'' select * from TestTable where cid=@x select * from TestTable stmt execute. "Test the stored procedure." stmt prepare: '{? = call demo21(?,?,?)}'. "Check whether describe parameter function is supported by a Driver." (conn functionsupported: #SQL_API_SQLDESCRIBEPARAM) iftrue: [ "Call describe parameter function." p1 := stmt describeparam: 1. p2 := stmt describeparam: 2. p3 := stmt describeparam: 3. p4 := stmt describeparam: 4. ]. "Set parameter description." p1 value: 1. p2 value: 10. p3 value: 11. p4 value: 'test'. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

82 stmt setparamdescr: 1 to: p1 output: true. stmt setparamdescr: 2 to: p2. stmt setparamdescr: 3 to: p3. stmt setparamdescr: 4 to: p4 output: true. stmt execute. "Fetch the result." rc := stmt fetch. [ rc == 0 ] whiletrue: [ stmt recordasarray out. rc := stmt fetch. ]. "Make sure there are no more result sets." rc := stmt moreresults. [ rc == 0 ] whiletrue: [ rc1 rc1 := stmt fetch. [ rc1 == 0 ] whiletrue: [ stmt recordasarray out. rc1 := stmt fetch. ]. rc := stmt moreresults. ]. rc == 100 iftrue: [ "Verify the output parameters." p1 value out. p4 value out. ]. stmt close. "Remove statement from the collection of known statements for a connection." conn removestatement: stmt. "Disconnect from the data source." conn disconnect. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

83 Calling stored procedures with INPUT and OUTPUT parameters, and with more than one result set, at the database level At the database level, you do not need to worry about this additional result set processing. ObjectStudio will take care of it for you. This is demonstrated by the following sample Workspace code, which shows how to call stored procedures with INPUT and OUTPUT parameters, at the database level: "Logon to the database server." ODBCDatabase logonserver: #ODBCTest user: #OSTUDIO password: #OSTUDIO. "Get access to the database needed." db := ODBCDatabase accessname: #ODBCTest. "Create the binding parameter array with initial values." vars := { 'test'}. "Create the binding parameter option array indicating whether the parameters are for INPUT or OUTPUT." outputparamarray := {true false false true}. "Create an error block." errorblock := [ :error ^ error asmessage. ]. "Execute the procedure." resulttables := db execproc: '{? = call demo21(?,?,?)}' params: vars outputparams: outputparamarray onerror: errorblock. "Verify the input and output parameter values." vars out. After running the code above, you can see that resulttables is an array of two resulting tables. Also, vars contains both of the unchanged INPUT parameters, as well as the OUTPUT parameters that have new values. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

84 Cursors and scrollable cursors Introduction to cursors and scrollable cursors For SQL SELECT commands, the statement replaces the concept of an embedded SQL cursor. Each statement used for an SQL SELECT command has a name that the application can use to reference it. Each name within a given connection is unique. Before executing the SELECT statement, an application can specify a name to keep the system from generating a name. An application can retrieve any name the system has generated. (This is required for positioned UPDATE and DELETE statements.) This section contains the following Workspace code samples: Using a cursor on page 84 Using a scrollable cursor on page 85 Using a cursor The following sample Workspace code demonstrates how to use a cursor: "Establish a connection to a data source." c := ODBCConnection connect: #ODBCTest uid: #OSTUDIO pwd: #OSTUDIO. "Open a statement within the scope of the connection c." s := c addstatement. "Prepare the statement." s prepare: 'select * from TestTable'. "Assign a cursor name to the statement (optional)." s setcursorname: #TestCursor. "Send the statement to the data source for execution." s execute. "Fetch one record of the result set at a time and show them in the System Transcript." [s fetch == 0] whiletrue: [ s recordasarray out. ]. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

85 "Close the statement (optional, because the following command implicitly does it)." s close. "Delete the statement from the collection of known statements for the connection." c removestatement: s. "Disconnect from the data source." c disconnect. Using a scrollable cursor The following sample Workspace code demonstrates how to use a scrollable cursor: "Establish a connection to a data source." c := ODBCConnection connect: #ODBCTest uid: #OSTUDIO pwd: #OSTUDIO. "Open a statement within the scope of the connection." s := c addstatement. "Set options that control the behavior of a cursor associated with the statement; set concurrency to be read only; keep the key for every row retrieved." ((ret := s setscrolloptionsconcurrency: 1 keyset: -1) == (ODBCConstants at: #SQL_SUCCESS)) iftrue: [ "Prepare a statement." s prepare: 'select * from TestTable order by cid'. "Send the statement to the data source for execution." s execute. "Position at first record." s extendedfetchnext. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

86 "Display the first record of the result set in the System Transcript window." s recordasarray out. "Absolute positioning at record 5." s extendedfetchabsolute: 5. "Display the record in the result set in the System Transcript window." s recordasarray out. "Position a cursor at a previous record (position 4)." s extendedfetchprevious. "Display the record in the System Transcript window." s recordasarray out. ] iffalse: [s lasterror out]. "Close a statement." s close. "Remove a statement from the collection of known statements for a connection." c removestatement: s. "Disconnect from the data source." c disconnect. Database User s Guide, P Chapter: 4. ODBC Section: System catalog access

87 Setting and getting connection options Introduction to setting and getting connection options You may wish to set or get connection options (attributes). There are two kinds of connection option: Options that must be set before connecting to a data source, in order for them to take effect. Options that must be set after connecting to a database. In ObjectStudio 8.x, you can set or get connection options at both the connection and database levels. This section contains the following Workspace code samples: Setting and getting connection options at the connection level on page 87 Setting and getting connection options at the database level on page 89 Setting and getting connection options at the connection level The following sample Workspace code shows how to set and get connection options at the connection level: "Start from the attributes that can be set before the connection is established." "Create a new connection without connecting." Conn := ODBCConnection new. "Set the attribute to preserve cursors." Res := Conn setoption: 1204 to: 1. "This is equivalent to the following:" Res := Conn setoptionsymbol: #SQL_PRESERVE_CURSORS to: 1. Database User s Guide, P Chapter: 4. ODBC Section: Setting and getting connection options

88 "Getting the same attribute; should get the right value back." Res := Conn getconnectoption: "This is equivalent to the following:" Res := Conn getconnectoptionsymbol: #SQL_PRESERVE_CURSORS. "Then, we test the attributes that can be set only after the connection is established." "Connect to the data source." ConnStr := 'DSN=DSName;UID=username;PWD=password;'. Conn driverconnect: ConnStr. "Retrieve the default isolation level of the connection. Should be 2, meaning READ COMMITTED." Conn txnisolation. "Set Isolation Level to 1, meaning READ UNCOMMITTED." rc := Conn txnisolation: 1. "Retrieve the default isolation level. Should be 1, meaning READ UNCOMMITTED" Conn txnisolation. "Do the same thing in a different way." Res := Conn getconnectoptionsymbol: #SQL_TXN_ISOLATION. "Set Isolation Level to 4, meaning REPEATABLE_READ." rc := Conn txnisolation: 4. "Retrieve the isolation level to confirm." Conn txnisolation. "Disconnect the connection." Conn disconnect. Database User s Guide, P Chapter: 4. ODBC Section: Setting and getting connection options

89 Setting and getting connection options at the database level The following sample Workspace code shows how to set and get connection options at the database level: "Start from an attribute that must be set before the connection is established." "Get a database instance without connecting to a data source." DB := ODBCDatabase accessnamewithoutconnect: #DSName. "Set the option using the defined ODBC constant." DB setconnectoptionsymbol: #SQL_PRESERVE_CURSORS to: 1. "Set the option using the magic number. This has the same effect as the previous line." DB setconnectoption: 1204 to: 1. "At this time, getting the option again will give you the right value." DB getconnectoptionsymbol: #SQL_PRESERVE_CURSORS. "The same using a magic number instead of defined macros." DB getconnectoption: "Connect to a data source." DB connectuser: #username password: #password. "Retrieve the default isolation level of the active connection. Should be 2, meaning READ COMMITTED." DB getconnectoptionsymbol: #SQL_TXN_ISOLATION. Database User s Guide, P Chapter: 4. ODBC Section: Setting and getting connection options

90 "Set the connections' Isolation Level to 1, READ UNCOMMITTED." DB setconnectoptionsymbol: #SQL_TXN_ISOLATION to: 1. "Retrieve the isolation level. Should be 1, meaning READ UNCOMMITTED." DB getconnectoptionsymbol: #SQL_TXN_ISOLATION. "Set the connection's isolation Level to 4, REPEATABLE_READ." DB setconnectoptionsymbol: #SQL_TXN_ISOLATION to: 4. "Retrieve the default isolation level; should be 4, REPEATABLE_READ." DB getconnectoptionsymbol: #SQL_TXN_ISOLATION.... Note that if more connections are needed for the database operations, the new connections will be created automatically, and they will have the same connection options set as the active connection. Database User s Guide, P Chapter: 4. ODBC Section: Setting and getting connection options

91 Using Multiple Active Result Sets (MARS) support in SQL Server's SQL Native Client The old SQL Server ODBC driver disallows more than one active statement on a single connection. However, the SQL Native Client accompanying SQL Server 2005 and later allows you to circumvent this issue. This SQL Native Client supports MARS (Multiple Active Result Sets) if you set the connection attribute SQL_COPT_SS_MARS_ENABLED to the following value: SQL_MARS_ENABLED_YES MARS is a before attribute of the connection. That is, you must set it before the connection to the data source is established. For the ObjectStudio 8.x ODBC database wrapper, you may take advantage of MARS support when you are using the SQL Native Client to connect to a SQL Server database. However, when you are using the SQL Native Client to connect to any other database, or when you are using the old SQL Server ODBC driver to connect to a SQL Server database, attempting to enable MARS support will have no effect but will cause no errors. Code samples The code samples below demonstrate how to use MARS support at both the connection and database levels. Note that these samples are merely code fragments and are not intended to serve as complete examples. Using the SQL Native Client with MARS support, at the connection level See the samples below: "Create a new connection without connecting." Conn := ODBCConnection new. "Enable MARS support." Res := Conn enablemars. "Connect to the data source." ConnStr := 'DSN=SQLServerDSN1;UID=username;PWD=password;'. Conn driverconnect: ConnStr. Database User s Guide, P Chapter: 4. ODBC Section: Using Multiple Active Result Sets (MARS) support in SQL Server's SQL Native Client

92 "Verify the value of the attribute, which should be 1." Res := Conn getconnectoptionsymbol: #SQL_COPT_SS_MARS_ENABLED. "Open a statement within the scope of the connection." stmt := Conn addstatement. "Create a test table." stmt prepare: 'create table testactivestatements1 (cid int, cname varchar(100))'. stmt execute. "Insert some data." stmt prepare: 'insert into testactivestatements1 values (11, ''test11'')'. stmt execute. stmt prepare: 'insert into testactivestatements1 values (12, ''test12'')'. stmt execute. "Create another test table." stmt prepare: 'create table testactivestatements2 (cid int, cname varchar(100))'. stmt execute. "Insert some data." stmt prepare: 'insert into testactivestatements2 values (21, ''test21'')'. stmt execute. stmt prepare: 'insert into testactivestatements2 values (22, ''test22'')'. stmt execute. "Remove the statement from the connection." Conn removestatement: stmt. "Open a statement within the scope of the connection." stmt1 := Conn addstatement. Database User s Guide, P Chapter: 4. ODBC Section: Using Multiple Active Result Sets (MARS) support in SQL Server's SQL Native Client

93 "Retrieve the first record from the first table." stmt1 prepare: 'select * from testactivestatements1'. stmt1 execute. stmt1 fetch. stmt1 recordasarray out. "Before exhausting the records from the first statement, open another statement on the same connection." stmt2 := Conn addstatement. "Retrieve the first record from the second table. It should work properly." stmt2 prepare: 'select * from testactivestatements2'. stmt2 execute. stmt2 fetch. stmt2 recordasarray out.... Using the SQL Native Client with MARS support, at the database level See the samples below: "Enable MARS support." ODBCDatabase enablemars. "Verify the value of marssupport." ODBCDatabase marssupport. "Log on to the database server." ODBCDatabase logonserver: #SQLServerDSN1 user: #username password: #password. "Get access to the needed database." DB := ODBCDatabase accessname: #SQLServerDSN1.... Database User s Guide, P Chapter: 4. ODBC Section: Using Multiple Active Result Sets (MARS) support in SQL Server's SQL Native Client

94 Working with Binary Large Objects (BLOBs) Enabling ODBC Support BLOBs are supported only in ODBC Extension Level 1 or 2. To enable ODBCBlob object support for all ODBCStatements executed for an ODBCConnection, send the message blobsupport: true to the ODBCConnection object. To enable ODBCBlob object support for a specific ODBCStatement only, send the message blobsupport: true to the ODBCStatement object prior to preparing and executing the statement. ODBC supports BLOBs through the following data types: LONG_VARCHAR WLONGVARCHAR LONG_VARBINARY However, in SQL Server 2005, Microsoft introduced the following new data types, which are now preferred for LOB operations: varbinary(max) varchar(max) nvarchar(max) You can use either of the following two SQL Server ODBC drivers: The old SQL Server ODBC driver. This is SQLSRV32.DLL. The new SQL Native client. This is SQLNCLI.DLL. The ODBC wrapper in ObjectStudio 8.x has no problem dealing with these LOB data types, using either the old SQL Server ODBC driver or the new SQL Native client. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

95 Using chunks Introduction to using chunks Theoretically, the maximum size of a BLOB is two gigabytes. To handle this amount of data, you must use chunks. Columns containing BLOB data can be read in chunks using the ODBCBlob object. The default size of a chunk is 32 KB, but you can set the chunk size to any value. A TextBlob or Binary object pointing to the real data is returned in a result set. You can use this object to get the LOB value. This section contains the following Workspace code samples: Inserting LOB values into a table on page 96 Retrieving LOB objects from a table, using the default chunk size on page 99 Inserting LOB values into a table, using a chunk size of 192 KB on page 101 Getting any size of the LOB data on page 103 Handling LOBs at the database level on page 109 Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

96 Inserting LOB values into a table The following sample Workspace code demonstrates how to insert LOB values into a table on a SQL Server 2005 database: "Establish a connection to a data source." conn := ODBCConnection connect: #ODBCTest uid: #OSTUDIO pwd: #OSTUDIO. "Open a statement within the scope of the connection." stmt := conn addstatement. "Create a test table with LOB data types." stmt prepare: 'CREATE TABLE testlobtypes( cid int NOT NULL, ctext text, cimage image, cntext ntext, cvarcharmax varchar(max), cvarbinarymax varbinary(max), cnvarcharmax nvarchar(max) )'. stmt execute. "Prepare a new statement." stmt prepare:'insert into testlobtypes values( 11,?,?,?,?,?,?)'. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

97 "Get parameter descriptions." (conn functionsupported: #SQL_API_SQLDESCRIBEPARAM) iftrue: [ p1 := stmt describeparam: 1. p2 := stmt describeparam: 2. p3 := stmt describeparam: 3. p4 := stmt describeparam: 4. p5 := stmt describeparam: 5. p6 := stmt describeparam: 6. ] iffalse: [ p1 := SAGSqlColumnDescriptor type: -1 precision: nil scale: nil nullable: true. p2 := SAGSqlColumnDescriptor type: -4 precision: nil scale: nil nullable: true. p3 := SAGSqlColumnDescriptor type: -10 precision: nil scale: nil nullable: true. p4 := SAGSqlColumnDescriptor type: -1 precision: nil scale: nil nullable: true. p5 := SAGSqlColumnDescriptor type: -4 precision: nil scale: nil nullable: true. p6 := SAGSqlColumnDescriptor type: -10 precision: nil scale: nil nullable: true. ]. "Create test LOB values." str := String new: withall: $c. ba := ByteArray new: withall: 0. "Bind the parameters to the statement." stmt setparamdescr: 1 to: p1. stmt setparamdescr: 2 to: p2. stmt setparamdescr: 3 to: p3. stmt setparamdescr: 4 to: p4. stmt setparamdescr: 5 to: p5. stmt setparamdescr: 6 to: p6. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

98 "Assign LOB values to the parameters." p1 value: str. p2 value: ba. p3 value: str. p4 value: str. p5 value: ba. p6 value: str. "Execute." stmt execute. "Commit the changes." conn commit. "Remove statement from the collection of known statements for a connection." conn removestatement: stmt. "Disconnect from the data source." conn disconnect. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

99 Retrieving LOB objects from a table, using the default chunk size The following sample Workspace code shows how to retrieve LOB objects from a table: "Establish a connection to a data source." conn := ODBCConnection connect: 'DSN=ODBCTest;UID=OSTUDIO;PWD=OSTUDIO'. "Open a statement within the scope of the connection." stmt := conn addstatement. "Set blob support option." stmt blobsupport: true. "Prepare a statement." stmt prepare: 'select * from testlobtypes'. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

100 "Send the statement to the data source for execution." stmt execute. "Fetch the first record of the result set." stmt fetch. res := stmt recordasarray. "Get a clob object from a record." clobobj := res at: 2. "Get first chunk of the clob." chunk := clobobj getchunk. lobsize := 0. [ chunk notnil ] whiletrue: [ chunksize chunksize := chunk size. lobsize := lobsize + chunksize. "Display chunk size in the System Transcript." chunksize out. "Get the next chunk." chunk := clobobj getchunk. ]. "Display LOB size in the System Transcript." lobsize out. "Remove statement from the collection of known statements for a Connection." conn removestatement: stmt. "Disconnect from the data source." conn disconnect. From the printout in the Transcript, you can see that the initial default chunk size is (32 KB). However, to improve performance, you can reset this value based on the size of the LOB objects you are dealing with. That is, you can increase it for large LOBs or reduce it for small LOBs. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

101 Inserting LOB values into a table, using a chunk size of 192 KB The following sample Workspace code is similar to the code in the preceding section, Retrieving LOB objects from a table, using the default chunk size, on page 99. The difference is that in this section, the chunk size is set to (192 KB). This code demonstrates how to reset the chunk size to improve performance: "Establish a connection to a data source." conn := ODBCConnection connect: 'DSN=ODBCTest;UID=OSTUDIO;PWD=OSTUDIO'. "Open a statement within the scope of the connection." stmt := conn addstatement. "Set blob support option." stmt blobsupport: true. "Reset the chunk size to 192 KB." ODBCBlob defaultchunksize: "Prepare a statement." stmt prepare: 'select * from testlobtypes'. "Send the statement to the data source for execution." stmt execute. "Fetch the first record of the result set." stmt fetch. res := stmt recordasarray. "Get a clob object from a record." clobobj := res at: 2. "Get first chunk of the clob." chunk := clobobj getchunk. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

102 lobsize := 0. [ chunk notnil ] whiletrue: [ chunksize chunksize := chunk size. lobsize := lobsize + chunksize. "Display chunk size in the System Transcript." chunksize out. "Get next chunk." chunk := clobobj getchunk. ]. "Display LOB size in the System Transcript." lobsize out. "Remove statement from the collection of known statements for a connection." conn removestatement: stmt. "Disconnect from the data source." conn disconnect. From the printout in the Transcript, you will see the new chunk size. You will also see that fewer network round trips are required to get the value of the entire LOB. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

103 Getting any size of the LOB data Classic ObjectStudio contained the restriction that you could only get the first chunk of LOB data when you set the instance variable blobsupport to false. In ObjectStudio 8.x, this restriction is lifted; you can now get data in any desired size. You can set blobsupport and lobvaluesize at either the connection or statement level. The instance variable blobsupport defaults to false, meaning that data is returned. The instance variable lobvaluesize gets its default value (the default value can also be reset, but its initial value is 16MB) initially at the connection level, and can be changed at any time. When a statement is added, it will inherit the values for both instance variables from the connection, but these values can be changed at any time based upon your needs. This means that users can get one set of records as values and the next set of records as ODBCBlob class instances. The size of the returned LOB value can be changed as well. The following sample Workspace code demonstrates how to get any size of the LOB data: "First, create a test table and insert some test data." "Establish a connection to a data source " conn := ODBCConnection connect: 'DSN=ODBCTest;UID=OSTUDIO;PWD=OSTUDIO'. "Open a statement within the scope of the connection." stmt := conn addstatement. "Create a test table with LOB data types." stmt prepare: 'DROP TABLE testlobtypes'. stmt execute. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

104 "Create a test table with LOB data types." stmt prepare: 'CREATE TABLE testlobtypes( cid int NOT NULL, ctext text, cimage image, cntext ntext, cvarcharmax varchar(max), cvarbinarymax varbinary(max), cnvarcharmax nvarchar(max) )'. stmt execute. "Prepare a new statement; only insert a few lob values and leave the others as NULLs." stmt prepare:'insert into testlobtypes(cid, ctext, cimage) values( 12,?,?)'. "Get parameter descriptions." (conn functionsupported: #SQL_API_SQLDESCRIBEPARAM) iftrue: [ p1 := stmt describeparam: 1. p2 := stmt describeparam: 2. ] iffalse: [ p1 := SAGSqlColumnDescriptor type: -1 precision: nil scale: nil nullable: true. p2 := SAGSqlColumnDescriptor type: -4 precision: nil scale: nil nullable: true. ]. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

105 "Create test LOB values; one is smaller than the default buffer size, the other bigger." str := String new: 9800 withall: $c. ba := ByteArray new: withall: 0. "Bind the parameters to the statement." stmt setparamdescr: 1 to: p1. stmt setparamdescr: 2 to: p2. "Assign LOB values to the parameters." p1 value: str. p2 value: ba. "Execute." stmt execute. "Commit the changes." conn commit. "Close the statement." stmt close. "Remove the statement from the collection of known statements for a connection." conn removestatement: stmt. "Disconnect from the data source." conn disconnect. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

106 "Then try to retrieve the data by setting blobsupport to be either true or false." "Establish a connection to a data source." conn := ODBCConnection connect: 'DSN=ODBCTest;UID=OSTUDIO;PWD=OSTUDIO'. "Set the size of LOB data you want to be retrieved; the default is 16 MB." conn lobvaluesize: "Open a statement within the scope of the connection." stmt := conn addstatement. "Set the blob support option." stmt blobsupport: false. "Prepare a statement." stmt prepare: 'select * from testlobtypes'. "Send the statement to the data source for execution." stmt execute. "Fetch the first record of the result set." stmt fetch. res := stmt recordasarray. "Get the clob value from the record; since lobvaluesize is bigger than the actual size of the clob, we get the whole lob." clobobj := res at: 2. clobobj size. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

107 "Get part of the blob value, since lobvaluesize is smaller than the actual size of the blob." blobobj := res at: 3. blobobj size. "Get a NULL value in a LOB column." nilobj := res at: 4. "Close the statement." stmt close. "Remove statement from the collection of known statements for a connection." conn removestatement: stmt. "Disconnect from the data source." conn disconnect. "The following shows you how to handle ODBCBlob instances." "Establish a connection to a data source." conn := ODBCConnection connect: 'DSN=ODBCTest;UID=OSTUDIO;PWD=OSTUDIO'. "Open a statement within the scope of the connection." stmt := conn addstatement. "Set blob support option." stmt blobsupport: true. "Prepare a statement." stmt prepare: 'select * from testlobtypes'. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

108 "Send the statement to the data source for execution." stmt execute. "Fetch the first record of the result set." stmt fetch. res := stmt recordasarray. "Get a clob object from a record, using a size bigger than the actual size; we get the whole lob." clobobj := res at: 2. data := clobobj getdataofsize: data size. "Get a blob object from a record, using a size smaller than the actual size; we get part of the lob." blobobj := res at: 3. data := blobobj getdataofsize: data size. "Test a NULL value in a LOB column." nilobj := res at: 4. data := nilobj getdataofsize: "Close the statement." stmt close. "Remove statement from the collection of known statements for a connection." conn removestatement: stmt. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

109 Handling LOBs at the database level The previous code samples demonstrated how you could handle LOBs at the connection level. However, many ObjectStudio customers use ODBCDatabase instances directly. LOB handling at the database level is easier, but due to a limitation in ODBC, you cannot retrieve ODBCBlob instances when you call the execsql: method. You can only get ODBCBlob instances when using cursors. The following sample Workspace code demonstrates LOB handling at the database level: "Logon to the database server." ODBCDatabase logonserver: #ODBCTest user: #OSTUDIO password: # OSTUDIO. "Get access to the database needed." db := ODBCDatabase accessname: # ODBCTest. "Drop the test table if existed." res := db execsql: 'DROP TABLE testlobtypes'. "Create the test table." res := db execsql: 'CREATE TABLE testlobtypes( cid int NOT NULL, ctext text, cimage image, cntext ntext, cvarcharmax varchar(max), cvarbinarymax varbinary(max), cnvarcharmax nvarchar(max) )'. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

110 "Create test LOB values." str := String new: 9800 withall: $c. ba := ByteArray new: withall: 0. "Create a binding array." vars := Array new: 2. vars at: 1 put: str. vars at: 2 put: ba. "Execute the query to insert the test values." res := db execsql: 'insert into testlobtypes(cid, ctext, cimage) values( 12,?,?)' vars: vars. "Test retrievals." "Set the size of the return LOB value. The default is 16 MB." db lobvaluesize: "Run a query to retrieve LOB values. You can only get LOB values back using the following method." res := db execsql: 'select * from testlobtypes'. "Check the return LOB value sizes." recs := res records. rec := recs at: 1. clob := rec at: 2. clob size. blob := rec at: 3. blob size. nilobj := rec at: 4. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

111 "Test cursor support. In cursors, you can get back either LOB values or ODBCBlob instances." "The sql string used." sqlstring := 'select * from testlobtypes' "Test forward-only cursors." "Get LOB values back." db blobsupport: false. cur := db opencursorsql: sqlstring forupdateof: nil. row1 := cur next. "Check LOB value sizes." (row1 at: #ctext) size. (row1 at: #cimage) size. "Close the cursor." cur close. "Get ODBCClob instances back." db blobsupport: true. cur := db opencursorsql: sqlstring forupdateof: nil. row1 := cur next. "Get an ODBCBlob instance." clob := row1 at: #ctext. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

112 "Retrieve the LOB value in the desired size." clobvalue := clob getdataofsize: clobvalue size. blob := row1 at: #cimage. blobvalue:= blob getdataofsize: blobvalue size. "Close the cursor." cur close. "Test scrollable cursors." db blobsupport: false. cur := db openscrollablecursorsql: sqlstring forupdateof: nil. row1 := cur next. (row1 at: #ctext) size. (row1 at: #cimage) size. "Close the cursor." cur close. "Get ODBCClob instances back." db blobsupport: true. cur := db openscrollablecursorsql: sqlstring forupdateof: nil. row1 := cur next. clob := row1 at: #ctext. clobvalue := clob getdataofsize: clobvalue size. blob := row1 at: #cimage. blobvalue:= blob getdataofsize: blobvalue size. "Close the cursor." cur close. Database User s Guide, P Chapter: 4. ODBC Section: Working with Binary Large Objects (BLOBs)

113 Handling errors The following return codes are used with low-level ODBC support: SQL_SUCCESS SQL_SUCCESS_WITH_INFO SQL_ERROR SQL_STILL_EXECUTING SQL_INVALID_HANDLE SQL_NEED_DATA SQL_NO_DATA_FOUND If the returned error code is SQL_ERROR, send the lasterror message to a connection or statement to get the error information. For additional information on ODBC error handling, refer to the documentation in the Microsoft Open Database Connectivity Software Development kit. Database User s Guide, P Chapter: 4. ODBC Section: Handling errors

114 5. DB2 Introduction This chapter describes how the support for DB2 differs from the standard ObjectStudio database support. What s new in the ObjectStudio 8.x DB2 database wrapper Here are the highlights of the new DB2 database wrapper: In ObjectStudio 8.x, the specific operations necessary to support IBM databases are transparently sent through the VisualWorks DB2EXDI to the DB2 Call Level Interface (DB2 CLI). This means that, unlike in Classic ObjectStudio, there is no C code in the wrapper and there are no ObjectStudio DLLs serving as a bridge between the Smalltalk code and the database client libraries. The binding files that were needed in Classic ObjectStudio, which used the precompiler DB2 wrappers, are therefore no longer needed. The DB2 database wrapper s dependency on DB2 client versions has been eliminated. For example, the DB2 database wrapper will work with all DB2 clients as long as the db2cli.dll file is in an accessible folder whose path is specified by the PATH environment variable. Compared with Classic ObjectStudio s DB2 database wrapper, ObjectStudio 8.x s DB2 wrapper has much better support for LOB processing, stored procedure execution, and host variable handling. Because the ObjectStudio 8.x DB2 database wrapper contains only Smalltalk code, which is transparent to users, you can easily add new features. Database User s Guide, P Chapter: 5. DB2 Section: Introduction

115 Connecting to a DB2 database After configuring a DB2 client, you can use ESDatabase class>>logonserver: sname user: uname password: password to connect to a DB2 database. The following sample Workspace code demonstrates how to execute a simple query: db resulttable "Logon to a DB2 database." ESDatabase logonserver: #DBName user: #Ostudio password: #Ostudio. "Get the database instance." db := Database accessname: #DBName. "Run a select statement." resulttable := db execsql: 'select * from atable. Table information loaded when you access a DB2 database In ObjectStudio 8.x, you can control which tables will be loaded into an ESDatabase instance. By default, only the tables belonging to the logged-in user are loaded. To load only the tables belonging to the logged-in user, execute the following default table-loading SQL statement: 'SELECT NAME,CREATOR,REMARKS FROM SYSIBM.SYSTABLES WHERE CREATOR=USER ORDER BY NAME'. Database User s Guide, P Chapter: 5. DB2 Section: Connecting to a DB2 database

116 At any time, you can change the table-loading SQL and reload the table information. This can be useful because you can improve performance by limiting the number of tables loaded into the image. The following sample Workspace code demonstrates how this feature can be used: "Logon to a DB2 database." ESDatabase logonserver: #DB2Test user: #OSTUDIO password: #OSTUDIO. "Get the database instance." db := Database accessname: #DB2Test. "Check the loaded tables using the default loading SQL." loadedtables := db dbtables. "Write the customized loading SQL." loadingsql :='SELECT NAME,CREATOR,REMARKS FROM SYSIBM.SYSTABLES WHERE CREATOR=USER OR CREATOR=''SYSSTAT'' ORDER BY NAME'. "Change the loading SQL from default to the customized." ESDatabase tableloadingsql: loadingsql. "Re-load the table information using the customized loading SQL." db loadinfo. "Verify the new loaded tables." loadedtables1 := db dbtables.... Note that for the tables belonging to the logon user, table names will not contain the table owner s name. However, for other tables, the table owner's name will be part of the table names. Database User s Guide, P Chapter: 5. DB2 Section: Table information loaded when you access a DB2 database

117 Using cursors and scrollable cursors Introduction to using cursors and scrollable cursors The DB2 CLI supports the following two types of cursor: Non-scrollable. Forward-only non-scrollable cursors are the default cursor type used by the DB2 CLI driver. This cursor type is unidirectional and requires the least amount of overhead processing. Scrollable. The DB2 CLI supports these three types of scrollable cursors: Static Keyset-driven Dynamic This section contains the Workspace code sample Example of non-scrollable and scrollable cursors on page 118. Scrollable cursors supported by the DB2 CLI Static scrollable cursors A static scrollable cursor is read-only. Once it is created, no rows can be added or removed, and no value in any row will change. The cursor is not affected by other applications accessing the same data. The isolation level of the statement used to create the cursor determines how the rows of the cursor are locked, if at all. Keyset-driven scrollable cursors Unlike a static scrollable cursor, a keyset-driven scrollable cursor can detect and make changes to the underlying data. Keyset-driven cursors are based on row keys. When a keyset-driven cursor is first opened, it stores the keys in a keyset for the life of the entire result set. The keyset is used to determine the order and set of rows that are included in the cursor. As the cursor scrolls through the result set, it uses the keys in this keyset to retrieve the most recent values in the database, which are not necessarily the values that existed when the cursor was first opened. For this reason, changes are not reflected until the application scrolls to the row. Database User s Guide, P Chapter: 5. DB2 Section: Using cursors and scrollable cursors

118 Dynamic scrollable cursors Dynamic scrollable cursors can detect all changes (inserts, deletes, and updates) to the result set, and make insertions, deletions, and updates to the result set. Unlike keyset-driven cursors, dynamic cursors: Detect rows inserted by other cursors. Omit deleted rows from the result set (keyset-driven cursors recognize deleted rows as holes in the result set). Types of cursors supported by the ObjectStudio 8.x DB2 wrapper The ObjectStudio 8.x DB2 wrapper supports both non-scrollable and scrollable cursors. However, the only type of scrollable cursor that it currently supports is keyset-driven scrollable cursors. It does not currently support static scrollable cursors or dynamic scrollable cursors. Example of non-scrollable and scrollable cursors Here is an example of using non-scrollable (forward-only) and scrollable cursors: db sqlstring res cur curvalue "Logon to a DB2 database." ESDatabase logonserver: #DB2Test user: #OSTUDIO password: #OSTUDIO. "Get the database instance." db := Database accessname: #DB2Test. "Create a test table." res := db execsql: 'CREATE TABLE TestTable (cid int not null primary key, cname varchar(100))'. Database User s Guide, P Chapter: 5. DB2 Section: Using cursors and scrollable cursors

119 "Insert test data into the test table using host variables." sqlstring := 'INSERT INTO TestTable VALUES (?,?)'. 1 to: 10 do: [ :i vars vars := Array with: i with: ('test' + i). db execsql: sqlstring vars: vars. ]. "Create the test SQL statement." sqlstring := 'select * from TestTable'. "Get a forward-only cursor." cur := db opencursorsql: sqlstring forupdateof: nil. "Get next cursor value and print it to the transcript." [(curvalue := cur next) notempty] whiletrue: [ curvalue out. ]. "Close the cursor." cur close. "Get a scrollable cursor." cur := db openscrollablecursorsql: sqlstring forupdateof: nil. "Set cursor to the last record." cur setpositionto: 10. "Get previous cursor value and print it to the transcript." [(curvalue := cur previous) notnil] whiletrue: [ curvalue out. ]. "Close the cursor." cur close. Database User s Guide, P Chapter: 5. DB2 Section: Using cursors and scrollable cursors

120 Executing stored procedures Introduction to executing stored procedures ObjectStudio provides methods that execute DB2 procedures. There are two varieties of each of these methods, one that includes a block of code that executes when an error occurs, and one that does not include the block. This section contains the Workspace code sample Examples of DB2 stored procedures on page 122. Methods to execute DB2 procedures Use one of the following methods to execute DB2 procedures: execproc: procstr - Executes stored procedure and returns an instance of class Array containing the output values from the procedure or, if an error occurs, an instance of class Message or an instance of class Integer (representing the return code from the stored procedure). procstr contains a string object identifying the procedure name of the DB2 stored procedure to execute. execproc: procstr onerror: errorblock - Executes stored procedures in the same manner as execproc:. errorblock specifies an instance of BlockContext. execproc: procstr params: params paramtypes: paramtypes - Executes stored procedures in the same manner as execproc:. params is an array of objects to be passed to/from the DB2 stored procedure. Each object of the array must match the corresponding type defined by paramtypes. params and paramtypes must be arrays of the same size. paramtypes is an array of instances of class Symbol indicating whether the corresponding parameter is for input, output, or both. The valid Symbols are #in, #out and #inout. execproc: procstr params: params paramtypes: paramtypes onerror: errorblock - Executes stored procedures in the same manner as execproc:params:paramtypes: with the addition of the errorblock parameter. Database User s Guide, P Chapter: 5. DB2 Section: Executing stored procedures

121 Considerations for parameters used by stored procedures In order to pass data to or receive data from a DB2 stored procedure, you must consider the parameter s characteristics and define that parameter s characteristics with the usual ObjectStudio allocation techniques. For example, if you plan to pass a string of 18 bytes as input to a stored procedure and receive up to 100 bytes as output from the same parameter of a stored procedure, the String object passed as a parameter should be defined as a 100-byte string. Here is the code: astring := 'My eighteen bytes.' append: (String new: 82). Another example: if you want to receive (output only parameter) a decimal value back from a stored procedure that has a precision of 9 and scale of 2, ensure the stored procedure is called with a Decimal object that has the precision and scale properly defined. Here is the code to accommodate a decimal value with precision 9 and scale 2: adecimal := In general, predefine parameter objects used by stored procedures by defining their maximum precision before calling the stored procedure or at least ensure that the parameters passed have the same precision as those expected by the stored procedure. Database User s Guide, P Chapter: 5. DB2 Section: Executing stored procedures

122 Examples of DB2 stored procedures The following sample Workspace code for creates and invokes DB2 procedures with in, out, and inout parameters: "Logon to the DB2 database." ret := ESDatabase logonserver: #DB2Test user: #username password: #password. "Get the database instance." db := ESDatabase accessname: #DB2Test. "Create the test table." res := db execsql: 'create table TestTable(cid int, cname varchar(50))'. "Create an insert procedure." res := db execsql: 'create procedure testproc_1(in inint int, IN inchar varchar(50)) LANGUAGE SQL begin insert into TestTable values (inint, inchar); end'. "Invoke the procedure." res := db execproc: 'testproc_1' params: {1 'test1'} paramtypes: {#in #in}. "Verify the result." res := db execsql: 'select * from TestTable'. "Create a procedure with IN and OUT parameters." res := db execsql: 'create procedure testproc_2(in inint int, OUT outchar varchar(50)) LANGUAGE SQL begin select cname into outchar from TestTable where cid= inint; end'. Database User s Guide, P Chapter: 5. DB2 Section: Executing stored procedures

123 "Invoke the procedure." res := db execproc: 'testproc_2' params: {1 'xxx'} paramtypes: {#in #out}. "Create a procedure with INOUT parameters." res := db execsql: 'create procedure testproc_3(inout inoutvalue int) LANGUAGE SQL begin declare v_cid int default 0; select cid into v_cid from TestTable where cid= inoutvalue; set inoutvalue = v_cid + 100; end'. "Invoke the procedure." res := db execproc: 'testproc_3' params: {1} paramtypes: {#inout}. "Create a procedure with no parameters." res := db execsql: 'create procedure delete_testdata() LANGUAGE SQL begin delete from TestTable; end'. "Invoke the procedure." res := db execproc: 'delete_testdata '. "Verify the result; the returned table should be empty." res := db execsql: 'select * from TestTable'.... Database User s Guide, P Chapter: 5. DB2 Section: Executing stored procedures

124 Working with LOBs Introduction to working with LOBs This section contains the following Workspace code samples for working with Large Objects (LOBs): General example for working with LOBs on page 124 Working with LOBs in cursors and scrollable cursors on page 127 Working with LOBs and files on page 131 General example for working with LOBs The following sample Workspace code provides a general demonstration of how to handle LOBs: "Logon to a DB2 database." ESDatabase logonserver: #DB2Test user: #OSTUDIO password: #OSTUDIO. "Get the database instance." DB := Database accessname: #DB2Test. "Drop the test table if existed." Res := DB execsql: 'DROP TABLE TestLob'. "Create a test table with LOB columns." Res := DB execsql: 'CREATE TABLE TestLob (a CLOB(2m), b BLOB(2m), c INT)'. "Prepare some test LOB values." ClobLength := "1MB" BlobLength := "1MB" ClobInput := String new: ClobLength withall: $a. BlobInput := ByteArray new: ClobLength withall: 1. Database User s Guide, P Chapter: 5. DB2 Section: Working with LOBs

125 "Start a transaction." DB begintran. "Insert the test data into the test table." Res := DB execsql: 'INSERT INTO TestLob (a, b, c) VALUES (?,?,?)' vars: (Array with: ClobInput readstream with: BlobInput readstream with: 2). "Commit the transaction." DB commit. "Start a new transaction." DB begintran. "We want the returned LOB values to have a size limit of 200 bytes." DB lobvaluesize: 200. "Get LOBs as values." Res := DB execsql: 'select * from TestLob' answerlobasproxy: false. Recs := Res records. Rec1 := Recs at: 1. "Verify the CLOB value and size." Clob := Rec1 at: 1. Clob size. "Verify the BLOB value and size." Blob := Rec1 at: 2. Blob size. Database User s Guide, P Chapter: 5. DB2 Section: Working with LOBs

126 "Get LOBs as locators." Res := DB execsql: 'select * from testlob' answerlobasproxy: true. Recs := Res records. Rec1 := Recs at: 1. "Get the CLOB locator and verify its length." Clob := Rec1 at: 1. Clob getloblength. "Get the whole CLOB and verify its size. The size should be the same as that of the CLOB value we inserted before." ClobValue := Clob readall. ClobValue size. "Get the CLOB locator and verify its length." Blob := Rec1 at: 2. Blob getloblength. "Get the whole BLOB and verify its size. The size should be the same as that of the BLOB value we inserted before." BlobValue := Blob readall. BlobValue size. "Rollback the transaction." DB rollback. Database User s Guide, P Chapter: 5. DB2 Section: Working with LOBs

127 From the example above, you can see that there are two ways to retrieve LOBs from the database: As values. Useful when you are dealing with small LOBs and you do not need to worry about memory usage. As LOB locators. Useful when you are dealing with Large LOBs or you are interested in, and need to retrieve, only some of the LOBs. You must use the following method to handle LOBs: ESDatabase>>execSql: sqlobj answerlobasproxy: aboolean 'sqlobj' is an object of class String or an SQL query object. 'aboolean' is used to indicate whether value or LOB locators should be returned if the result set contains LOB columns. If you choose to get the LOBs as values, you can set the size limit of the returned LOB values by using the following method: ESDatabase>> lobvaluesize: aninteger If you do not set this method s value, it will take its default value of 4000 bytes. You can reset its value at any time. Working with LOBs in cursors and scrollable cursors LOB handling in both cursors and scrollable cursors is done in a similar way. See the following sample Workspace code: "Logon to a DB2 database." ESDatabase logonserver: #DB2Test user: #OSTUDIO password: #OSTUDIO. "Get the database instance." DB := Database accessname: #DB2Test. "Begin a new transaction." DB begintran. Database User s Guide, P Chapter: 5. DB2 Section: Working with LOBs

128 "Using cursors." "Get LOBs as values. We reset the default size to get the whole LOBs." DB lobvaluesize: "Open a cursor." Cur := DB opencursorsql: 'select * from testlob' forupdateof: {} answerlobasproxy: false. "Get the next record." Val1 := Cur next. "Get the CLOB value and verify its size." Clob := Val1 at: #A. Clob size. "Get the BLOB value and verify its size." Blob := Val1 at: #B. Blob size. "Close the cursor." Cur close. "Get LOBs as locators." Cur := DB opencursorsql: 'select * from testlob' forupdateof: {} answerlobasproxy: true. "Get the next record." Val1 := Cur next. "Get the CLOB locator and verify its length." Clob := Val1 at: #A. Clob getloblength. Database User s Guide, P Chapter: 5. DB2 Section: Working with LOBs

129 "Get the CLOB value and verify its size." ClobValue := Clob readall. ClobValue size. "Get the BLOB locator and verify its length." Blob := Val1 at: #B. Blob getloblength. "Get the BLOB value and verify its size." BlobValue := Blob readall. BlobValue size. "Close the cursor." Cur close. "Using scrollable cursors, get LOBs as values. We reset the default size to 200 bytes." DB lobvaluesize: 200. Cur := DB openscrollablecursorsql: 'select * from testlob' forupdateof: {} answerlobasproxy: false. "Get the next record." Val1 := Cur next. "Get the CLOB value and verify its size." Clob := Val1 at: #A. Clob size. "Get the BLOB value and verify its size." Blob := Val1 at: #B. Blob size. "Close the cursor." Cur close. Database User s Guide, P Chapter: 5. DB2 Section: Working with LOBs

130 "Get LOBs as locators." Cur := DB openscrollablecursorsql: 'select * from testlob' forupdateof: {} answerlobasproxy: true. Val1 := Cur next. "Get the CLOB locator and verify its length." Clob := Val1 at: #A. Clob getloblength. "Get the CLOB value and verify its size." ClobValue := Clob readall. ClobValue size. "Get the BLOB locator and verify its length." Blob := Val1 at: #B. Blob getloblength. "Get the BLOB value and verify its size." BlobValue := Blob readall. BlobValue size. "Close the cursor." Cur close. "Rollback the transaction." DB rollback. Database User s Guide, P Chapter: 5. DB2 Section: Working with LOBs

131 Working with LOBs and files You may sometimes need to insert files into LOB columns in a database. These may be audio, video, photo, or plain text files. Or you may need to retrieve some LOB contents directly into files on your hard drive. OS8 s DB2 database wrapper enables you to do this easily. To insert files, just tell the wrapper which files you want to insert into LOB columns, and the wrapper will do it for you. Or to retrieve files, just tell the wrapper into which files you wish to retrieve the LOB contents, and again the wrapper will do it for you. See the following sample Workspace code: "Assume that there is a folder called C:\Test. This folder contains a text file named LOBFileReference.test and a binary file named calc.exe (calc.exe is the Windows calculator). In the example below, these two files are inserted into the LOB columns of a DB2 table and then retrieved back to the C:\Test folder, using different file names. By comparing the files, you will find that the retrieved files are identical to the ones inserted." ret db res clobfileref blobfileref bindarray arrayoffilenames "Logon and get the database instance you want." ret := ESDatabase logonserver: #DB2Test user: #username password: #pwd. db :=ESDatabase accessname: #DB2Test. "Create a test table with LOB columns." res := db execsql: 'CREATE TABLE TestLOBFileRef (a CLOB(32k), b BLOB(1M), c INT)'. "Prepare the LOB files to insert into the test table." clobfileref := db getlobfilereferencefor: 'C:\Test\LOBFileReference.test' isblob: false. blobfileref := db getlobfilereferencefor: 'C:\Test\calc.exe' isblob: true. bindarray := Array with: clobfileref with: blobfileref with: 1. "Start a transaction." db begintran. Database User s Guide, P Chapter: 5. DB2 Section: Working with LOBs

132 "Insert the test data into the test table." res := db execsql: 'INSERT INTO TestLOBFileRef (a, b, c) VALUES (?,?,?)' vars: bindarray. "Commit the transaction." db commit. "Start a transaction." db begintran. "Retrieve the LOB values into files." arrayoffilenames := Array with: 'C:\Test\LOBFileRefOutputFile.test' with: 'C:\Test\calcOutput.exe'. res := db execsql: 'select a, b from TestLOBFileRef where c=1' answerlobasfiles: arrayoffilenames. "Rollback the transaction." db rollback. Note that you can mix up the usage of different data types when you insert into the database, as shown above, but not when you retrieve from it. For example, you can create a binding array containing Integers, Strings, ByteArrays, and LOB file references, and insert them into the database. However, if you want to retrieve LOBs, you must either retrieve them as Strings and ByteArrays or as files, but not both in a single call. Database User s Guide, P Chapter: 5. DB2 Section: Working with LOBs

133 6. Oracle Introduction This chapter describes how the support for the Oracle databases differs from the standard ObjectStudio database support. What s new in the ObjectStudio 8.x Oracle database wrapper Here are the highlights of the new Oracle database wrapper: In ObjectStudio 8.x, the specific operations necessary to support Oracle databases are transparently sent through the VisualWorks OracleEXDI to the Oracle Call Interface (Oracle CLI). This means that, unlike in Class ObjectStudio, there is no C code in the wrapper and there are no ObjectStudio DLLs serving as a bridge between the Smalltalk code and the database client libraries. The Oracle database wrapper s dependency on Oracle client versions has been eliminated. The Oracle database wrapper will now work with all Oracle clients as long as the oci.dll file is in an accessible folder whose path is specified by the PATH environment variable. Compared with Classic ObjectStudio s Oracle database wrapper, ObjectStudio 8.x s Oracle wrapper has much better support for LOB processing, stored procedure execution, and host variable handling. Because the ObjectStudio 8.x Oracle database wrapper contains only Smalltalk code, which is transparent to users, you can easily add new features. Database User s Guide, P Chapter: 6. Oracle Section: Introduction

134 Connecting to an Oracle database There are two ways to logon to an Oracle database: Use the Oracle Logon window. Logon programmatically. Use the following logon method: OracleDatabase>>logOnServer: user: password: alias: Consider the following example: OracleDatabase logonserver: #OracleDB user: #scott password: #tiger alias: #OracleDB. Getting version information for the Oracle client and server In the ObjectStudio 8.x Oracle database wrapper, you can get these types of version information: Version information for the Oracle OCI client you are using. You can get this information before the connection is established. Version information for the Oracle server to which you have connected. You can get this information only after the connection has been established. The following code samples demonstrate: How to get various kinds of version information for the Oracle client, before the connection has been established How to get version information for the Oracle server, after the connection has been established See below: "Get the client version." OracleDatabase ociclientversion. "Get the client major version." OracleDatabase ociclientmajorversion. "Get the client minor version." OracleDatabase ociclientminorversion. Database User s Guide, P Chapter: 6. Oracle Section: Connecting to an Oracle database

135 "Get the client patch number." OracleDatabase ociclientpatchnum. "Get the client update number." OracleDatabase ociclientportupdatenum. "Get the client port update number." OracleDatabase ociclientupdatenum. "Log on to the Oracle server." Ret :=OracleDatabase logonserver: #'OracleDB' user: #'username' password: #'password' alias: #'OracleDB'. "Get the database instance." DB := OracleDatabase accessname: #OracleDB. "Get the Oracle server version." Sver := DB getserverversion. Database User s Guide, P Chapter: 6. Oracle Section: Getting version information for the Oracle client and server

136 Table information loaded when you access an Oracle database Introduction to loaded table information In ObjectStudio 8.x, you can control which tables will be loaded into an OracleDatabase instance. By default, only the tables, views, and synonyms belonging to the logged-in user are loaded. To load only the tables, views, and synonyms belonging to the logged-in user, execute the following default tableloading SQL statement: 'SELECT TABLE_NAME,OWNER, '''' as REMARKS FROM ALL_TABLES WHERE OWNER=USER AND TABLE_NAME NOT LIKE ''BIN%'' UNION SELECT VIEW_NAME,OWNER, '''' as REMARKS FROM ALL_VIEWS WHERE OWNER=USER UNION SELECT SYNONYM_NAME,OWNER, '''' as REMARKS FROM ALL_SYNONYMS WHERE OWNER=USER ORDER BY 1,2'. At any time, you can change the table-loading SQL and reload the table information. This can be useful because you can improve performance by limiting the number of tables loaded into the image. This section contains the following Workspace code samples: Changing the table-loading SQL and reloading the table information on page 137 Accessing tables in an OracleDatabase instance on page 138 Database User s Guide, P Chapter: 6. Oracle Section: Table information loaded when you access an Oracle database

137 Changing the table-loading SQL and reloading the table information The following sample code in Workspace demonstrates how you can change the table-loading SQL and reload the table information: "Logon to the Oracle server." ret := OracleDatabase logonserver: #OracleDB user: #username password: #pwd alias: #OracleDB. "Get the database instance." db := Database accessname: #OracleDB. "Check the loaded tables using the default loading SQL." loadedtables := db dbtables. "Write the customized loading SQL. In this example, we just want to load the tables belonging to SYSTEM as well." loadingsql := 'SELECT TABLE_NAME,OWNER, '''' as REMARKS FROM ALL_TABLES WHERE (OWNER=USER OR OWNER = ''SYSTEM'') AND TABLE_NAME NOT LIKE ''BIN%'' UNION SELECT VIEW_NAME,OWNER, '''' as REMARKS FROM ALL_VIEWS WHERE OWNER=USER UNION SELECT SYNONYM_NAME,OWNER, '''' as REMARKS FROM ALL_SYNONYMS WHERE OWNER=USER ORDER BY 1,2'. "Change the loading SQL from default to the customized." OracleDatabase tableloadingsql: loadingsql. "Reload the table information using the customized loading SQL." db loadinfo. "Verify the new loaded tables." loadedtables1 := db dbtables.... Note that for the tables belonging to the logon user, table names will not contain the table owner s name. However, for other tables, the table owner's name will be part of the table names. Database User s Guide, P Chapter: 6. Oracle Section: Table information loaded when you access an Oracle database

138 Accessing tables in an OracleDatabase instance You can get OracleTable instances from an OracleDatabase instance. Although Oracle table names are normally case-insensitive, if you enclose one in double quotes, it becomes case-sensitive. This is important to remember when you are naming an Oracle table, and the name includes a space, requiring that you enclose the name in double quotes. For the tables belonging to the logon user, the table owner s name will not be added in front of the table name. However, for the tables not belonging to the logon user, the table owner s name will be added before the table name. This means that you must know the complete name (table owner s name + table name) to access these tables. See the following sample code in Workspace: "Logon to the Oracle server." Ret := OracleDatabase logonserver: #OracleDB user: #username password: #pwd alias: #OracleDB. "Get the database instance." DB := OracleDatabase accessname: #OracleDB. "Create a test table." Res := DB execsql: 'create table "test case1"(cid int, cname varchar2(50))'. "This works." Tb := DB getnamed: #'"test case1"'. "This does not work." Tb := DB getnamed: #'"test case"' asuppercase. "Assuming the logon user is TEST." "This should work too." Tb := DB getnamed: #'TEST."test case"'. Database User s Guide, P Chapter: 6. Oracle Section: Table information loaded when you access an Oracle database

139 "Try the tables not belonging to the logon user." "Write the customized loading SQL." loadingsql := 'SELECT TABLE_NAME,OWNER, '''' as REMARKS FROM ALL_TABLES WHERE (OWNER=USER OR OWNER = ''SYSTEM'') AND TABLE_NAME NOT LIKE ''BIN%'' UNION SELECT VIEW_NAME,OWNER, '''' as REMARKS FROM ALL_VIEWS WHERE OWNER=USER UNION SELECT SYNONYM_NAME,OWNER, '''' as REMARKS FROM ALL_SYNONYMS WHERE OWNER=USER ORDER BY 1,2'. "Change the loading SQL from default to the customized." OracleDatabase tableloadingsql: loadingsql. "Reload the table information using the customized loading SQL." DB loadinfo. "This works." Tb := DB getnamed: #'SYSTEM.HELP'. "This should not work." Tb := DB getnamed: #'HELP'.... Database User s Guide, P Chapter: 6. Oracle Section: Table information loaded when you access an Oracle database

140 Using cursors and scrollable cursors The following sample Workspace code demonstrates the use of cursors and scrollable cursors in the Oracle database wrapper: ret db sqlstring res cur curvalue "Logon to the Oracle server." ret := OracleDatabase logonserver: #OracleDB user: #username password: #pwd alias: #OracleDB. "Access the database." db := OracleDatabase accessname: #OracleDB. "Create a test table." res := db execsql: 'CREATE TABLE TestTable (cid int not null primary key, cname varchar2(100))'. "Insert test data into the test table using host variables." sqlstring := 'INSERT INTO TestTable VALUES (?,?)'. 1 to: 10 do: [ :i vars vars := Array with: i with: ('test' + i). db execsql: sqlstring vars: vars. ]. "Create the test SQL statement." sqlstring := 'select * from TestTable'. "Get a forward-only cursor." cur := db opencursorsql: sqlstring forupdateof: nil. "Get next cursor value and print it to the transcript." [(curvalue := cur next) notempty] whiletrue: [ curvalue out. ]. Database User s Guide, P Chapter: 6. Oracle Section: Using cursors and scrollable cursors

141 "Close the cursor." cur close. "Get a scrollable cursor." cur := db openscrollablecursorsql: sqlstring forupdateof: nil. "Set cursor to the last record." cur setpositionto: 10. "Get previous cursor value and print it to the transcript." [(curvalue := cur previous) notnil] whiletrue: [ curvalue out. ]. "Close the cursor." cur close.... Database User s Guide, P Chapter: 6. Oracle Section: Using cursors and scrollable cursors

142 Working with host variables Host variables are Smalltalk variables that are referenced within SQL statements. They allow an application to pass input data to, and to receive output data from, the database. By using a host variable instead of a literal value in an SQL statement, you give an application the flexibility to process different rows in a table or view. The following sample Workspace code shows how to use host variables in the ObjectStudio 8.x Oracle database wrapper: "Logon to the Oracle server." Ret := OracleDatabase logonserver: #OracleDB user: #username password: #pwd alias: #OracleDB. "Get the database instance." DB := OracleDatabase accessname: #OracleDB. "Drop the test table if it exists." Res := DB execsql: 'drop table tryvar'. "Create the test table." Res := DB execsql: 'create table tryvar (cid int, cname varchar2(50))'. "Insert a row of test data." Res := DB execsql: 'insert into tryvar values(10, ''your name'')'. "Update the row using host variable support." SqlString := 'UPDATE tryvar set name = ''the sample1'' cid = :1 '. Vars := {10}. Res := DB execsql: SqlString vars: Vars. where "Verify the data changes." Res := DB execsql: 'select * from tryvar'. "Try a select statement using host variables." SqlString := 'SELECT * FROM tryvar WHERE cid = :1 '. Vars := {10}. Res := DB execsql: SqlString vars: Vars. Database User s Guide, P Chapter: 6. Oracle Section: Working with host variables

143 Binding arrays When you are binding arrays of values, the size of the array must match the size specified by the INSERT statement. When multiple host variables are used in array binding, the sizes of the binding arrays for different host variables are not required to be the same, but the size of the longest array is used as the execution iteration. See the following sample Workspace code: "Insert arrays of data using host variable support." SqlString := 'insert into tryvar values (?,?)'. Vars := {{ } {'test1' 'test2' 'test3'}}. Res := DB execsql: SqlString vars: Vars. "Another way of inserting arrays of data." SqlString := 'insert into tryvar values (:1, :2)'. Vars := {{ } {'test11' 'test21' 'test31'}}. Res := DB execsql: SqlString vars: Vars. "Verify the data inserted." Res := DB execsql: 'select * from tryvar'. Database User s Guide, P Chapter: 6. Oracle Section: Binding arrays

144 Binding Class Instances The preceding code samples showed you how to bind an array by position. However, binding by name will enable you to bind class instances. In this section, you will use a class named TestBind in all of the examples. Defining class TestBind Define a class TestBind as the following: Smalltalk.ObjectStudio defineclass: #TestBind superclass: #{ObjectStudio.Object} indexedtype: #none private: false instancevariablenames: 'cid cname ' classinstancevariablenames: '' imports: '' category: 'Test' Defining the instance methods for class TestBind The TestBind class defines few instance methods: initialize cid := nil. cname := nil. TestBind>>cid ^cid cid: anobject cid := anobject cname ^cname cname: anobject cname := anobject Database User s Guide, P Chapter: 6. Oracle Section: Binding Class Instances

145 Defining the class method for class TestBind The TestBind class also defines a class method: cid: aninteger cname: astring ^self new cid: aninteger; cname: astring Inserting the TestBind instances into the test table By executing the following pieces of code in the Workspace, you will be able to insert the TestBind instances in to the test table: "Test binding an instance of TestBind class." SqlString := 'insert into tryvar values (:cid, :cname)'. Vars := TestBind cid: 101 cname: 'test101'. Res := DB execsql: SqlString vars: Vars. "Verify the data inserted." Res := DB execsql: 'select * from tryvar'. Binding arrays using an instance of the TestBind class When binding class instances, you can also bind arrays. See the following sample Workspace code: "Test binding arrays using an instance of TestBind class." SqlString := 'insert into tryvar values (:cid, :cname)'. Vars := TestBind cid: { } cname: {'test11' 'test21' 'test31' 'try41' 'try51'}. Res := DB execsql: SqlString vars: Vars. "Verify the data inserted." Res := DB execsql: 'select * from tryvar'.... Note that when you are binding class instances, the host variable names must be the same as those method names that get the corresponding instance variables. Database User s Guide, P Chapter: 6. Oracle Section: Binding Class Instances

146 Executing Oracle PL/SQL procedures Introduction to executing Oracle PL/SQL procedures ObjectStudio provides methods that execute Oracle PL/SQL procedures. There are two varieties of each of these methods: one that includes a block of code that executes when an error occurs, and one that does not include the block. Use one of the following methods to execute Oracle PL/SQL procedures: execproc: procstr paramtypes: paramtypes - Executes an Oracle PL/SQL procedure using parameters and returns an instance of class Array containing the output values from the procedure. The procstr parameter contains a string with a PL/SQL procedure call that can contain output variable placeholders. The paramtypes parameter is an array of instances of class Symbol. Each Symbol represents the Oracle type for the output variable placeholders. Valid paramtypes are: #VARCHAR2, #CHAR, #INTEGER, #FLOAT, #LONG, and #DATE. execproc: procstr onerror: errorblock - Executes an Oracle PL/SQL procedure. The procstr parameter contains a string with a PL/SQL procedure call that can contain output variable placeholders. errorblock is an instance of BlockContext. execproc: procstr paramtypes: paramtypes onerror: errorblock - Executes an Oracle PL/SQL procedure in a manner that combines the features of execproc:paramtypes: and execproc:onerror:. This section contains the Workspace code sample Example of working with Oracle stored procedures on page 147. Database User s Guide, P Chapter: 6. Oracle Section: Executing Oracle PL/SQL procedures

147 Example of working with Oracle stored procedures Below is sample Workspace code for working with Oracle stored procedures: ret db res "Logon to the Oracle server." ret := OracleDatabase logonserver: #OracleDB user: #username password: #pwd alias: #OracleDB. "Get the database instance." db := OracleDatabase accessname: #OracleDB. "Drop the test table if it exists." res := db execsql: 'drop table TestTable'. "Create the test table." res := db execsql: 'create table TestTable(cid number, cname varchar2(50))'. "Create an insert procedure." res := db execsql: 'create or replace procedure testproc_1(inint IN number, inchar IN varchar2) AS begin insert into TestTable values (inint, inchar); end;'. "Invoke the procedure." res := db execproc: 'testproc_1 (4, ''test:4:'') '. "Insert another row." res := db execproc: 'testproc_1 (3, ''test3'') '. "Make sure the inserts are successful. You should see two rows inserted into the table." res := db execsql: 'select * from TestTable'. Database User s Guide, P Chapter: 6. Oracle Section: Executing Oracle PL/SQL procedures

148 "Create another procedure to get OUT parameters." res := db execsql: 'create or replace procedure testproc_2(inint IN int, outchar OUT varchar2) AS begin select cname into outchar from TestTable where cid = inint; end;'. "Invoke the procedure. You should get an array of OUTPUT parameter values." res := db execproc: 'testproc_2 (4, :1)' paramtypes: { #VARCHAR2 }. "Another way to invoke the procedure. You should get an array of OUTPUT parameter values." res := db execproc: 'testproc_2 (3, :b)' paramtypes: { #VARCHAR2 }.... Database User s Guide, P Chapter: 6. Oracle Section: Executing Oracle PL/SQL procedures

149 Executing Oracle PL/SQL functions Introduction to executing Oracle PL/SQL functions ObjectStudio provides the following methods to execute Oracle PL/SQL functions: execfunc: funcstr returntype: returntype paramtypes: paramtypes - Executes an Oracle PL/SQL function and returns an instance of class Array. The first position contains the function return value. The remaining positions contain the output values from the function. The funcstr parameter is a string that contains a PL/SQL function call. The string can contain output variable placeholders. The returntype parameter specifies the Oracle type for the return value and must be one of the previous paramtypes. The paramtypes parameter is an array of instances of class Symbol. Each Symbol represents the Oracle type for the output variable placeholders. Valid paramtypes are: #VARCHAR2, #CHAR, #INTEGER, #FLOAT, #LONG, and #DATE. execfunc: funcstr onerror: errorblock - Executes an Oracle PL/SQL function and returns an instance of class Array in the same manner as execfunc:returntype:paramtypes:. In addition, the errorblock specifies an instance of BlockContext. execfunc: funcstr returntype: returntype paramtypes: paramtypes onerror: errorblock - Executes an Oracle PL/SQL function in a manner that combines the features of execfunc:returntype:paramtypes: and execfunc:onerror:. This section contains the Workspace code sample Examples of calling Oracle PL/SQL functions on page 150. Database User s Guide, P Chapter: 6. Oracle Section: Executing Oracle PL/SQL functions

150 Examples of calling Oracle PL/SQL functions Using the test table created in the preceding example, you can test the use of Oracle functions in the following sample Workspace code: "Create a function to test." res := db execsql: 'create or replace function testfunction_1(inid number) return varchar2 is begin declare ret_name varchar2(30); begin select cname into ret_name from TestTable where cid=inid; return ret_name; end; end; '. "Invoke the function. You should get an array of return values." res := db execfunc: 'testfunction_1(4) ' "Invoke again using a different input value." res := db execfunc: 'testfunction_1(3) ' Database User s Guide, P Chapter: 6. Oracle Section: Executing Oracle PL/SQL functions

151 "Create the second function to test." res := db execsql: 'create or replace function testfunction_2(inname varchar2) return number is begin declare ret_id number; begin select cid into ret_id from TestTable where cname=inname; return ret_id; end; end; '. "Invoke the function. You should get an array of return values." res := db execfunc: 'testfunction_2( ''test:4:'') ' "Get another record." res := db execfunc: 'testfunction_2(''test3'') ' Database User s Guide, P Chapter: 6. Oracle Section: Executing Oracle PL/SQL functions

152 "Create the third function, which has both a return value and OUT parameters to test." res := db execsql: 'create or replace function testfunction_3(inname varchar2, outparam OUT varchar2) return number is begin declare ret_id number; begin select cid into ret_id from TestTable where cname=inname; select cname into outparam from TestTable where cid=ret_id- 1; return ret_id; end; end; '. "Invoke the function. You should get an array of return values." res := db execfunc: 'testfunction_3( ''test:4:'', :outvalue)' returntype: #VARCHAR2 paramtypes: { #VARCHAR2 }. "Another try to invoke." res := db execfunc: 'testfunction_3( ''test:4:'', :1)' returntype: #VARCHAR2 paramtypes: { #VARCHAR2 }.... Database User s Guide, P Chapter: 6. Oracle Section: Executing Oracle PL/SQL functions

153 Support for Oracle Nested Tables and Oracle PL/SQL REF Cursors Introduction NESTED TABLE is an Oracle data type supporting columns that can each contain entire sub-tables. ObjectStudio 8.x supports the use of Oracle Nested Tables. Two alternative approaches to retrieving Oracle Nested Table information In ObjectStudio 8.x, you can retrieve information stored in Oracle Nested Tables using either of two alternative approaches: Getting information all at once from each referenced Oracle Nested Table. This approach will return the information from each referenced Oracle Nested Table in an ObjectStudio table. To make use of this approach, use the method execsql: to execute an SQL statement that references one or more Oracle Nested Tables. See Example 1 in the topic Code sample for retrieving Oracle Nested Tables and for using Oracle REF Cursors in Oracle functions and procedures on page 154. Getting information row-by-row from each referenced Oracle Nested Table. This approach will return a cursor for each referenced Oracle Nested Table. To make use of this approach, use the forward-only cursor to execute an SQL statement that references one or more Oracle Nested Tables, then process the records row-by-row. See Example 1 in the topic Code sample for retrieving Oracle Nested Tables and for using Oracle REF Cursors in Oracle functions and procedures on page 154. Using Oracle PL/SQL REF Cursors with Oracle Nested Tables, in Oracle functions and procedures An Oracle REF Cursor is an Oracle data type that contains a cursor value. ObjectStudio 8.x supports the use of Oracle REF cursors in the following: Oracle functions Oracle procedures Oracle REF Cursors can be useful, within an Oracle function or procedure, for returning the pointer to the result sets. See Example 2 in the topic Code sample for retrieving Oracle Nested Tables and for using Oracle REF Cursors in Oracle functions and procedures on page 154. Database User s Guide, P Chapter: 6. Oracle Section: Support for Oracle Nested Tables and Oracle PL/SQL REF Cursors

154 Code sample for retrieving Oracle Nested Tables and for using Oracle REF Cursors in Oracle functions and procedures This Workspace script contains the following examples: Example 1: Retrieve Oracle Nested Table information in two alternative ways Example 2: Use PL/SQL REF Cursors in Oracle functions and procedures See below: "Log on to the Oracle server." ret := OracleDatabase logonserver: #OracleDB user: #username password: #pwd alias: #OracleDB. "Access the database." db := OracleDatabase accessname: #oracledb. "Example 1: Retrieve Oracle Nested Table information in two alternative ways." "This SQL statement will SELECT the department s number and name, as well as the names of all employees working for that specific department." sqlstring := ' SELECT d.deptno, d.dname, CURSOR(SELECT e.ename FROM scott.emp e WHERE e.deptno = d.deptno ) emps FROM scott.dept d'. "Get the Oracle Nested Table s information all at once. To do this, use the execsql: method to return the information, taken from the referenced Oracle Nested Table, in an ObjectStudio table." tab := db execsql: sqlstring. Database User s Guide, P Chapter: 6. Oracle Section: Support for Oracle Nested Tables and Oracle PL/SQL REF Cursors

155 "Get the Oracle Nested Table s information row-by-row. To do this, use a forward-only cursor to return a cursor for the referenced Oracle Nested Table. You can then process the records row-by-row." cur := db privateopencursorsql: sqlstring. [ (row := cur next) isnilorempty ] whilefalse: [ ('Dept Number : ' + (row at: #DEPTNO)) out. ('Dept Name : ' + (row at: #DNAME)) out. cur1 := row at: #EMPS. cur1 out. [ (row1 := cur1 next) isnilorempty ] whilefalse: [ (' Employee Name : ' + (row1 at: #ENAME)) out. ]. ]. "Close the REF Cursor." cur1 close. "Close the Cursor." cur close. Database User s Guide, P Chapter: 6. Oracle Section: Support for Oracle Nested Tables and Oracle PL/SQL REF Cursors

156 "Example 2: Use PL/SQL REF Cursors in Oracle functions and procedures." "Create a package." res := db execsql: 'create or replace package types as type cursortype is ref cursor; end; '. "Create a test function that will get employee names and employee numbers from table scott.emp." res := db execsql: 'create or replace function fn_listemp return types.cursortype as l_cursor types.cursortype; begin open l_cursor for select ename, empno from scott.emp order by ename; return l_cursor; end; '. "Create test procedure 1. This procedure will get employee names and employee numbers from table scott.emp." res := db execsql: 'create or replace procedure getemps( p_cursor in out types.cursortype ) as begin open p_cursor for select ename, empno from scott.emp order by ename; end; '. Database User s Guide, P Chapter: 6. Oracle Section: Support for Oracle Nested Tables and Oracle PL/SQL REF Cursors

157 "Create test procedure 2. This procedure will get employee names and employee numbers, for a specific department, from table scott.emp." res := db execsql: 'create or replace procedure getemps_1( deptid int, emps in out types.cursortype ) as begin open emps for select ename, empno from scott.emp where deptno = deptid; end; '. "Invoke the test function." res := db execfunc: 'fn_listemp' returntype: #REFCURSOR paramtypes: {}. "Invoke test procedure 1." res := db execproc: 'getemps(:1)' paramtypes: { #REFCURSOR }. "Invoke test procedure 2." res := db execproc: 'getemps_1(30, :1)' paramtypes: { #REFCURSOR }. Array fetch ObjectStudio uses the array fetch Oracle optimization for the execsql: and loadsql: methods. For each fetch call made by ObjectStudio, array fetch allows Oracle to pass multiple rows across the network, thereby reducing network flows. Set the number of rows to return with the OracleDatabase setarrayfetchsizeto: instance method. The default size used by ObjectStudio is 1. Using higher values requires more memory allocation to handle the processing of execsql: and loadsql: messages, but it can increase performance. Database User s Guide, P Chapter: 6. Oracle Section: Array fetch

158 Prefetching rows Introduction to prefetching rows The Oracle database wrapper supports prefetching rows. When you prefetch rows, you force the Oracle client to retrieve multiple table rows in each fetch, from the Oracle server. Prefetching rows is similar to array fetching. Like array fetching, prefetching rows has the advantage of reducing network overhead, as well as potentially improving application performance. However, prefetching rows differs from array fetching, in that prefetching rows occurs within the Oracle client. Appropriately allocating memory for prefetching rows To appropriately allocate memory for prefetching rows, you must set the Oracle connection attribute OCI_ATTR_PREFETCH_ROWS to a desired number of rows. To set this attribute, use the method OracleDatabase>>prefetchRows. You can set this attribute at any time after the connection to the Oracle server has been established. As an example, to set the attribute OCI_ATTR_PREFETCH_ROWS to 1000 rows, for an OracleDatabase instance named db, you would use the following code: db prefetchrows: The Oracle client determines the amount of memory allocated for prefetching rows by multiplying the number of rows to which you set OCI_ATTR_PREFETCH_ROWS by the row memory size. Database User s Guide, P Chapter: 6. Oracle Section: Prefetching rows

159 Workspace example for prefetching rows Explanation of the Workspace example for prefetchrows The Workspace example, located later in this section, demonstrates the performance improvements that occur when you use the method OracleDatabase>>prefetchRows. To accomplish this, the example does the following: Sets up the connection to the Oracle server. See the code under these comments: "Logon to the Oracle Server." "Get the Oracle database instance." Creates and populates a test table ( TESTTABLE ) containing 2000 rows. See the code under these comments: "Drop the test table, if it exists." "Create a test table." "Specify the SQL used to perform the insert." "Set the number of records being inserted." "Populate the table." "Print out the milliseconds spent." Prepares for the prefetching demonstrations. See the code under these comments: "Set the number of times to repeat." "Set the SQL that will perform the fetch." Performs prefetching demonstration #1, with prefetchrows set to 1. See the code under these comments: "Set prefetchrows to 1 (Default value; same as having prefetching disabled.)" "Read all table records, with prefetchrows set to 1." "Print out the milliseconds spent, with prefetchrows set to 1." Database User s Guide, P Chapter: 6. Oracle Section: Prefetching rows

160 Performs prefetching demonstration #2, with prefetchrows set to 100. See the code under these comments: "Set prefetchrows to 100." "Read all table records, with prefetchrows set to 100." "Print out the milliseconds spent, with prefetchrows set to 100." Performs prefetching demonstration #3, with prefetchrows set to See the code under these comments: "Set prefetchrows to 1000." "Read all table records, with prefetchrows set to 1000." "Print out the milliseconds spent, with prefetchrows set to 1000." Workspace code example for prefetchrows "Logon to the Oracle Server." OracleDatabase logonserver: #'OracleDB' user: #'username' password: #'pwd' alias: #'OracleDB'. "Get the Oracle database instance." db := Database accessname: #'OracleDB'. "Drop the test table, if it exists." db execsql: 'DROP TABLE TESTTABLE'. "Create a test table." db execsql: 'CREATE TABLE TESTTABLE( CID int, CNAME varchar2 (30) )'. "Set the number of records being inserted." loopcount := "Specify the SQL used to perform the insert." sql := 'INSERT INTO TESTTABLE VALUES (?,?)'. Database User s Guide, P Chapter: 6. Oracle Section: Prefetching rows

161 "Populate the table." inserttime := [ bindarray numarray stringarray numarray := Array new. stringarray := Array new. 1 to: loopcount do: [ :i numarray add: i. stringarray add: 'bla'. ]. bindarray := Array with: numarray with: stringarray. sql := 'INSERT INTO TESTTABLE VALUES (?,?)'. db execsql: sql vars: bindarray. ] millisecondstorun. "Print out the milliseconds spent." ('Insert using array binding: ' + inserttime) out. "Set the number of times to repeat." loopcount := 1. "Set the SQL that will perform the fetch." sql := 'SELECT * from TESTTABLE'. "Set prefetchrows to 1 (Default value; same as having prefetching disabled.)" db prefetchrows: 1. Database User s Guide, P Chapter: 6. Oracle Section: Prefetching rows

162 "Read all table records, with prefetchrows set to 1." selecttime1 := [ 1 to: loopcount do: [ :i db execsql: sql. ]. ] millisecondstorun. "Print out the milliseconds spent, with prefetchrows set to 1." ('Select with prefetchrows= 1: ' + selecttime1) out. "Set prefetchrows to 100." db prefetchrows: 100. "Read all table records, with prefetchrows set to 100." selecttime2 := [ 1 to: loopcount do: [ :i db execsql: sql. ] ] millisecondstorun. "Print out the milliseconds spent with prefetchrows set to 100." ('Select with prefetchrows=100: ' + selecttime2) out. "Set prefetchrows to 1000." db prefetchrows: "Read all table records, with prefetchrows set to 1000." selecttime3 := [ 1 to: loopcount do: [ :i db execsql: sql. ] ] millisecondstorun. "Print out the milliseconds spent, with prefetchrows set to 1000." ('Select with and prefetchrows=1000: ' + selecttime3) out. Database User s Guide, P Chapter: 6. Oracle Section: Prefetching rows

163 Using LOB proxies Introduction to using LOB proxies Formerly, if you wished to retrieve or modify LOB contents, you could use the Oracle wrapper to return Large Objects (CLOBs and BLOBs) only by value. However, returning LOBs by value is undesirable when you are accessing LOBs of significant size (for example, a few hundred MB or a few GB), since ObjectStudio has to load them into memory before they can be used. Therefore, in OS 8, you can now use the Oracle wrapper to return LOBs either by proxy or by value. LOB proxies enable you to deal with LOB locaters (LOB pointers). This section contains the Workspace code sample Using LOB insert/retrieval/write on page 164. Method for returning LOBs by proxy or by value Use the following method to return LOBs either by proxy or by value: OracleDatabase>>execSql: sqlstring answerlobasproxy: aboolean The parameters are the following: sqlstring. A SELECT statement whose result set may contain LOB columns. aboolean. Indicates whether you wish to receive LOB proxies or LOB values for the LOB columns. If true, LOB proxies will be returned. If false, LOB values will be returned. Processing LOBs after they have been returned by proxy After you return LOBs by proxy, you can use the methods in the VisualWorks OracleLobProxy class to process (retrieve or modify) them. For more information, refer to the VisualWorks documentation or browse the VisualWorks OracleLobProxy class. Database User s Guide, P Chapter: 6. Oracle Section: Using LOB proxies

164 Using LOB insert/retrieval/write The following sample Workspace code demonstrates LOB insert/retrieval/write: db sqlstring vars res recs rec clobproxy blobproxy clob blob cloblength bloblength "Logon to DB." OracleDatabase logonserver: #'DBname' user: #'userid' password: #'pwd' alias: #'DBname'. db := Database accessname: #'DBname'. "Create a table containing LOB columns." db execsql: 'CREATE TABLE TestLob (A CLOB, B BLOB, C INTEGER)'. "Inserts." sqlstring := 'INSERT INTO TestLob(A, B, C) VALUES (?,?,?)'. vars := Array with:(string new: 1000 withall: $a) with: (ByteArray new: 1000 withall: 1) with: 1. res := db execsql: sqlstring vars: vars. "Retrieve LOB as values." res := db execsql: 'select * from testlob where c=1' answerlobasproxy: false. "Retrieve LOB as proxies." res := db execsql: 'select * from testlob where c=1' answerlobasproxy: true. recs := res records. rec := recs at: 1. clobproxy := rec at: 1. blobproxy := rec at: 2. "Gets the length and value of the CLOB." clobproxy getloblength inspect. clobproxy readall inspect. Database User s Guide, P Chapter: 6. Oracle Section: Using LOB proxies

165 "Gets the length and value of the BLOB." blobproxy getloblength inspect. blobproxy readall inspect. "Modify/change LOBs. It must happen inside a transaction." db begintran. res := db execsql: 'select a, b from testlob where c=1 for update' answerlobasproxy: true. recs := res records. rec := recs at: 1. clobproxy := rec at: 1. blobproxy := rec at: 2. "Gets the length and value of the CLOB before the change." clobproxy getloblength inspect. clobproxy readall inspect. "Gets the length and value of the BLOB before the change." blobproxy getloblength inspect. blobproxy readall inspect. cloblength := 500. bloblength := 500. clob := String new: cloblength withall: $e. blob := ByteArray new: bloblength withall: 0. Database User s Guide, P Chapter: 6. Oracle Section: Using LOB proxies

166 "Change the first 500 elements." clobproxy writefrom: 1 with: clob asbytearray. blobproxy writefrom: 1 with: blob. "Commit the changes." db commit. "You may rollback the changes too." "db rollback." "Gets the length and value of the CLOB after the change." clobproxy getloblength inspect. clobproxy readall inspect. "Gets the length and value of the BLOB after the change." blobproxy getloblength inspect. blobproxy readall inspect. Database User s Guide, P Chapter: 6. Oracle Section: Using LOB proxies

167 Making adjustments to improve LOB performance Introduction to making adjustments to improve LOB performance You may be able to improve LOB performance in two ways: Changing the size of the LOB buffer Changing the size of the returned LOB values This section contains the Workspace code sample Example for changing the LOB buffer size and changing the size of returned LOB values on page 168. Changing the size of the LOB buffer Based on the size of the LOB values you are processing, you may wish to change the size of the LOB buffer. This buffer is used for copying data between the server and your application, and its default size is 32K. If the LOB values you are processing are small, decreasing the buffer size may save memory. If the LOB values you are processing are large, increasing the buffer size may minimize number of network round trips required to get the desired data. The size of the LOB buffer is controlled by the lobbuffersize instance variable. Use the following method to reset this variable: OracleDatabase>> lobbuffersize: Changing the size of the returned LOB values You may be able to improve performance by changing the size of the returned LOB values. The default size is 4000 bytes. If you want entire LOB values to be retrieved, just set this instance variable to a value greater than the size of your biggest LOB. The size of the returned LOB values is controlled by the lobvaluesize instance variable. Use the following method to reset this variable: OracleDatabase>> lobvaluesize: Database User s Guide, P Chapter: 6. Oracle Section: Making adjustments to improve LOB performance

168 Example for changing the LOB buffer size and changing the size of returned LOB values The following Workspace code sample shows how to change the LOB buffer size and how to change the size of the returned LOB values. It also demonstrates the effects of these changes: "Logon to an Oracle database." Ret := OracleDatabase logonserver: #OracleDB user: #username password: #password alias: #OracleDB. "Get the database instance." DB := Database accessname: #OracleDB. "Create a test table." Res := DB execsql: 'CREATE TABLE TestLob (a CLOB, b BLOB, c INT)'. "Change LOB buffer size." DB lobbuffersize: "Create the LOB values to be inserted." ClobLength := BlobLength := ClobInput := String new: ClobLength withall: $a. BlobInput := ByteArray new: ClobLength withall: 1. "Starts a transaction." DB begintran. "Input the test data." Res := DB execsql: 'INSERT INTO TestLob (a, b, c) VALUES (?,?,?)' vars: (Array with: ClobInput with: BlobInput with: 2). "Commits the transaction." DB commit. Database User s Guide, P Chapter: 6. Oracle Section: Making adjustments to improve LOB performance

169 "Starts a new transaction." DB begintran. "Retrieve 200 byes of data." DB lobvaluesize: 200. "Change LOB buffer size." DB lobbuffersize: 200. "Get LOB values directly." Res := DB execsql: 'select * from testlob' answerlobasproxy: false. Recs := Res records. Rec1 := Recs at: 1. "Verify the retrieved LOB values and their sizes." Clob := Rec1 at: 1. Clob size. Blob := Rec1 at: 2. Blob size. "Get the values of entire LOBs." DB lobvaluesize: "Change LOB buffer size." DB lobbuffersize: Database User s Guide, P Chapter: 6. Oracle Section: Making adjustments to improve LOB performance

170 "Get LOB proxies." Res := DB execsql: 'select * from testlob' answerlobasproxy: true. Recs := Res records. Rec1 := Recs at: 1. "Verify the length and the size of the retrieved LOB values." Clob := Rec1 at: 1. Clob getloblength. ClobValue := Clob readall. ClobValue size. Blob := Rec1 at: 2. Blob getloblength. BlobValue := Blob readall. BlobValue size. "Rollback the transaction." DB rollback. "Cursor Usage." DB begintran. Database User s Guide, P Chapter: 6. Oracle Section: Making adjustments to improve LOB performance

171 "Get LOBs as values. We reset the default size to get the whole LOBs." DB lobvaluesize: "Change LOB buffer size." DB lobbuffersize: "Get LOBs as values." Cur := DB opencursorsql: 'select * from testlob' forupdateof: {} answerlobasproxy: false. Val1 := Cur next. "Verify the retrieved LOB values and their sizes." Clob := Val1 at: #A. Clob size. Blob := Val1 at: #B. Blob size. "Close the cursor." Cur close. "Get LOBs as proxies." Cur := DB opencursorsql: 'select * from testlob' forupdateof: {} answerlobasproxy: true. Val1 := Cur next. Clob := Val1 at: #A. "Get LOB length. It should be " Clob getloblength. Database User s Guide, P Chapter: 6. Oracle Section: Making adjustments to improve LOB performance

172 "Read the LOB and verify its size. It should be 4000 bytes." ClobValue := Clob readall. ClobValue size. Blob := Val1 at: #B. "Get LOB length." Blob getloblength. "Read the LOB and verify its size. It should be 4000 bytes." BlobValue := Blob readall. BlobValue size. "Close the cursor." Cur close. "Using scrollable cursors, get LOBs as values. We reset the default size to 200 bytes and the LOB buffer to 1024 bytes." "Retrieve 200 byes of data." DB lobvaluesize: 200. "Change LOB buffer size." DB lobbuffersize: Cur := DB openscrollablecursorsql: 'select * from testlob' forupdateof: {} answerlobasproxy: false. Val1 := Cur next. Database User s Guide, P Chapter: 6. Oracle Section: Making adjustments to improve LOB performance

173 "Read the LOB and verify its size. It should be 200 bytes." Clob := Val1 at: #A. Clob size. Blob := Val1 at: #B. Blob size. "Close the cursor." Cur close. "Get LOBs as proxies." Cur := DB openscrollablecursorsql: 'select * from testlob' forupdateof: {} answerlobasproxy: true. Val1 := Cur next. "Get LOB length. It should be " Clob := Val1 at: #A. Clob getloblength. Database User s Guide, P Chapter: 6. Oracle Section: Making adjustments to improve LOB performance

174 "Read the LOB and verify its size. It should be 200 bytes." ClobValue := Clob readall. ClobValue size. "Get LOB length. It should be " Blob := Val1 at: #B. Blob getloblength. "Read the LOB and verify its size. It should be 200 bytes." BlobValue := Blob readall. BlobValue size. "Close the cursor." Cur close. "Rollback the transaction." DB rollback.... Database User s Guide, P Chapter: 6. Oracle Section: Making adjustments to improve LOB performance

175 Using statement caching Introduction to using statement caching Since Oracle 9.2, Oracle has included a feature called statement caching. Statement caching provides and manages a cache of statements for each session. In the server, this means that cursors are ready to be used without the need to parse the statement again. Using it will improve performance and scalability. To use statement caching, users first perform the usual steps to logon. They then indicate that statement caching should be enabled. The statement cache will initially be empty. The OCI will attempt to find a statement in the cache, using the statement text. If the statement exists, the API will return a previously prepared statement handle. Otherwise, the API will return a newly prepared statement handle. The statement caching feature is useful when you execute the same SQL statement multiple times. By using this feature, an existing prepared statement handle will be reused, thus improving performance. This section contains the Workspace code sample Turning on statement caching on page 176. Database User s Guide, P Chapter: 6. Oracle Section: Using statement caching

176 Turning on statement caching For a demonstration of turning on statement caching in the ObjectStudio 8.x, see the following sample Workspace code: "The default is not to use statement caching." OracleDatabase usestatementcaching. "Have to be set before a connection is established" OracleDatabase usestatementcaching: true. OracleDatabase logonserver: #'OracleDB' user: #'userid' password: #'pwd' alias: #'oracledb'. "Get the Oracle database instance." DB := Database accessname: #OracleDB. "Default cache size is 20." DB getstatementcachesize. "Set cache size to 30." DB setstatementcachesize: 30. "Verify the new cache size." DB getstatementcachesize.... Note that in order for statement caching to take effect, you must set usestatementcaching to true before logging on to the Oracle server. Database User s Guide, P Chapter: 6. Oracle Section: Using statement caching

177 7. Sybase Introduction The Sybase wrapper is now available in ObjectStudio 8.x. For ObjectStudio 8.x, the Sybase wrapper makes use of the VisualWorks Sybase CTLibEXDI. All commands are sent to the Sybase Open Client Library through the VisualWorks CTLibEXDI. Since scrollable cursor support is only available from Sybase 15.0 or later, the default behavior of Sybase Open Client is set to version If you are not using Sybase 15.0 or later, you should run the following code in the Workspace or in your program before connecting to a Sybase server: SybaseDatabase setbehaviortoversion125 Note that if you do this, scrollable cursors will not be supported. All cursors will be forward-only. Database User s Guide, P Chapter: 7. Sybase Section: Introduction

178 What s new in the ObjectStudio 8.x Sybase database wrapper Here are the highlights of the new Sybase database wrapper: In ObjectStudio 8.x, the specific operations necessary to support Sybase databases are transparently sent through the VisualWorks CTLibEXDI to the Sybase Open Client Library. This means that, unlike in Classic ObjectStudio, there is no C code in the wrapper and there are no ObjectStudio DLLs serving as a bridge between the Smalltalk code and the database client libraries. The new Sybase database wrapper will now work with all Sybase client versions, as long as the library files (libsybcs.dll and libsybct.dll) are in an accessible folder whose path is specified by the PATH environment variable. Compared with Classic ObjectStudio s Sybase database wrapper, ObjectStudio 8.x s Sybase wrapper has much better support for stored procedure execution and host variable handling. Because the ObjectStudio 8.x Sybase database wrapper contains only Smalltalk code, which is transparent to users, you can easily add new features. Connecting to a Sybase server There are two ways to logon to a Sybase server: Use the Sybase Logon window. This window will open after you load the Sybase OpenClient application from the Applications window. Logon programmatically. Use the following logon method: SybaseDatabase>>logOnServer: user: password: Consider the following example: SybaseDatabase logonserver: #SybaseServerName user: #OStudio password: #test. Database User s Guide, P Chapter: 7. Sybase Section: Connecting to a Sybase server

179 Using Sybase default client password encryption The ObjectStudio 8.x Sybase database wrapper supports Sybase s default client password encryption. You can choose to enable or disable this feature. By default, it is disabled. Client password encryption is a "before" attribute of the connection. That is, you must set it before the connection to the database server is established. In ObjectStudio 8.x, if you want to use client password encryption, you must set usepasswordencryption to be true before logging on to the Sybase server. The following code samples demonstrate how to check the value of Sybase s default client password encryption attribute, and how to change this attribute s value: "Check the default value, which is false." SybaseDatabase usepasswordencryption. "Set the value to true." SybaseDatabase usepasswordencryption: true. "Again check the value, which should be true." SybaseDatabase usepasswordencryption. "Connect to the Sybase server." SybaseDatabase logonserver: #sybaseserver user: #username password: #pwd. "Get the database instance." DB := SybaseDatabase accessname: #sybasedb. "Check the value from a database instance, which should be 1." DB getpasswordencryptionstatus. Table information loaded when you access a Sybase database After logon, the SybaseDatabase instance will contain the Sybase tables returned by calling Sybase procedure sp_tables without arguments. Database User s Guide, P Chapter: 7. Sybase Section: Using Sybase default client password encryption

180 Sybase wrapper functionality example This section contains a code sample demonstrating the functionality of the Sybase wrapper. For more information, browse the Sybase wrapper classes: SybaseDatabase SybaseDatabaseCursor SybaseScrollableCursor SybaseTable A complete code example The following Workspace code sample shows you how to logon to a Sybase server, create a test table, and insert some test data. It also demonstrates the use of cursors and scrollable cursors: db sqlstring testcursor testscursor "Logon to the database server." SybaseDatabase logonserver: #DBServerName user: #username password: #password. "Get access to the database needed." db := SybaseDatabase accessname: #DBName. "Create a test table." db execsql: 'CREATE TABLE TestTable (cid int primary key, cname varchar(100))'. Database User s Guide, P Chapter: 7. Sybase Section: Sybase wrapper functionality example

181 "Insert test data into the test table." sqlstring := 'INSERT INTO TestTable VALUES ('. 1 to: 10 do: [ :i cid cname sql cid := i asstring. cname := 'test' + cid. sql := sqlstring + cid + ',' + cname asdbstring +')'. db execsql: sql. ]. "Retrieve the data from the test table." db execsql: 'SELECT * FROM TestTable'. "Create a non-scrollable cursor." testcursor := db opencursorselect:{#cid #cname} from:{#testtable} continuation:'order BY cid'. "Get the first row, print to Transcript." testcursor next out. "Close the cursor." testcursor close. "Create a scrollable cursor." testscursor := db openscrollablecursorselect:{#cid #cname} from:{#testtable} continuation:'order BY cid'. Database User s Guide, P Chapter: 7. Sybase Section: Sybase wrapper functionality example

182 "Get the first row, print to Transcript." testscursor next out. "Get the second row, print to Transcript." testscursor next out. "Go back to the first row, print to Transcript." testscursor previous out. "Close the cursor." testscursor close. "Logoff from the database server." SybaseDatabase logoff. Database User s Guide, P Chapter: 7. Sybase Section: Sybase wrapper functionality example

183 Variables in queries To execute a query containing one or more query variables, the database instance must first be given an input template object, which will be used to satisfy the variables in the query. The method by which values are obtained from the input template depends on the form of the query variable. If the input variable is a question mark, then the input template must either have indexed variables or instance variables. The first template variable will be used to satisfy the value for the first query variable, the second template variable will be used to satisfy the second query variable, and so on. The following sample Workspace code demonstrates the use of query variables: db "Logon to the database server." SybaseDatabase logonserver: #DBServerName user: #username password: #password. "Get access to the database needed." db := SybaseDatabase accessname: #DBName. "Insert a new row to the test table." db execsql: 'INSERT INTO TestTable VALUES (?,?)' vars: {16 'test16'}. "Retrieve the row back." db execsql: 'SELECT * FROM TestTable WHERE cid=?' vars: {16 }. "Update the row using question marks. Please pay attention to the order of the binding values." db execsql: 'UPDATE TestTable SET cname =? WHERE cid=?' vars: {'test17' 16 }. Database User s Guide, P Chapter: 7. Sybase Section: Variables in queries

184 "Verify the change." db execsql: 'SELECT * FROM TestTable WHERE cid=?' vars: {16 }. "Update the row again using a colon followed immediately by a number. Again, pay attention to the order of the binding values." db execsql: 'UPDATE TestTable SET cname = :2 WHERE cid= :1' vars: {16 'test18'}. "Verify the change again." db execsql: 'SELECT * FROM TestTable WHERE cid=?' vars: {16 }. "Logoff from the database server." SybaseDatabase logoff. Database User s Guide, P Chapter: 7. Sybase Section: Variables in queries

185 Creating and invoking Sybase stored procedures The following sample Workspace code demonstrates how to create and invoke Sybase stored procedures: db res sqlobj vars sqlstring "Logon to the database server." SybaseDatabase logonserver: #'sybasedb' user: #'userid' password: #'pwd'. "Get access to the database needed." db := SybaseDatabase accessname: #sybasedb. "Create a test table." db execsql: 'CREATE TABLE TestTable (cid int primary key, cname varchar(100))'. "Insert test data into the test table." sqlstring := 'INSERT INTO TestTable VALUES ('. 1 to: 10 do: [ :i cid cname sql cid := i asstring. cname := 'test' + cid. sql := sqlstring + cid + ',' + cname asdbstring +')'. db execsql: sql. ]. Database User s Guide, P Chapter: 7. Sybase Section: Creating and invoking Sybase stored procedures

186 "Create a simple stored procedure." res := db execsql: 'CREATE PROCEDURE testprocedure1 AS SELECT * FROM TestTable'. "Invoke the stored procedure." sqlobj := 'testprocedure1'. res := db execproc: sqlobj. "Create a stored procedure with parameters." res := db execsql: 'CREATE PROCEDURE VARCHAR(20) AS SELECT * FROM TestTable WHERE cname "Invoke the stored procedure." sqlobj := 'testprocedure2 :1'. vars := {'test2' }. res := db execproc: sqlobj params: vars. "Create a stored procedure with parameters and a return value." res := db execsql: 'CREATE PROCEDURE VARCHAR(20) AS SELECT * FROM TestTable WHERE cname RETURN 1'. "Invoke the stored procedure." sqlobj INT = testproc3 vars := {'test2' }. res := db execproc: sqlobj params: vars. Database User s Guide, P Chapter: 7. Sybase Section: Creating and invoking Sybase stored procedures

187 "Create a more complicated stored procedure with INPUT, OUTPUT parameters and a return value, plus a result set." res := db execsql: 'create procedure int varchar(30) output as select * from TestTable where cname return 2'. "Invoke the stored procedure." sqlobj varchar(30) = testprocedure4 :1, output as status'. vars := {'test9' 10 }. res := db execproc: sqlobj params: vars. Database User s Guide, P Chapter: 7. Sybase Section: Creating and invoking Sybase stored procedures

188 8. Database Notebook Introduction This chapter describes the Database Notebook, which provides access to all databases, both internal and external. With the Database Notebook, you can: Create a database, create and modify a table, and save Internal Database changes Enter data Manage data Create SQL queries Database User s Guide, P Chapter: 8. Database Notebook Section: Introduction

189 Using the Database Notebook This section describes: Database Notebook pop-up menu Creating a new database Creating and modifying a table Saving changes to the Internal Database Database Notebook pop-up menu Press mouse button 2 on the background of the Database Notebook page to display the Database Notebook pop-up menu. The following table describes the options on the Database Notebook pop-up menu: Option Refresh Help SQL Browser SQL Window Create Database Drop Database Create Table Commit Rollback Allows you to Update the display of the Database Notebook if you have made changes. Open ObjectStudio Help files. Open the SQL Queries dialog box (SQL Browser) to create a new query or to edit, execute, or display existing queries. Open the SQL Window, which allows you to type SQL queries directly into the window. Use the Create Database dialog box to create a new external database. Remove the selected database from the Database Notebook. Open the Table Name Entry Form dialog box to create a new table in the current database. Commit a database transaction that has been entered. Roll back database transactions and return the database to its state when it was accessed or its state after the last commit. Database User s Guide, P Chapter: 8. Database Notebook Section: Using the Database Notebook

190 Creating a new database To create a new database: 1. Select Tools Database Notebook from the Desktop menu. The Database Notebook opens, as shown here: For each external database that is loaded, a tab appears at the bottom of the notebook page. 2. Press mouse button 2 on the background of the Database Notebook page to display the Database Notebook pop-up menu. 3. Select Create Database from the Database Notebook pop-up menu. The Create Database dialog box displays. Capabilities of the Internal Database. Although you cannot create new databases with the Internal Database, you can create, modify, and delete tables. You can also create, modify, delete, preview, and print data. Database User s Guide, P Chapter: 8. Database Notebook Section: Using the Database Notebook

191 4. Select the type of database you want to create from the Select database type drop-down list box. 5. Enter the database name in the Name entry field. Additional data entry. Depending on the options available for the selected database type, ObjectStudio may give you the chance to enter drive information and an optional comment. 6. Enter a drive specification in the Drive entry field. 7. Enter a comment in the Comment entry field. 8. Click OK to close the Create Database dialog box. A tab for the new database appears along the bottom of the Database Notebook. Privileges for database creation. You must have appropriate privileges for your DBMS before you can create a database using ObjectStudio. Database User s Guide, P Chapter: 8. Database Notebook Section: Using the Database Notebook

192 Creating and modifying a table The Database Notebook allows you to create new tables with the Table Definition dialog box. ObjectStudio dynamically creates this dialog box, depending on the field types and attributes supported by your underlying database. The ability to enter comments, field lengths, and so on, depends on the underlying database and the selected field type. The Internal Database will be used for illustration in this section. Internal Database The Internal Database displays the following field types on the Table Definition dialog box: Symbol String (default length 20) Number SmallInteger LongInteger Float Object Decimal (default length 8, decimal places 2) Boolean Date Time Timestamp field The Internal Database displays the following attributes on the Table Definition dialog box: Computed Mandatory Unique Key Database User s Guide, P Chapter: 8. Database Notebook Section: Using the Database Notebook

193 Table pop-up menu Press mouse button 2 on the background of the Table Notebook page to display the Table pop-up menu. The following table describes the options on the Table pop-up menu: Option Open Help Create Table Edit Table Drop Table Data Entry Data Manager Data Manager Form Allows you to Open the SQL Result window to view all records in the table. Open ObjectStudio Help files. Display the Table Name Entry Form dialog box to create a table in the current database. Open the Table Definition dialog box to display and edit the table definition. Remove the selected table from the database. Open the Data Entry dialog box to add new records to the database. Display a default Data Manager dialog box for the table. Load the default Data Manager form for the current table into the Designer. Database User s Guide, P Chapter: 8. Database Notebook Section: Using the Database Notebook

194 Creating a new table To create a new table: 1. Select Tools Database Notebook to open the Database Notebook. 2. Select the database in which to create the table by clicking the appropriate tab along the bottom of the Notebook window. 3. Press mouse button 2 on the background of the Database Notebook page to display the Database Notebook pop-up menu. 4. Select Create Table from the pop-up menu. The Table Name Entry dialog box displays, as shown here: 5. Type a name in the Table name entry field. Database User s Guide, P Chapter: 8. Database Notebook Section: Using the Database Notebook

195 6. Click OK. The Table Definition dialog box opens. 7. Create a field: A. Type a field name in the Field name entry field. B. Select a field type from the Types list box. C. Select an attribute from the Attributes list box, if necessary. D. If comment, length, and/or decimal places fields appear, enter the appropriate information. E. Click Add to save the information. F. Repeat steps A E to define all of the fields in the table. 8. Click Save to create the table and close the Table Definition dialog box. Database User s Guide, P Chapter: 8. Database Notebook Section: Using the Database Notebook

196 Modifying an entry To modify an existing entry: 1. Select the entry that you want to modify. 2. Type new information in the appropriate entry field. 3. Click Modify to enter the new information. Deleting a field To delete a field, select the field and click Delete. Saving changes to the Internal Database Unlike when working with an external database, changes made to the Internal Database are not saved to the disk automatically. Saving the database If you change the Internal Database structure or add data and you want to save those changes permanently, save the ObjectStudio image file as described in the ObjectStudio User s Guide, P Saving tables To save changes to an individual Internal Database table, publish your class to a Store repository, or to a parcel file. The next time you run ObjectStudio, load the class using the appropriate method described in the ObjectStudio User s Guide, P Image saving not recommended for Internal Database data storage. When you save an ObjectStudio image, ObjectStudio saves data, recorded in the Internal Database, in the ObjectStudio image file. Because table data changes frequently, but is saved only when you save the ObjectStudio image, Cincom does not recommend this method of data storage. Database User s Guide, P Chapter: 8. Database Notebook Section: Using the Database Notebook

197 Entering data The Database Notebook dynamically creates a default data entry form for each table available to the system. This form only allows you to add records. You cannot use it to edit or delete data. For more information, see Managing data on page 199. Accessing the default data entry form To access the default data entry form for a table: 1. Select Tools Database Notebook to open the Database Notebook. 2. Use the notebook tabs and/or the arrow tabs to display the appropriate table, as shown here: 3. Press mouse button 2 outside the white display area to display the Table pop-up menu for the selected page. Database User s Guide, P Chapter: 8. Database Notebook Section: Entering data

198 4. Select Data Entry from the Table pop-up menu to display the Data Entry dialog box. The following illustration shows the Data Entry dialog box for the Employee table of the Internal Database: You can type new information in any of the entry fields. Blank button. You can clear the entry fields by clicking the Blank button. 5. To navigate through the database: A. Press the TAB key to move from field to field. B. Click Next to display the next record. Click Previous to go back to a previous record. 6. Click Enter to enter the record into the database. Additional step if the database supports transaction processing. If the underlying database supports transaction processing, commit the changes to the database by clicking the Commit button. 7. Click Close when you are finished entering data. Database User s Guide, P Chapter: 8. Database Notebook Section: Entering data

199 Customizing the Data Entry dialog box You can select Data Entry Form from the Table pop-up menu to build the default data entry form for the displayed table and load it into the Designer. This feature eliminates the need to create your own data entry form and allows you to customize and save the form. For example, you may want to modify the form to include error checking and to provide default values. These changes then are available whenever you access the form. For more information on using the Designer, refer to the ObjectStudio User Interface Guide, P Managing data The Database Notebook dynamically creates a default Data Manager form for each table available to the system. Unlike the Data Entry dialog box, which only allows you to add records, the Data Manager allows you to enter new records, edit or delete existing records, and preview and print data. Opening the default Data Manager You can open the Data Manager from the SQL Browser, the Database Notebook, or the SQL Editor. If you open it from the Database Notebook, the system makes the entire contents of the table available to you. If you open it from the SQL Browser or SQL Editor, the system limits access to the results of the active query. To open the default Data Manager for a table: 1. Select Tools Database Notebook to open the Database Notebook. 2. Use the notebook tabs and/or the arrow tabs to display the appropriate table. 3. Press mouse button 2 to display the Table pop-up menu for the selected page. Database User s Guide, P Chapter: 8. Database Notebook Section: Managing data

200 4. Select Data Manager from the Table pop-up menu to display the Data Manager dialog box. The following illustration shows the Data Manager for the Employee table of the Internal Database: You can type new information in any of the entry fields. 5. Do one of the following: Click New to create a new record in the table. Click Next to go to the next record, or click Previous to go back to a previous record. Click Refresh to return the record to its original state if you decide that you do not want to make changes to the record. Click Select to open the Data Manager Selection dialog box for the current table. Double-click the record that you want to edit and click Close to return to the Data Manager. 6. Click Save to save any changes. 7. Select File Exit to close the Data Manager dialog box. Database User s Guide, P Chapter: 8. Database Notebook Section: Managing data

201 Customizing the Data Manager Form Select Data Manager Form from the Table pop-up menu to build the default Data Manager form for the displayed table and load it into the ObjectStudio Designer. This feature eliminates the need to create your own data management form and allows you to customize and save the form. For example, you may want to modify the form to include error checking and to provide default values. These changes then are available whenever you access the form. After publishing your changes, you can load it into ObjectStudio and use it in your application. Database User s Guide, P Chapter: 8. Database Notebook Section: Managing data

202 Creating a SQL query ObjectStudio provides two ways to create queries in the Database Notebook. You can use: SQL tools - SQL Editor - SQL Window SQL Browser Using the SQL tools The SQL tools include the SQL Editor and the SQL Window. SQL Editor The SQL Editor features a point-and-click interface to help you create SQL statements embedded in Smalltalk class files. You can create parametric queries and assign the return value of a Smalltalk statement or the current value of an entry field as the parameter. Once you create these queries, you can incorporate them into your applications. You can access the SQL Editor from the SQL Browser or from the ObjectStudio Desktop (File New Query). SQL Window The SQL Window allows you to create quick, text-based queries for prototyping and testing purposes. You can save, load, and execute these queries in the SQL Window, or you can export them as text files to use in other applications. You can access the SQL Window from the Database Notebook or from the ObjectStudio Desktop (Tools SQL Window). Database User s Guide, P Chapter: 8. Database Notebook Section: Creating a SQL query

203 Using the SQL Browser The SQL Browser allows you to create and edit SQL queries. You can also display query results and access the Data Manager. When you access the SQL Browser from the Database Notebook, ObjectStudio assumes that you want to query the currently displayed database. The following table describes the buttons on the SQL Browser: Button Edit Display Data Manager Data Manager Form Create Allows you to Open the SQL Editor and edit the selected query. Display the SQL Result Display with results of the query. You can save the results in an ASCII or a delimited file. Display a default Data Manager dialog box for the table. Load the default Data Manager form for the current table into the Designer. Open the SQL Editor to create a new query. To open the SQL Browser from the Database Notebook: 1. Select Tools Database Notebook from the ObjectStudio Desktop menu. The Database Notebook displays. 2. Select the database that you want to query. 3. Press mouse button 2 on the background of the Database Notebook page to open the Database Notebook pop-up menu. Database User s Guide, P Chapter: 8. Database Notebook Section: Creating a SQL query

204 4. Select SQL Browser from the Database Notebook pop-up menu. The SQL Queries dialog box opens, as shown here: 5. Click Create to create a new query. 6. Click Close to close the SQL Queries dialog box. Database User s Guide, P Chapter: 8. Database Notebook Section: Creating a SQL query

205 9. SQL tools Introduction SQL Editor This chapter describes two ObjectStudio tools that enable you to create SQL statements: SQL Editor SQL Window The SQL Editor allows you to: Create SQL statements by using ObjectStudio s point-and-click interface, or by typing statements directly Verify SQL statements before they are executed Execute SQL statements and view the results in the SQL Editor Create parametric queries and associated Smalltalk statements that allow you to base queries on information available at run time Set the SQL Editor to commit database changes automatically or manually Save SQL statements as Smalltalk class files for inclusion in your applications Import and export SQL statements as text files for reuse in the SQL Editor or SQL Window You can use the SQL Editor s point-and-click options to specify the elements of an SQL statement. ObjectStudio then constructs the SQL statement, which provides the correct syntax automatically. You also can type SQL statements directly into the editor. The SQL Editor provides a statement type (DIRECT) that permits you to do so. Database User s Guide, P Chapter: 9. SQL tools Section: Introduction

206 Creating an SQL statement To create an SQL statement: 1. Select File New Query from the Desktop menu to open the SQL Editor. You also can open the editor from the Database Notebook. For more information, see 8. Database Notebook on page 188. The SQL Editor displays, as shown here: The Selection dialog box also opens, as shown here: 2. Select a Type at the top of this box and define the type of query. For more information, see Using the Selection dialog box on page Select Actions Verify from the SQL Editor menu to validate the syntax of the statement. If the statement contains an error, correct the syntax and repeat this step. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

207 4. Select Actions Run Statement to execute the statement. 5. Select File Save to save the statement in a Smalltalk class file. You also can select File Export to text file to save the statement in a text file for later use. Another way to create a new SQL statement is to use the SQL Browser. See Using the SQL Browser on page 203. The following options are on the SQL Editor menu: File menu. The options on the File menu allow you to save queries and to import and export queries to and from a file. Statement menu. The options on the Statement menu correspond to SQL clauses, as described in the following table: Option Allows you to Section Selection Specify the type of SQL statement, including SELECT, INSERT, UPDATE, DELETE, and DIRECT, and to specify the database and table on which to base the statement. Using the Selection dialog box on page 209 Search condition Construct a WHERE clause. Defining a WHERE clause on page 219 Join condition Construct a WHERE clause as a Table Join. Defining a JOIN clause on page 221 Grouping Construct a GROUP BY clause. Defining a GROUP BY clause on page 223 Having Construct a HAVING clause. This option is also available as a button on the Grouping dialog box. Defining a HAVING clause on page 223 Order Construct an ORDER BY clause. Defining an ORDER BY clause on page 224 Values Construct a VALUES clause. This option is also available as a button on the Selection dialog box. Using the Selection dialog box on page 209 Parameters Create parametric SQL statements. Creating parametric SQL statements on page 225 Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

208 Actions menu. The Actions menu contains options to verify and run SQL statements. It also contains options to open the Report Editor and the Data Manager. For more information, see Executing a statement on page 218. Transactions menu. The options on the Transactions menu are available if the available external databases support transaction processing. The options allow you to commit and roll back SQL transactions. For more information, see Committing changes on page 227. Options menu. The Options menu allows you to select display options. Check marks appear next to the selected options. The following options are available: - Show database Displays the name of the database on which the statement is based. - Show status line Displays helpful information in the status line at the bottom of the form. - Word wrap Toggles the word wrap feature. Turning off word wrap places each clause on a separate line. Help menu. The Help menu contains options to get help about the SQL Editor and ObjectStudio. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

209 Using the Selection dialog box The Selection dialog box allows you to specify the statement type and define which database, tables, and columns to use. The Selection dialog box appears immediately if you are creating a new statement. If you are editing an existing statement, select Statement Selection from the SQL Editor menu (shown in Creating an SQL statement on page 230). Options on the Selection dialog box The following table describes the options on the Selection dialog box. Some of the options that appear depend on the type of SQL statement that you are creating. Option Type radio buttons Database type/name list boxes Table/columns list boxes Selected columns list box Arrow buttons Distinct results check box Define Alias button Calculated Column button Values button Allows you to Specify the statement type. The Selection dialog box changes dynamically to present only those options available for the chosen statement type. Specify the database on which to base the statement. Specify the tables and columns on which to base the statement. Select columns on which to base the statement. The SQL Editor uses the information in the Selected Columns list box to create the FROM clause automatically. To specify a table in the FROM clause without specifically selecting any of its columns, edit the FROM clause manually in the main SQL Editor window. Add or remove selected columns. Single arrows add or remove selected columns; double arrows add or remove all columns. Exclude duplicate records from the result set. Define shorter or more recognizable column names. The Internal Database does not support aliases. Define columns whose values are calculated from data values stored in other columns. Replace existing row data in an UPDATE statement or define the new row in an INSERT statement. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

210 Defining SELECT statements To define a SELECT statement: 1. Select Statement Selection from the SQL Editor menu. The Selection dialog box displays, as shown here: 2. Select a database from the Database type/name drop-down list box. 3. Select a table on which to base the SQL statement from the Table/columns drop-down list box. The column names for the table appear in the list box. 4. Select a column on which to base the SQL statement from the list box. Click > to add the column to the Selected Columns list box. If you want to add all of the columns, click >>. 5. Check Distinct results if you want to exclude duplicate results from the result set. 6. Repeat steps 2 5 until you have selected all of the tables and columns required for the statement. 7. Click OK to close the Selection dialog box and return to the SQL Editor after you have made your selections. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

211 The following illustration shows an example of how an SQL statement appears in the SQL Editor: The following sections describe how to define an alias and how to create calculated columns. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

212 Defining an alias To define a column alias: 1. Click Define Alias on the Selection dialog box. The Define Alias dialog box displays, as shown here: 2. Select a table name from the Table drop-down list box. 3. Type an alias for the selected table in the Alias name entry field. 4. Click Add to create a new alias. 5. Click OK to close the Define Alias dialog box. The table name in the list changes to the alias you specified. Modifying an alias To modify an existing alias: 1. Select the alias that you want to change from the Defined aliases list box. See the preceding section, Defining an alias. 2. Type a new alias in the Alias name entry field. You also can select a different table from the Table drop-down list box. 3. Click Modify. Deleting an alias To delete a defined alias, select the alias and click Remove. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

213 Calculating columns To calculate a column: 1. Click Calculated Columns on the Selection dialog box. The Calculated Column dialog box opens, as shown here: 2. Type an expression in the entry field. You can also create the expression by: A. Double-clicking a function in the Function list box to adding it to the expression entry field. B. Selecting a table and a column from the Table/Column list box. C. Selecting a mathematical function, the open or close parenthesis, or the DISTINCT indicator from the Keypad. D. Repeating steps a c until the calculated column is defined. 3. Click OK to save the expression and return to the Selection dialog box. 4. To create multiple calculated columns, repeat steps 1 and 2 as necessary. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

214 Creating UPDATE or INSERT statements To create an SQL UPDATE or INSERT statement: 1. Select Update on the Selection dialog box to define an UPDATE/SET clause. Select Insert to define an INSERT/INTO clause. These statement types use the same dialog box. The Selection dialog box for INSERT and UPDATE opens, as shown here: 2. Select the column that you want to update or in which the statement should insert new data. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

215 3. Click Values. The Values dialog box opens, as shown here: 4. Select the column and value from the synchronized list box. 5. Enter the new column value in the Value entry field. 6. Click Apply. Repeat steps 4 6 until you have entered data for all of the column values. 7. Click OK to close the Values dialog box. You also can access the Values dialog box by selecting Statement Values from the SQL Editor menu. You must have appropriate database rights to perform UPDATE and INSERT statements. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

216 Defining DELETE statements To define an SQL DELETE statement: 1. Select Delete on the Selection dialog box. You must have appropriate database rights to perform DELETE statements. 2. Define your DELETE statement by selecting options similar to those shown here: 3. Click OK to close the Selection dialog box and enter the DELETE statement in the SQL Editor. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

217 Typing directly in the SQL Editor window If you select Direct on the Selection dialog box, you can type an SQL statement directly in the SQL Editor window. You can enter any valid SQL statement, including those that are not defined by the Statement menu (for example, CREATE TABLE, DROP, or GRANT). The SQL Editor provides a verification utility to make sure your statement is syntactically correct before it executes. To create or modify an SQL statement by typing directly in the Editor: 1. Select Direct from the Selection dialog box. The Selection dialog box opens, as shown here: 2. Select the database type and database name to be used in the direct query from the Database type/name list boxes. 3. Click OK to return to the SQL Editor. 4. Type your SQL statement at the cursor. The Internal Database does not support statements created using this option. Opening the Data Manager To open the Data Manager from the SQL Editor: 1. Define a query. 2. Select Actions Data Manager. The Data Manager displays and contains columns and data that correspond to your query. For more information on the Data Manager, see Managing data on page 199. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

218 Executing a statement When you execute a SELECT statement, the results appear in an SQL Result Display window. Other statement types return a message indicating success or failure. The Internal Database displays a result set generated from UPDATE, DELETE, or INSERT statements. External databases do not display a result set. (To view the results, create a SELECT statement to retrieve these records.) To execute a statement: 1. Select Actions Verify from the SQL Editor menu. The status line displays a message that tells you if the statement is syntactically correct. An error message box appears if there is a problem with the statement. 2. Select Actions Run Statement from the SQL Editor menu. The SQL Result Display window displays, as shown here: 3. If you want to save the results: Select File Save as to save the results to a file. Select File Save Table to convert the results to an internal table. Select File Export to delimited to save the table in a delimited file. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

219 Defining a WHERE clause You can define a WHERE clause in the Search Condition dialog box. To define a WHERE clause: 1. Select Statement Search condition from the SQL Editor menu. The Search Condition dialog box displays, as shown here: 2. Select an expression from the first Expression drop-down list box (for example, Customer.status). You can also type an expression in the list box entry field. 3. Select an operator from the Operator drop-down list box (for example, =). You can also type an operator in the list box entry field. If you select the EXISTS or NOT EXISTS operator, the first Expression dropdown list box is disabled. If you select the BETWEEN or NOT BETWEEN operator, an AND drop-down list box appears. 4. Select a conjunction to link the next condition. The default conjunction is AND. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

220 5. Select the second expression (or pair of expressions) from the second Expression drop-down list box (for example, MARRIED). You can also type an expression in the list box. 6. Click Apply to add the condition to the Conditions list box. Repeat Steps 2 6 until you have defined or modified all parts of the WHERE clause. 7. Optional. Group conditions by selecting conditions as needed and clicking Group. The Group option changes the order in which the statement applies the selected condition; for example: Grouping A: WHERE (customer.name = 'Smith' AND product.name = 'chair') OR saleperson.name = 'Fred' Retrieves all of the records where the customer named Smith bought chairs, and all records where Fred is the salesperson. Grouping B: WHERE customer.name = 'Smith' AND (product.name = 'chair' OR saleperson.name = 'Fred') Retrieves all of the records where the customer name is Smith, and all of the records where Fred sold chairs. 8. Optional. Negate one or more conditions by selecting the conditions to be negated and clicking Negate. NOT appears on the line before the selected conditions. 9. Click OK to close the Search Condition dialog box. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

221 Defining a JOIN clause Naming two or more tables in the FROM clause results in an implicit join of those tables. If you do not specify the point at which the join should be made, the statement results include every possible combination of rows. This result is called a Cartesian product and is usually undesirable. You can specify explicit table joins in the WHERE clause (for example, WHERE customer.name=orders.custname), or by including a JOIN statement in the FROM clause. To join tables: 1. Create a SELECT statement (see Using the Selection dialog box on page 209). You must select at least two tables to create a JOIN clause. 2. Select Statement Join condition from the SQL Editor menu. The Table Join dialog box displays, as shown here: 3. Drag a column name icon from one table and drop it onto the equivalent column name in another table. Joined columns are indicated by combining the table colors within the icons. Repeat as needed to join the necessary columns. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

222 4. The default join condition is equals (=). Change the operators used to define the join: A. Double-click the join circle to be adjusted. The Join Details dialog box opens, as shown here: B. If you joined the table to more than one other table, select the table column for which the operator should be changed. C. Select a new operator under Operator (the default is equals (=). D. Click OK. 5. Click OK to close the Table Join dialog box. The JOIN function does not recognize table aliases. If you create a join in which one or more tables were assigned aliases, edit the JOIN statement in the main SQL Editor window to replace the table name with the appropriate alias. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

223 Defining a GROUP BY clause To define a GROUP BY clause: 1. Select Statement Grouping from the SQL Editor menu. The Grouping dialog box opens, as shown here: 2. Select the table that contains the column in which you want to group data from the Table/Columns drop-down list box. 3. Select the appropriate columns from the list box. 4. Repeat steps 2 and 3 until the GROUP BY clause is defined. 5. Click OK to close the Grouping dialog box. The Having button opens the Having dialog box, which allows you to define a HAVING clause. For more information on the Having dialog box, see Defining a HAVING clause that follows. Defining a HAVING clause An SQL HAVING clause performs similar functions within a group (see the preceding section, Defining a GROUP BY clause ) that a WHERE clause does for the entire statement. That is, it filters the records included in the result set groups based on the GROUP BY clause. The Having dialog box contains the same elements as the Search Condition dialog box, and the clause is constructed in the same way. For more information, see Defining a WHERE clause on page 219. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

224 Defining an ORDER BY clause Use the Order dialog box to create an ORDER BY clause, which determines the sort order for the result set. Rows are sorted according to the values within the first selected column. If you select more than one column, rows with duplicate data in the first column are sorted further by the values in succeeding columns. You can order the statement result by any field, even if that field does not appear in the SELECT clause. For example, you can sort the data by the order date column, even if you do not display the order date in the result set. To define an ORDER BY clause: 1. Select Statement Order from the SQL Editor menu. The Order dialog box opens, as shown here: 2. Select the table that contains the column by which to order data from the Table/Columns drop-down list box. 3. Select the column by which you want to order data from the list box. 4. Click > to copy your selection to the Ordered by list box. Click >> to copy all of the columns to the Ordered by list box. 5. Choose a sort direction (ASC, ascending, or DESC, descending) for the selected column. The default sort direction is ASC. Numeric columns sort in cardinal order (for example, 1, 2, 3). Alphabetic columns sort according to the character set s collation sequence (usually ASCII). 6. Repeat steps 1 5 until the ORDER BY clause is defined completely. 7. Click OK to close the Order dialog box. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

225 Creating parametric SQL statements Parametric queries allow you to build queries based on information that is available only at run time. ObjectStudio allows you to build queries with replaceable parameters and get the value for the parameter from a data entry window, a report, or any executable Smalltalk code. To enter a replaceable parameter in an SQL statement, define a WHERE clause that contains a question mark (?); for example: WHERE City =? You can enter any number of replaceable parameters into an SQL statement. However, you must define a parameter value for each question mark entered into the statement. ObjectStudio replaces the embedded question marks, in the order in which they appear in the statement, with the parameter value definitions, in the order in which they are defined. Replaceable parameters without corresponding parameter definitions can cause unpredictable results. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

226 To create a parametric SQL statement: 1. Select Statement Parameters from the SQL Editor menu. The Query Parameters dialog box opens, as shown here: Options on the dialog box change depending on which Source you select. 2. Select Window to select an item from any currently open data entry window, and then: A. Select a window from the Window drop-down list box. B. Select a form item from the Item drop-down list box. C. Click Insert to add the item to the Parameters list box. 3. Select Report to select an item from any currently open report, and then: A. Select a report from the Report drop-down list box. B. Select a form item from the Item drop-down list box. C. Click Insert to add the item to the Parameters list box. 4. Select Special to enter executable Smalltalk code to define the parameter value. 5. Repeat steps 2 4 until all parameter values are defined. 6. Click OK to close the Query Parameters dialog box. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

227 Committing changes You can set up the SQL Editor to commit database changes automatically when you run a statement, or manually when you select a menu option. Commit, Rollback, and Auto Commit options are available only if the underlying database supports transaction processing. The Internal Database does not support transaction processing. To commit changes to the database manually (the default), select Transaction Commit from the SQL Editor menu. To commit database changes automatically as you run each statement, select Transaction Auto Commit from the SQL Editor menu. A check mark appears next to the menu option. Rolling back changes To roll back the database to its state when you accessed it or its state immediately after the last commit action, select Transaction Rollback from the SQL Editor window. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

228 Importing and exporting statements ObjectStudio allows you to import SQL statements created with other applications and export SQL statements created in ObjectStudio for use in other applications. ObjectStudio provides import and export access to SQL statements in ASCII format. Importing statements To import a statement from a text file: 1. Select File Import from text file from the SQL Editor menu. The Open dialog box displays. 2. Select the folder where the text file is stored. 3. Select or type the file name. 4. Click Open to load the file and return to the SQL Editor. Exporting statements To export a statement to a text file: 1. Select File Export to text file from the SQL Editor menu. The Save As dialog box opens. 2. Select a folder in which to save the file. 3. Type a file name for the statement in the File name entry field. ObjectStudio uses the default extension.sql. 4. Click Save to save the statement and return to the SQL Editor. Creating a report for the statement Select Actions Report editor to access the Report Editor directly from the SQL Editor with the current SELECT statement already linked to a report template. This option is available only for SELECT statements. For more information on the Report Editor, see 10. Report Editor on page 231. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Editor

229 SQL Window The SQL Window allows you to: Type SQL statements directly into a window Import and export SQL statements as text files for reuse in the SQL Editor or SQL Window Scroll forward and backward through a series of up to five SQL statements Create and execute multiple batches of SQL statements When you open the SQL Window, the system assumes that you want to query the currently displayed database. However, you can select any other available database on which to base the query. File menu The following table describes the File menu options: Option Load Save as Exit Allows you to Bring an existing statement into the SQL Window. Save the currently displayed SQL statement as a text file (the default extension is.sql). Close the SQL Window. Displays the Save As dialog box if the system detects unsaved changes to the currently displayed SQL statement. Actions menu The following table describes the Actions menu options: Option Execute New Previous Next Allows you to Perform the statement displayed in the SQL Window. Clear the statement displayed in the SQL Window so you can enter a new one. Scroll backward through the last five statements entered in the SQL Window. Scroll forward through the next five statements entered in the SQL Window. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Window

230 Creating an SQL statement To create an SQL statement in the SQL Window: 1. Select Tools SQL Window from the Desktop menu. You can also open the SQL Window from the Database Notebook (see 8. Database Notebook on page 188). The SQL Window opens, as shown here: The status of the current SQL statement appears in the status line located at the bottom of the window. 2. Select the database that you want to query from the Database drop-down list box. 3. Type one or more SQL statements directly in the SQL Window. Separate multiple statements with a semicolon (;). 4. Do one of the following: Select Actions Execute to execute the statements and display the results (if a SELECT statement) or a Successful status (if any other statement type). Select Actions Previous to return to the previously executed SQL statements (if applicable) Select Actions Next to move to the next statement to be executed 5. Select File Save as to save the currently displayed statement. 6. Select File Exit to close the SQL Window. Loading an ASCII text file into the SQL Window You can load an ASCII file containing one or more SQL statements into the SQL Window and edit or execute it. For more information on loading SQL text files, see Importing and exporting statements on page 228. Database User s Guide, P Chapter: 9. SQL tools Section: SQL Window

231 10. Report Editor Using the Report Editor The Report Editor allows you to create free form or standard reports and include them in your applications. The Report Editor includes the following features: Full text and graphics capabilities, allowing you to select fonts, font sizes, icons, bitmaps, and four types of graphs Full mathematical capabilities, including aggregate functions, expressions, and numeric formatting based on country Full database management functions, including access to queries Screen previewing with report data, allowing you to test your queries and expressions and to verify the placement of text, numbers, and graphics in the report Full printer support, including time-delayed printing, color printing, and printing to files Database User s Guide, P Chapter: 10. Report Editor Section: Using the Report Editor

232 Creating a report Before you create a report in ObjectStudio, you may want to plan it on paper. This plan can help you define which fields to add, which queries to use or to create, and what calculations, such as subtotals or percentages, should be performed. After you create and save a report, see Formatting, previewing, and printing a report on page 257 for information on editing, previewing, or printing an existing report. To create a new report: 1. Select File New Report from the Desktop menu. The Create New Report dialog box displays, as shown here: 2. Enter a report name in the Name entry field. Database User s Guide, P Chapter: 10. Report Editor Section: Using the Report Editor

233 3. Specify the report format: A. Select Table or Query to choose a data source for the report. B. Select Default or Blank to start your report with either a default report format, or a blank format on which you place fields manually. C. Click New Query to create a query on which to base the report. For more information on the SQL Editor, see SQL Editor on page 205. D. Click Page Setup to format the page (for example, to select paper size and margins). E. Click Default Font to select a standard font and font size for your report. Setting default font options. You can save time by setting the default font options from the Create New Report dialog box. Once you enter the Report Editor, you can change the font and size for individual report items only. Database User s Guide, P Chapter: 10. Report Editor Section: Using the Report Editor

234 4. Click OK to close the Create New Report dialog box. The Report Editor opens, as shown here. If you selected the default report form, the system also displays fields from the database table or query. Database User s Guide, P Chapter: 10. Report Editor Section: Using the Report Editor

235 Saving reports To save a report: 1. Select File Save As from the Report Editor menu. You can also select File Exit or double-click the System Menu. The Save As dialog box opens. 2. Select a folder in which to save the file. 3. Type a file name in the File name entry field. 4. Click Save to save the file. The Report Editor creates an icon on the work area of the Desktop. The name under the icon is the same as the name you entered in the Create New Report dialog box. Database User s Guide, P Chapter: 10. Report Editor Section: Using the Report Editor

236 Working with report sections Reports typically have several sections, each of which contains specific types of information, as described in the following table: Section name Includes Placement Report Header Page Header Page Body Page Footer Report Footer Information that applies to the entire report (such as the report name). Information that applies to each report page (such as column headers and field names). Information that makes up the main part of the report. Information that applies to each report page (such as subtotals or page numbers). Information that applies to the entire report (such as grand totals or the print date). Top of the first page, before the page header (if any). Top of each page. Middle of each page, repeated for each record in the table. Bottom of each page. Bottom of the last page, before page footer (if any). Report sections function independently. Format settings made in one section have no effect on the others. Similarly, and with few exceptions, items (fields) placed in one section have no effect on items in other sections. Level breaks Level breaks allow you to group information and summarize data. For more information on level breaks, see Using level breaks on page 238. Database User s Guide, P Chapter: 10. Report Editor Section: Working with report sections

237 Adding or removing sections When you access the Report Editor, the system displays a report header, page header, and page body by default. Use the Sections menu to add and delete sections from your report. To suppress a section from the report preview and printout, set its height to zero as described in the next section; otherwise, the system leaves space for the item on the page. Formatting sections Format options for sections affect only height and grid size. The settings have no effect on items you place in the section, other than alignment to the grid. To format a section: 1. Select Format Sections from the Report Editor menu. The Format Section dialog box displays, as shown here: 2. Select a section from the Section drop-down list box. 3. Select a unit of measure. The unit of measure affects the position of report items. When designing a report for screen display, select tenths of millimeters to provide the greatest compatibility across hardware platforms and operating systems. 4. Uncheck Show Grid if you do not want to use the grid. If you want to use the grid, you can change the grid resolution in the X Grid Res and Y Grid Res entry fields. 5. Uncheck Snap Items to Grid if you do not want to align report items to the grid. 6. Click OK to save the settings and close the Format Section dialog box. Database User s Guide, P Chapter: 10. Report Editor Section: Working with report sections

238 Using level breaks Level breaks group and summarize report data. They appear as part of the report body when you preview or print the report, but they appear as separate sections in the Report Editor. Use level breaks to apply aggregate functions and expressions, or to include information from additional queries to specific subgroups of report data. The report illustrated here shows product revenues and sales costs per quarter, sorted by salesperson: Database User s Guide, P Chapter: 10. Report Editor Section: Working with report sections

239 Note the following about the level breaks shown in the previous figure: The first level break is based on the salesperson field. It contains the salesperson s name and an instruction to print at the top of each group. The second level break is based on the quarter field and contains sales figures. The third level break is also based on the salesperson field and summarizes the sales figures for each salesperson. You can use several level breaks in the same report. Subqueries Level breaks can also include subqueries. A subquery can be any query created in the SQL Editor. First, create the report and define the expressions and variables you want to use. Second, save the report; then access the SQL Editor and define your subquery. Finally, return to the Report Editor and select the subquery you want to use in the level break. For more information on the SQL Editor, see SQL Editor on page 205. Subqueries often use parameters from your report. Using the example shown in the figure above, suppose you want to list salespersons cities next to their names. Assume your database contains a table called Employee, which contains a field called City. Construct the following query: select * from Employee where name =? Assume the name of the report is SalesRpt and that Report Item 7 is linked to the name field. In the SQL Editor, select Statement Parameters and add the following parameter: (Report report: #SalesRpt at #reportitem7 asstring Save the query and return to the Report Editor. Link the first level break to the subquery, which then allows you to place fields, such as the City field, from the subquery into the report. (Instructions for placing report items are provided in Copying or moving report items on page 244.) Database User s Guide, P Chapter: 10. Report Editor Section: Working with report sections

240 Adding or modifying level breaks To add or modify a level break: 1. Select Sections Level Breaks from the Report Editor menu. The Level Breaks dialog box opens, as shown here: 2. Select a field, on which to base the level break, from the Fields list box. The system automatically names the break for the field and attaches a numeric identifier. You can also select an existing level break. The system highlights any options previously chosen for the selected level break. Database User s Guide, P Chapter: 10. Report Editor Section: Working with report sections

241 3. Format the level break: A. Select ASC (ascending) or DESC (descending) to order the data in the level break. B. Select Group Header or Group Footer to place the level break before or after its related data in the body of the report. C. Check Trigger lower breaks to reset and reprint information when using multiple level breaks. D. Check Page break before or Page break after to put a page break before or after a level break. E. Check Merge nested breaks to combine the data from level breaks that are linked by subqueries. 4. Repeat steps 2 and 3 as needed to define additional level breaks. 5. Click OK to return to the Report Editor. 6. Add, change, or remove report items to each level break, as needed. You can insert any report item into a level break, including a graph. For information on creating a graph, see Defining and formatting graphs and graph legends on page 253. Working with report items Report items can be text strings, graphic elements, or data fields: Text strings can be used as titles, headers, or other identifying labels in the report. Graphic elements include lines, boxes, graphs, or bitmaps. Data fields contain values from the selected table or query. Data fields can also contain values from calculations, such as the numeric value of a grand total placed at the end of a report. You can place items in any section of the report. After you place the items, you can delete, move, resize, or copy them. Database User s Guide, P Chapter: 10. Report Editor Section: Working with report items

242 Adding report items To add an item to a report: 1. Select Edit New Item from the Report Editor menu. The New Item dialog box opens, as shown here: 2. Enter a name for the item in the Name entry field or keep the default name. 3. Select a section from the Section drop-down list box. 4. Select a type from the Type list box. 5. Select a Field from the Field list box. 6. Check Link to Field to link the report item to a specific field in the table or query. When you select the field, the system automatically selects the correct field type. Database User s Guide, P Chapter: 10. Report Editor Section: Working with report items

243 7. Check Add Page Title to insert a column header in the page header section. Check Select Add Page Total to insert a total in the page footer section. To create a graph, link to a number field and then select the Graphics field type. For more information on using graphs, see Defining and formatting graphs and graph legends on page Click OK to save your changes and close the New Item dialog box. Resizing report items To resize a report item: 1. Select the report item that you want to resize. 2. Hold mouse button 1 and grab one of the report item handles. 3. Drag the report item in the appropriate direction until the item is the size that you want and release mouse button 1. Deleting report items To delete a report item: 1. Select the item you want to delete from the report section in the Report Editor. 2. Select Edit Delete Item from the Report Editor menu. Database User s Guide, P Chapter: 10. Report Editor Section: Working with report items

244 Copying or moving report items To copy an item and/or move it to a different section: 1. Select the item that you want to copy or move. 2. Select Edit Copy/Move Item from the Report Editor menu. The Copy/Move dialog box opens, as shown here: 3. Enter the destination name in the Destination Name entry field. 4. Select a section from the Destination Section drop-down list box. 5. Select a page to which the selected item should be moved or copied from the Destination Page drop-down list box. 6. Optional. Enter new X and Y positions and a new height for the copied or moved item. The units of measure refer only to measurements in the Copy/Move dialog box. When you change units, the values for position and size convert automatically. 7. Click Copy or Move to confirm your changes and return to the Report Editor. You also can select a report item and use mouse button 1 to drag the item to a new location on the report page. Database User s Guide, P Chapter: 10. Report Editor Section: Working with report items

245 Formatting report items Report items have different formatting options, depending on the information they contain. For example, the formatting options for a text string differ from those for a pie chart. After placing string and numeric items on your report, you can format them or change their function. To format a report item: 1. Double-click the report item that you want to change. You can also select the item, then select Format Selected Item from the Report Editor menu. The Report Item Options dialog box opens, as shown here: The Value field displays information that appears in the report (for example, the text in a column header, columnar data, or an expression). Database User s Guide, P Chapter: 10. Report Editor Section: Formatting report items

246 2. To enter a new string value, such as a column header, type the new string in the Value field. 3. Select Expression to define an expression in the Value entry field (uncheck Link to Field if necessary). Select fields and operators from the Field and Operators list boxes. The expression appears in the Value field. 4. Link to Field allows you to link an item to a specific field from the table or query on which the report is based. To link an item to a field, check Link to Field; then select a field. You also can use a linked field for aggregate functions. Check Link to Field; then select one of the Functions (Count, Sum, Average, Minimum, or Maximum). 5. Check Multi-Line String if you want to format an item that occupies more than one line of the report (for example, lengthy comment fields). The Options button appears on the form. For more information on formatting multi-line strings, see Formatting multi-line string items on page Display Options allows you to hide a box that surrounds items, suppress repeated data in a column, or prevent an item from appearing on the screen. For example, you might want to hide repeated data, such as sales order numbers, so that they print only once (for example, when the numbers change). 7. Click Format to display the String, Numeric, or Date Display Format dialog box. The dialog box that opens depends on the type of report item you select: String item format options include such settings as font, font size, justification, and style (for example, bold or italic). Numeric item format options include those available for string options, plus international currency and decimal settings, precision, and leading-character options. Date item format options include those available for string options, plus a variety of date and time settings. For more information on these formatting dialog boxes, refer to the ObjectStudio User Interface Guide, P Click OK to save your changes and close the Report Item Options dialog box. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting report items

247 Formatting multi-line string items Multi-line string items can contain up to 8,192 characters. To access formatting options for multi-line strings: 1. Select the report item to be used as a multi-line string. 2. Use the mouse to size the item appropriately. 3. Double-click the item to display the Report Item Options dialog box. 4. Check Multi-Line String. 5. Click Options. The Multiple Line Item Options dialog box displays, as shown here: Database User s Guide, P Chapter: 10. Report Editor Section: Formatting report items

248 6. Max Height determines how the multi-line string uses space on the report page. Select one of the following options: Size Field Dynamically adjusts the size of the item to accommodate the field contents. Size field up to max height adjusts the item to the size you set in step 1. (Field contents that exceed the maximum height are truncated.) Always use max height allows the full size that you set in step 1, whether or not the field contents need the space. 7. Select one of the measures of units. 8. Check User-defined line spacing to define how much space appears between each line of text. Type a value in the appropriate unit of measure in the Line Spacing entry field. 9. Click OK to close the Multiple Line Item Options Dialog Box. Formatting graphic items The Report Editor offers numerous graphic elements that enhance the appearance and readability of your reports. You can add any of the following items: Horizontal or vertical lines. Boxes with square or rounded corners. Bitmaps, such as your company s logo. Bar graphs, line charts, pie charts, and scatter graphs. For more information on graphs, see Defining and formatting graphs and graph legends on page 253. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting graphic items

249 Formatting lines and topic boxes Use vertical lines to separate columns of data, or a horizontal line to separate a column header or footer from the page body. Add topic boxes to a report to highlight or surround special information. To create and format a line item: 1. Select Line from the Type list box on the New Item dialog box and add it to the form. 2. Double-click the line item on the report page to open the Report Line Options dialog box, as shown here: Database User s Guide, P Chapter: 10. Report Editor Section: Formatting graphic items

250 3. Select a Format. 4. Type a line width in the Line Width entry field. Line widths are measured in tenths of millimeters. 5. Select a color from the Line Color list box. A sample of the line appears in the Example area. 6. Click OK to return to the Report Editor. 7. Use mouse button 1 (or the Copy/Move dialog box) to size the line or topic box, if necessary. The steps for creating and formatting a topic box are similar to the previous steps for creating and formatting a line. Creating and formatting bitmapped images The Report Editor allows you to insert one or more bitmaps into your reports. For example, for an inventory listing, you might want to display your company s logo in the report header and an image of a clipboard at the left side of the page body. Keep in mind that the quality of the images depends on your printer and monitor. If you plan to use the same file image repeatedly in many reports, register the image in ObjectStudio (see Registering a graphics file on page 252). Creating a bitmap To create a bitmap: 1. Select Edit New Item from the Report Editor menu. The New Item dialog box opens. 2. Select Bitmap from the Type list box on the New Item dialog box. 3. Click OK to close New Item dialog box. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting graphic items

251 Formatting the bitmap To format the bitmap: 1. Double-click the bitmap report item. The Report Bitmap Options dialog box opens, as shown here: 2. Type a new name in the Name entry field, or you can keep the default name. 3. Select the type of bitmap under Type: If you select Icon or Bitmap, you can select the type of bitmap from the Icons drop-down list box. The Example field displays an example of the bitmap that you selected. If you select File, you must select a file to create the bitmap: A. Click Search to open the Open dialog box. B. Select the file from the Open dialog box. C. Click Open. 4. Click OK to close the Report Bitmap Options dialog box. 5. Move, copy, and resize the image as needed. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting graphic items

252 Registering a graphics file If you use the same graphics files regularly, you can register them as bitmaps or icons. To register a graphics file: 1. Select Tools Workspace from the Desktop menu. 2. Define the image as a temporary variable. For example, to register a file called marble.bmp, enter the following in the Workspace: bmp :=bitmap loadfile: 'c:\marble.bmp'. bmp registeras: #Marble. 3. Select Actions Execute from the Workspace menu. 4. Select File Quit to close the Workspace and return to the Report Editor. As long as ObjectStudio is open, you can select the new bitmap by selecting Bitmap on the Report Bitmap Options dialog box. Save the image to store the bitmap permanently. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting graphic items

253 Defining and formatting graphs and graph legends The Report Editor can generate the following types of charts: Bar Line Scatter Pie The New Item dialog box contains two types of graphic report items. The Graphics Field option appears after you select the Link to field option and choose a numeric field. The graphics field item contains the actual graph, which you format after creating and placing the item. The Graphics Legend option can be selected like a string item and can be used to replace a field name in a graph with a more descriptive label. For more information on graphics legends, see Formatting graphics legends on page 256. Placing a graphics field The report section in which you place a graph determines its content: In the page body, a separate graph appears for each record In the page footer, the graph incorporates data from each page In a level break, the graph shows results for the break In the report footer, the graph includes data from the entire report Database User s Guide, P Chapter: 10. Report Editor Section: Defining and formatting graphs and graph legends

254 Defining a graphics field To define a graphics field: 1. Double-click the graphics field item to display the Report Graph Options dialog box. 2. Select the following options as needed: Assign a graph name that you can remember easily. If you use graph legends, you must link them to the correct graph. Select the type of graph under Type. Check Enable Label Link to choose a field name for the X-axis label. Select additional fields for the graph, if needed; then click Insert. For a scatter graph, select fields for the X- and Y-axis. Check Hide Item Borders to display or hide an outline around the graph. 3. Click OK to save your changes and return to the Report Editor 4. Move and resize the graph as needed. Formatting graphics fields The Report Editor offers full formatting capabilities for your graphs. Color selections appear in the report preview and in printouts if your printer supports the selected colors. For information on previewing and printing, see Formatting, previewing, and printing a report on page 257. To format a graphics field: 1. Double-click the graphics field item to display the Report Graph Options dialog box. 2. Click Format to open the Display Format dialog box for the type of graph you selected. Database User s Guide, P Chapter: 10. Report Editor Section: Defining and formatting graphs and graph legends

255 3. Select options as needed. The system displays your settings in the Example box. Confirm your changes when you are ready to return to the Report Editor. (The X- and Y- label format buttons present the String or Numeric Display Format dialog box, as appropriate.) Specific formatting options for each type of graph are: Bar graph format options: - A color and a pattern for each graph level (bar) and for the X- and Y-axis labels - Whether the bars should be grouped or stacked - Display formats and colors for the X- and Y-axis labels - Minimum and maximum numbers to display in the X- and Y-axes Line graph format options: - A color, pattern, and width (in millimeters) for each graph level (line) - Display formats and colors for the X- and Y-axis labels - Minimum and maximum numbers to display in the X- and Y-axes Scatter graph format options: - A color and shape for each graph level (marker) - Display formats and colors for the X- and Y-axis labels - Minimum and maximum numbers to display in the X- and Y-axes Pie chart format options: - A color and pattern for each graph level (section) - Minimum and maximum numbers to display in the X-axis - A display format for the X-axis Although you can set the X- and Y-axes colors, the selections have no effect on a pie chart. - The number of columns per group (for example, repetition of colors and patterns) Two graph levels are used in a pie chart, but you can select additional levels as needed by choosing the number of columns per group. Database User s Guide, P Chapter: 10. Report Editor Section: Defining and formatting graphs and graph legends

256 Formatting graphics legends Graphics legends list fields selected from the table or query on which the graph is based. Use the legends to substitute appropriate labels for your graph. For example, you might substitute Sales Rep for a field named srname. Create graphics legends just like string fields. Graphics legends work with bar, line, and scatter graphs but not with pie charts. To format a graphics legend: 1. Double-click the graphics legend report item. The Report Legend Options dialog box opens, as shown here: 2. Select a graph to which you want to link the graph legend from the Link to graph drop-down list box. 3. Click Label Format to display the String Display Format dialog box. Make changes as needed. 4. Click OK to close the Report Legend Options dialog box. Database User s Guide, P Chapter: 10. Report Editor Section: Defining and formatting graphs and graph legends

257 Formatting, previewing, and printing a report After you finish adding items and graphics to your report, you can preview and print the report. Formatting report pages Before you preview or print your report, set page format parameters: 1. Click Page Setup in the Create New Report dialog box, or select Format Page Setup in the Report Editor. The Page Setup dialog box opens, as shown here: 2. Select the page-size setting from the Page Size entry field. The page-size settings allow you to select the paper size and print orientation (portrait or landscape) for your report. To define custom-cut paper stock, select User Defined in the Page Size list box. Enter a page height, width, and margins in the appropriate units. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting, previewing, and printing a report

258 3. Select a Value to determine the units to use for setting the margins. The unit of measure refers only to the margin settings. When you change the unit of measure, the margin settings convert automatically. 4. Click OK to close the Page Setup dialog box. Horizontal and vertical pages. The Report Editor aligns reports on a grid of horizontal and vertical pages, as shown here: Horizontal pages display report items and data in columns, as in a spreadsheet. When you select the Default radio button on the Create New Report dialog box, the system automatically places each field in a column. If your table or query has several columns, your default report will have two or more horizontal pages. Use the Horizontal Pages menu in the Report Editor to add, display, or delete horizontal pages. Vertical pages display data according to the column alignment of the horizontal pages. The number of vertical pages in your report depends on the number of records and the number of required page breaks. Use the Pages menu in the Report Preview to move to another vertical or horizontal page. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting, previewing, and printing a report

259 Previewing a report Previewing a report on the screen allows you to verify the placement and content of report items. You can also print a single page to check a sample from your printer. To preview a report: 1. Select File Screen Preview from the Report Editor menu. The Report Preview opens, as shown here: It shows one formatted page at a time. You can resize the Report Preview window as needed and use the Pages menu to display additional report pages. (The system displays the current vertical and horizontal page in the title bar.) 2. Select File Exit to close the Report Preview window and return to the Report Editor. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting, previewing, and printing a report

260 Printing from the Report Preview To print from the Report Preview: 1. Select File Print current page or File Print all pages from the Report Preview menu. 2. Select the appropriate settings for your printer from the Print dialog box. 3. Click OK to print the report. Setting the report timer You can set the report timer to print a report at specific times. The timer starts when you activate it and save the report (see Saving reports on page 235). As long as ObjectStudio is open, the timer counts down until the report prints. In an application, the following actions start the timer: Double-clicking the report icon on the Desktop and selecting Report printing options from the Print dialog box. Loading a report from a file (if you saved the report with an activated timer). Closing the Report Output Options dialog box. Opening the Report Output Options dialog box or modifying the report in the Report Editor stops an activated timer. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting, previewing, and printing a report

261 To set the report timer: 1. Select File Timer from the Report Editor menu. The Report Timer dialog box opens, as shown here: The options available on the Report Timer dialog box depend on the Mode you select. 2. Do the following as needed: For a daily report, enter the time. For a weekly report, select the day of the week and enter the time. For an interval report, enter a period in hundredths of a second. (For example, to print the report every two hours, enter 720,000.) For a one-time-only report, enter the date and time. Select Activate to begin the timer countdown. Select Deactivate to keep the timer settings but disable the countdown. 3. Click OK to close the Report Timer dialog box. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting, previewing, and printing a report

262 Setting output options Report output options allow you to select page-printing options for your report. To set report output options: 1. Select File Output Options from the Report Editor menu. The Report Output Options dialog box displays, as shown here: 2. Select one of the following options: Select Do not prompt for printer setup to disable a printer setup dialog box. (The contents of the setup dialog box depend on your operating system.) Select Pause between vertical pages to give the user time to load special paper, such as letterhead, between horizontal and vertical pages. (This option is best suited for local printers rather than centrally located network printers.) Select Page breaks after each record to start each record on a new page. Select Disable FormFeed for page breaks to disable the normal form feed for page breaks. 3. Click OK to save the options and return to the Report Editor. Database User s Guide, P Chapter: 10. Report Editor Section: Formatting, previewing, and printing a report

Cincom Smalltalk. ObjectStudio. OLE User s Guide P ObjectStudio 8.3

Cincom Smalltalk. ObjectStudio. OLE User s Guide P ObjectStudio 8.3 Cincom Smalltalk ObjectStudio OLE User s Guide P40-3805-03 ObjectStudio 8.3 Cincom Smalltalk ObjectStudio OLE User's Guide Publication Number P40-3805-03 1988 1999, 2001, 2003, 2005, 2006, 2008 2011 Cincom

More information

Creating Enterprise and WorkGroup Applications with 4D ODBC

Creating Enterprise and WorkGroup Applications with 4D ODBC Creating Enterprise and WorkGroup Applications with 4D ODBC Page 1 EXECUTIVE SUMMARY 4D ODBC is an application development tool specifically designed to address the unique requirements of the client/server

More information

Store and Manage Data in a DBMS With ArcView Database Access. Presented By: Andrew Arana & Canserina Kurnia

Store and Manage Data in a DBMS With ArcView Database Access. Presented By: Andrew Arana & Canserina Kurnia Store and Manage Data in a DBMS With ArcView Database Access Presented By: Andrew Arana & Canserina Kurnia Overview Topics to be Covered: General method for accessing data database themes, database tables

More information

Web Services in Cincom VisualWorks. WHITE PAPER Cincom In-depth Analysis and Review

Web Services in Cincom VisualWorks. WHITE PAPER Cincom In-depth Analysis and Review Web Services in Cincom VisualWorks WHITE PAPER Cincom In-depth Analysis and Review Web Services in Cincom VisualWorks Table of Contents Web Services in VisualWorks....................... 1 Web Services

More information

Introduction JDBC 4.1. Bok, Jong Soon

Introduction JDBC 4.1. Bok, Jong Soon Introduction JDBC 4.1 Bok, Jong Soon javaexpert@nate.com www.javaexpert.co.kr What is the JDBC TM Stands for Java TM Database Connectivity. Is an API (included in both J2SE and J2EE releases) Provides

More information

Rapid SQL 7.5 Evaluation Guide. Published: September 28, 2007

Rapid SQL 7.5 Evaluation Guide. Published: September 28, 2007 Rapid SQL 7.5 Evaluation Guide Published: September 28, 2007 Embarcadero Technologies, Inc. 100 California Street, 12th Floor San Francisco, CA 94111 U.S.A. This is a preliminary document and may be changed

More information

CHAPTER. Oracle Database 11g Architecture Options

CHAPTER. Oracle Database 11g Architecture Options CHAPTER 1 Oracle Database 11g Architecture Options 3 4 Part I: Critical Database Concepts Oracle Database 11g is a significant upgrade from prior releases of Oracle. New features give developers, database

More information

IBM i Version 7.2. Database Database overview IBM

IBM i Version 7.2. Database Database overview IBM IBM i Version 7.2 Database Database overview IBM IBM i Version 7.2 Database Database overview IBM Note Before using this information and the product it supports, read the information in Notices on page

More information

External Data Connector for SharePoint

External Data Connector for SharePoint External Data Connector for SharePoint Last Updated: August 2014 Copyright 2014 Vyapin Software Systems Private Limited. All rights reserved. This document is being furnished by Vyapin Software Systems

More information

IBM. Database Database overview. IBM i 7.1

IBM. Database Database overview. IBM i 7.1 IBM IBM i Database Database overview 7.1 IBM IBM i Database Database overview 7.1 Note Before using this information and the product it supports, read the information in Notices, on page 39. This edition

More information

Acu4GL COBOL-to-RDBMS Interface

Acu4GL COBOL-to-RDBMS Interface Acu4GL COBOL-to-RDBMS Interface EXECUTIVE OVERVIEW Acu4GL is a patented interface technology designed to bridge the worlds of third-generation COBOL and fourth-generation Structured Query Language (SQL).

More information

Introducing the SAS ODBC Driver

Introducing the SAS ODBC Driver 1 CHAPTER 1 Introducing the SAS ODBC Driver Overview: The SAS ODBC Driver 1 What Is ODBC? 2 What Is the SAS ODBC Driver? 2 Types of Data Accessed with the SAS ODBC Driver 3 Understanding SAS 5 SAS Data

More information

VMware Horizon Session Recording Fling:

VMware Horizon Session Recording Fling: VMware Horizon Session Recording Fling: The VMware Horizon Session Recording fling allows administrators to record VMware Blast Extreme sessions to a central server for playback. These recordings can be

More information

DataFlux Web Studio 2.5. Installation and Configuration Guide

DataFlux Web Studio 2.5. Installation and Configuration Guide DataFlux Web Studio 2.5 Installation and Configuration Guide The correct bibliographic citation for this manual is as follows: SAS Institute Inc. 2014. DataFlux Web Studio 2.5: Installation and Configuration

More information

SAS. Information Map Studio 3.1: Creating Your First Information Map

SAS. Information Map Studio 3.1: Creating Your First Information Map SAS Information Map Studio 3.1: Creating Your First Information Map The correct bibliographic citation for this manual is as follows: SAS Institute Inc. 2006. SAS Information Map Studio 3.1: Creating Your

More information

SAS ODBC Driver. Overview: SAS ODBC Driver. What Is ODBC? CHAPTER 1

SAS ODBC Driver. Overview: SAS ODBC Driver. What Is ODBC? CHAPTER 1 1 CHAPTER 1 SAS ODBC Driver Overview: SAS ODBC Driver 1 What Is ODBC? 1 What Is the SAS ODBC Driver? 2 Types of Data Accessed with the SAS ODBC Driver 3 Understanding SAS 4 SAS Data Sets 4 Unicode UTF-8

More information

Analytics: Server Architect (Siebel 7.7)

Analytics: Server Architect (Siebel 7.7) Analytics: Server Architect (Siebel 7.7) Student Guide June 2005 Part # 10PO2-ASAS-07710 D44608GC10 Edition 1.0 D44917 Copyright 2005, 2006, Oracle. All rights reserved. Disclaimer This document contains

More information

Teradata Studio Express

Teradata Studio Express Teradata Studio Express User Guide Release 16.20 April 2018 B035-2042-518K Copyright and Trademarks Copyright 2006-2018 by Teradata. All Rights Reserved. All copyrights and trademarks used in Teradata

More information

SAS/ACCESS Interface to R/3

SAS/ACCESS Interface to R/3 9.1 SAS/ACCESS Interface to R/3 User s Guide The correct bibliographic citation for this manual is as follows: SAS Institute Inc. 2004. SAS/ACCESS 9.1 Interface to R/3: User s Guide. Cary, NC: SAS Institute

More information

JDBC. Sun Microsystems has included JDBC API as a part of J2SDK to develop Java applications that can communicate with databases.

JDBC. Sun Microsystems has included JDBC API as a part of J2SDK to develop Java applications that can communicate with databases. JDBC The JDBC TM API is the application programming interface that provides universal data access for the Java TM platform. In other words, the JDBC API is used to work with a relational database or other

More information

Connecting to Your Database. PowerBuilder 11.5

Connecting to Your Database. PowerBuilder 11.5 Connecting to Your Database PowerBuilder 11.5 DOCUMENT ID: DC37776-01-1150-01 LAST REVISED: September 2008 Copyright 2008 by Sybase, Inc. All rights reserved. This publication pertains to Sybase software

More information

About Database Adapters

About Database Adapters About Database Adapters Sun Microsystems, Inc. 4150 Network Circle Santa Clara, CA 95054 U.S.A. Part No: 820 5069 07/08/08 Copyright 2007 Sun Microsystems, Inc. 4150 Network Circle, Santa Clara, CA 95054

More information

ARPEGGIO Data Access Frequently Asked Questions

ARPEGGIO Data Access Frequently Asked Questions Technical Bulletin ARPEGGIO Data Access Frequently Asked Questions Product: ARPEGGIO products Version: ARPEGGIO 1.0 & later Host: Mainframe, AS/400 RS/6000 NIC: N/A Interface: RUMBA Router Microsoft SNA

More information

Data Validation Option Best Practices

Data Validation Option Best Practices Data Validation Option Best Practices 1993-2016 Informatica LLC. No part of this document may be reproduced or transmitted in any form, by any means (electronic, photocopying, recording or otherwise) without

More information

External Data Connector for SharePoint

External Data Connector for SharePoint External Data Connector for SharePoint Last Updated: July 2017 Copyright 2014-2017 Vyapin Software Systems Private Limited. All rights reserved. This document is being furnished by Vyapin Software Systems

More information

HP Database and Middleware Automation

HP Database and Middleware Automation HP Database and Middleware Automation For Windows Software Version: 10.10 SQL Server Database Refresh User Guide Document Release Date: June 2013 Software Release Date: June 2013 Legal Notices Warranty

More information

JDBC. Oracle ODBC SP API SP API. SQL server C function calls. SQL server ODBC SP API. Oracle DSN Oracle ODBC Oracle

JDBC. Oracle ODBC SP API SP API. SQL server C function calls. SQL server ODBC SP API. Oracle DSN Oracle ODBC Oracle How to Interact with DataBase? THETOPPERSWAY.COM Generally every DB vendor provides a User Interface through which we can easily execute SQL query s and get the result (For example Oracle Query Manager

More information

Product Documentation. DB Optimizer. Evaluation Guide. Version Published November 27, 2009

Product Documentation. DB Optimizer. Evaluation Guide. Version Published November 27, 2009 Product Documentation DB Optimizer Evaluation Guide Version 2.0.1 Published November 27, 2009 Copyright 1994-2009 Embarcadero Technologies, Inc. Embarcadero Technologies, Inc. 100 California Street, 12th

More information

Embarcadero DB Optimizer 1.0 Evaluation Guide. Published: July 14, 2008

Embarcadero DB Optimizer 1.0 Evaluation Guide. Published: July 14, 2008 Published: July 14, 2008 Embarcadero Technologies, Inc. 100 California Street, 12th Floor San Francisco, CA 94111 U.S.A. This is a preliminary document and may be changed substantially prior to final commercial

More information

Using the IMS Universal Drivers and QMF to Access Your IMS Data Hands-on Lab

Using the IMS Universal Drivers and QMF to Access Your IMS Data Hands-on Lab Attendee Choice: IMS Hands-on Lab Thursday, August 13, 2015: 12:30 PM - 01:30 PM, Dolphin, Asia 5 #17765 Insert Custom Session QR if Desired Business Analytics on zenterprise The QMF 11 Product Family

More information

One Identity Quick Connect for Base Systems 2.4. Administrator Guide

One Identity Quick Connect for Base Systems 2.4. Administrator Guide One Identity Quick Connect for Base Systems 2.4 Administrator Copyright 2017 One Identity LLC. ALL RIGHTS RESERVED. This guide contains proprietary information protected by copyright. The software described

More information

SAS/Warehouse Administrator Usage and Enhancements Terry Lewis, SAS Institute Inc., Cary, NC

SAS/Warehouse Administrator Usage and Enhancements Terry Lewis, SAS Institute Inc., Cary, NC SAS/Warehouse Administrator Usage and Enhancements Terry Lewis, SAS Institute Inc., Cary, NC ABSTRACT SAS/Warehouse Administrator software makes it easier to build, maintain, and access data warehouses

More information

Document # Rev. C 4/10 Cencon 4 Getting Started Guide

Document # Rev. C 4/10 Cencon 4 Getting Started Guide Page 1 KABA MAS Cencon 4 Getting Started Guide Kaba Mas Welcome Kaba Mas, part of the world-wide Kaba group, is the world's leading manufacturer and supplier of high security, electronic safe locks. Its

More information

SAP Workforce Performance Builder 9.5

SAP Workforce Performance Builder 9.5 Upgrade Guide Workforce Performance Builder Document Version: 1.0 2016-10-15 2016 SAP SE or an SAP affiliate company. All rights reserved. CUSTOMER Table of Contents 1 Introduction... 3 2 Migrating a Workarea...

More information

Configuring the Oracle Network Environment. Copyright 2009, Oracle. All rights reserved.

Configuring the Oracle Network Environment. Copyright 2009, Oracle. All rights reserved. Configuring the Oracle Network Environment Objectives After completing this lesson, you should be able to: Use Enterprise Manager to: Create additional listeners Create Oracle Net Service aliases Configure

More information

SQL Studio (BC) HELP.BCDBADASQL_72. Release 4.6C

SQL Studio (BC) HELP.BCDBADASQL_72. Release 4.6C HELP.BCDBADASQL_72 Release 4.6C SAP AG Copyright Copyright 2001 SAP AG. All rights reserved. No part of this publication may be reproduced or transmitted in any form or for any purpose without the express

More information

Embarcadero Rapid SQL

Embarcadero Rapid SQL Product Documentation Embarcadero Rapid SQL New Features Guide Version 8.6.1/XE5 Published May, 2014 2014 Embarcadero Technologies, Inc. Embarcadero, the Embarcadero Technologies logos, and all other Embarcadero

More information

Domino Enterprise Connections Services User Guide

Domino Enterprise Connections Services User Guide Domino Enterprise Connections Services User Guide COPYRIGHT Under the copyright laws, neither the documentation nor the software may be copied, photocopied, reproduced, translated, or reduced to any electronic

More information

Talend Open Studio for Data Quality. User Guide 5.5.2

Talend Open Studio for Data Quality. User Guide 5.5.2 Talend Open Studio for Data Quality User Guide 5.5.2 Talend Open Studio for Data Quality Adapted for v5.5. Supersedes previous releases. Publication date: January 29, 2015 Copyleft This documentation is

More information

Oracle Transparent Gateways

Oracle Transparent Gateways Oracle Transparent Gateways Using Transparent Gateways with Oracle9i Application Server Release 1.0.2.1 February 2001 Part No. A88729-01 Oracle offers two solutions for integrating data from non-oracle

More information

Extended Search Administration

Extended Search Administration IBM Lotus Extended Search Extended Search Administration Version 4 Release 0.1 SC27-1404-02 IBM Lotus Extended Search Extended Search Administration Version 4 Release 0.1 SC27-1404-02 Note! Before using

More information

Oracle Database Heterogeneous Connectivity User's Guide. 12c Release 2 (12.2)

Oracle Database Heterogeneous Connectivity User's Guide. 12c Release 2 (12.2) Oracle Database Heterogeneous Connectivity User's Guide 12c Release 2 (12.2) E85878-01 April 2017 Oracle Database Heterogeneous Connectivity User's Guide, 12c Release 2 (12.2) E85878-01 Copyright 2001,

More information

Database Toolbox Getting Started Guide. R2013a

Database Toolbox Getting Started Guide. R2013a Database Toolbox Getting Started Guide R2013a How to Contact MathWorks www.mathworks.com Web comp.soft-sys.matlab Newsgroup www.mathworks.com/contact_ts.html Technical Support suggest@mathworks.com bugs@mathworks.com

More information

DB2 QMF Data Service Version 12 Release 1. Studio User's Guide IBM SC

DB2 QMF Data Service Version 12 Release 1. Studio User's Guide IBM SC DB2 QMF Data Service Version 12 Release 1 Studio User's Guide IBM SC27-8886-00 DB2 QMF Data Service Version 12 Release 1 Studio User's Guide IBM SC27-8886-00 Note Before using this information and the

More information

Teiid Designer User Guide 7.5.0

Teiid Designer User Guide 7.5.0 Teiid Designer User Guide 1 7.5.0 1. Introduction... 1 1.1. What is Teiid Designer?... 1 1.2. Why Use Teiid Designer?... 2 1.3. Metadata Overview... 2 1.3.1. What is Metadata... 2 1.3.2. Editing Metadata

More information

APPENDIX 4 Migrating from QMF to SAS/ ASSIST Software. Each of these steps can be executed independently.

APPENDIX 4 Migrating from QMF to SAS/ ASSIST Software. Each of these steps can be executed independently. 255 APPENDIX 4 Migrating from QMF to SAS/ ASSIST Software Introduction 255 Generating a QMF Export Procedure 255 Exporting Queries from QMF 257 Importing QMF Queries into Query and Reporting 257 Alternate

More information

Ingres 9.3. Release Summary ING-93-RS-02

Ingres 9.3. Release Summary ING-93-RS-02 Ingres 9.3 Release Summary ING-93-RS-02 This Documentation is for the end user's informational purposes only and may be subject to change or withdrawal by Ingres Corporation ("Ingres") at any time. This

More information

Océ Posterizer Pro Designer. POP into retail. User manual Application guide

Océ Posterizer Pro Designer. POP into retail. User manual Application guide - Océ Posterizer Pro Designer POP into retail o User manual Application guide Copyright copyright-2010 Océ All rights reserved. No part of this work may be reproduced, copied, adapted, or transmitted in

More information

Publish Joomla! Article

Publish Joomla! Article Enterprise Architect User Guide Series Publish Joomla! Article Sparx Systems Enterprise Architect supports publishing an entire model, or part of the model, in a local Joomla! Repository as Articles (HTML

More information

TIBCO Spotfire Automation Services

TIBCO Spotfire Automation Services TIBCO Spotfire Automation Services Software Release 7.9 May 2017 Two-Second Advantage 2 Important Information SOME TIBCO SOFTWARE EMBEDS OR BUNDLES OTHER TIBCO SOFTWARE. USE OF SUCH EMBEDDED OR BUNDLED

More information

Publish Joomla! Article

Publish Joomla! Article Enterprise Architect User Guide Series Publish Joomla! Article Author: Sparx Systems Date: 10/05/2018 Version: 1.0 CREATED WITH Table of Contents Publish Joomla! Article 3 Install Joomla! Locally 4 Set

More information

Arcserve Backup for Windows

Arcserve Backup for Windows Arcserve Backup for Windows Agent for Sybase Guide r17.0 This Documentation, which includes embedded help systems and electronically distributed materials, (hereinafter referred to as the Documentation

More information

Using SAP NetWeaver Business Intelligence in the universe design tool SAP BusinessObjects Business Intelligence platform 4.1

Using SAP NetWeaver Business Intelligence in the universe design tool SAP BusinessObjects Business Intelligence platform 4.1 Using SAP NetWeaver Business Intelligence in the universe design tool SAP BusinessObjects Business Intelligence platform 4.1 Copyright 2013 SAP AG or an SAP affiliate company. All rights reserved. No part

More information

Automated Sign-on for Mainframe Administrator Guide

Automated Sign-on for Mainframe Administrator Guide Automated Sign-on for Mainframe Administrator Guide 12.5.1 For information about legal notices, trademarks, disclaimers, warranties, export and other use restrictions, U.S. Government rights, patent policy,

More information

USER GUIDE. Rockwell Automation Publication RSSQL-UM001I-EN-P-June 2014

USER GUIDE. Rockwell Automation Publication RSSQL-UM001I-EN-P-June 2014 USER GUIDE Rockwell Automation Publication RSSQL-UM001I-EN-P-June 2014 Supersedes Publication RSSQL-UM001H-EN-P-April 2011 Contacting Rockwell Copyright Notice Trademark Notices Other Trademarks Warranty

More information

Policy Commander Console Guide - Published February, 2012

Policy Commander Console Guide - Published February, 2012 Policy Commander Console Guide - Published February, 2012 This publication could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes

More information

ADVANTAGES. Via PL/SQL, all sorts of calculations can be done quickly and efficiently without use of Oracle engine.

ADVANTAGES. Via PL/SQL, all sorts of calculations can be done quickly and efficiently without use of Oracle engine. 1 PL/SQL INTRODUCTION SQL does not have procedural capabilities. SQL does not provide the programming techniques of condition checking, looping and branching that is required for data before permanent

More information

Perceptive Matching Engine

Perceptive Matching Engine Perceptive Matching Engine Advanced Design and Setup Guide Version: 1.0.x Written by: Product Development, R&D Date: January 2018 2018 Hyland Software, Inc. and its affiliates. Table of Contents Overview...

More information

Copyright 2010, Oracle. All rights reserved.

Copyright 2010, Oracle. All rights reserved. Agenda Interactive Dashboards Master-Detail Linking New Prompt Controls Pivot Table Interactions Enhanced Dashboard Builder Analysis Editor Overview Working with the analysis editor step by step Praxisteil

More information

PlanetPress Search User Guide.

PlanetPress Search User Guide. PlanetPress Search User Guide www.objectiflune.com 2010 Objectif Lune Inc - 2 - Copyright Information Copyright Information Copyright 1994-2011 Objectif Lune Inc. All Rights Reserved. No part of this publication

More information

DBArtisan 8.6 New Features Guide. Published: January 13, 2009

DBArtisan 8.6 New Features Guide. Published: January 13, 2009 Published: January 13, 2009 Embarcadero Technologies, Inc. 100 California Street, 12th Floor San Francisco, CA 94111 U.S.A. This is a preliminary document and may be changed substantially prior to final

More information

SAP NetWeaver Identity Management Virtual Directory Server. Tutorial. Version 7.0 Rev 4. - Accessing LDAP servers

SAP NetWeaver Identity Management Virtual Directory Server. Tutorial. Version 7.0 Rev 4. - Accessing LDAP servers SAP NetWeaver Identity Management Virtual Directory Server Tutorial - Accessing LDAP servers Version 7.0 Rev 4 SAP Library document classification: PUBLIC No part of this publication may be reproduced

More information

Project management integrated into Outlook

Project management integrated into Outlook Project management integrated into Outlook InLoox PM 7.x off-line operation An InLoox Whitepaper Published: November 2011 Copyright: 2011 InLoox GmbH. You can find up-to-date information at http://www.inloox.com

More information

Performance Optimization for Informatica Data Services ( Hotfix 3)

Performance Optimization for Informatica Data Services ( Hotfix 3) Performance Optimization for Informatica Data Services (9.5.0-9.6.1 Hotfix 3) 1993-2015 Informatica Corporation. No part of this document may be reproduced or transmitted in any form, by any means (electronic,

More information

SQL Optimizer for IBM DB2 LUW User Guide

SQL Optimizer for IBM DB2 LUW User Guide SQL Optimizer for IBM DB2 LUW 4.3.1 User Guide Contents 12 12 Getting Started 13 User Logon Screen 13 Access Plan Table 13 Connect to the Database 14 Loading information from the Data Dictionary 14 User

More information

KB_SQL Release Notes Version 4.3.Q2. Knowledge Based Systems, Inc.

KB_SQL Release Notes Version 4.3.Q2. Knowledge Based Systems, Inc. KB_SQL Release Notes Version 4.3.Q2 Copyright 2003 by All rights reserved., Ashburn, Virginia, USA. Printed in the United States of America. No part of this manual may be reproduced in any form or by any

More information

Oracle SQL. murach s. and PL/SQL TRAINING & REFERENCE. (Chapter 2)

Oracle SQL. murach s. and PL/SQL TRAINING & REFERENCE. (Chapter 2) TRAINING & REFERENCE murach s Oracle SQL and PL/SQL (Chapter 2) works with all versions through 11g Thanks for reviewing this chapter from Murach s Oracle SQL and PL/SQL. To see the expanded table of contents

More information

Service Manager. Database Configuration Guide

Service Manager. Database Configuration Guide Service Manager powered by HEAT Database Configuration Guide 2017.2.1 Copyright Notice This document contains the confidential information and/or proprietary property of Ivanti, Inc. and its affiliates

More information

Oracle FLEXCUBE Investor Servicing BIP Report Development Guide Release 12.0 April 2012 Oracle Part Number E

Oracle FLEXCUBE Investor Servicing BIP Report Development Guide Release 12.0 April 2012 Oracle Part Number E Oracle FLEXCUBE Investor Servicing BIP Report Development Guide Release 12.0 April 2012 Oracle Part Number E51528-01 Contents 1 Preface... 3 1.1 Audience... 3 1.2 Related documents... 3 1.3 Conventions...

More information

Oracle SQL Developer. Oracle TimesTen In-Memory Database Support User's Guide Release 4.0 E

Oracle SQL Developer. Oracle TimesTen In-Memory Database Support User's Guide Release 4.0 E Oracle SQL Developer Oracle TimesTen In-Memory Database Support User's Guide Release 4.0 E39882-02 December 2013 Oracle SQL Developer Oracle TimesTen In-Memory Database Support User's Guide, Release 4.0

More information

SAP Automation (BC-FES-AIT)

SAP Automation (BC-FES-AIT) HELP.BCFESRFC Release 4.6C SAP AG Copyright Copyright 2001 SAP AG. All rights reserved. No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission

More information

Embarcadero DB Optimizer 1.5 SQL Profiler User Guide

Embarcadero DB Optimizer 1.5 SQL Profiler User Guide Embarcadero DB Optimizer 1.5 SQL Profiler User Guide Copyright 1994-2009 Embarcadero Technologies, Inc. Embarcadero Technologies, Inc. 100 California Street, 12th Floor San Francisco, CA 94111 U.S.A. All

More information

Data protection and security in QlikView

Data protection and security in QlikView Author ALH, BMW, HBE, LJN Create date 02-Dec-03 Project Section Access in QlikView Last save date 4-Dec-03 Subject Data protection and security in QV Classification Public Data protection and security

More information

Attaché Server ODBC Installation and User Guide

Attaché Server ODBC Installation and User Guide Attaché Server ODBC Installation and User Guide October 2014 Publication Number Publication Date Product Version Attaché Server version 1.0.0.96 Attaché Software Australia Pty Ltd ACN 002 676 511 ABN 32002676

More information

BEA WebLogic. Adapter for RDBMS. User Guide

BEA WebLogic. Adapter for RDBMS. User Guide BEA WebLogic Adapter for RDBMS User Guide Release 7.0 Document Date: October 2002 Copyright Copyright 2002 BEA Systems, Inc. All Rights Reserved. Copyright 2002 iway Software. All Rights Reserved. Restricted

More information

PL/SQL Developer 10.0 User s Guide. February 2013

PL/SQL Developer 10.0 User s Guide. February 2013 PL/SQL Developer 10.0 User s Guide February 2013 PL/SQL Developer 10.0 User s Guide 3 Contents CONTENTS... 3 1. INTRODUCTION... 9 2. INSTALLATION... 13 2.1 SYSTEM REQUIREMENTS... 13 2.2 WORKSTATION INSTALLATION...

More information

ODBC Client Driver PTC Inc. All Rights Reserved.

ODBC Client Driver PTC Inc. All Rights Reserved. 2017 PTC Inc. All Rights Reserved. 2 Table of Contents 1 Table of Contents 2 4 Overview 4 External Dependencies 4 Setup 5 Channel Properties General 5 Channel Properties Write Optimizations 6 Channel Properties

More information

CA Gen. Distributed Processing - Client Manager User Guide. Release 8.5

CA Gen. Distributed Processing - Client Manager User Guide. Release 8.5 CA Gen Distributed Processing - Client Manager User Guide Release 8.5 This Documentation, which includes embedded help systems and electronically distributed materials, (hereinafter referred to as the

More information

Installation and Configuration Guide Simba Technologies Inc.

Installation and Configuration Guide Simba Technologies Inc. Simba ServiceNow ODBC Driver with SQL Connector Installation and Configuration Guide Simba Technologies Inc. Version 1.1.1 June 30, 2017 Copyright 2017 Simba Technologies Inc. All Rights Reserved. Information

More information

Acknowledgments Introduction. Part I: Programming Access Applications 1. Chapter 1: Overview of Programming for Access 3

Acknowledgments Introduction. Part I: Programming Access Applications 1. Chapter 1: Overview of Programming for Access 3 74029ftoc.qxd:WroxPro 9/27/07 1:40 PM Page xiii Acknowledgments Introduction x xxv Part I: Programming Access Applications 1 Chapter 1: Overview of Programming for Access 3 Writing Code for Access 3 The

More information

COGNOS MANAGEMENT SERIES PLANNING

COGNOS MANAGEMENT SERIES PLANNING COGNOS MANAGEMENT SERIES PLANNING CREATING IMPROMPTU AND IWR REPORTS FROM CONTRIBUTOR PUBLISH TABLES THE NEXT LEVEL OF PERFORMANCE This document applies to Cognos Management Series Planning version 7.1

More information

Question: Which statement would you use to invoke a stored procedure in isql*plus?

Question: Which statement would you use to invoke a stored procedure in isql*plus? What are the two types of subprograms? procedure and function Which statement would you use to invoke a stored procedure in isql*plus? EXECUTE Which SQL statement allows a privileged user to assign privileges

More information

Setting up a database for multi-user access

Setting up a database for multi-user access BioNumerics Tutorial: Setting up a database for multi-user access 1 Aims There are several situations in which multiple users in the same local area network (LAN) may wish to work with a shared BioNumerics

More information

Installation and Configuration Guide Simba Technologies Inc.

Installation and Configuration Guide Simba Technologies Inc. Simba MySQL ODBC Driver Installation and Configuration Guide Simba Technologies Inc. Version 1.0.3 December 5, 2017 Copyright 2017 Simba Technologies Inc. All Rights Reserved. Information in this document

More information

Sage X3 Intelligence Financial Reporting. Installation and Upgrade Guide

Sage X3 Intelligence Financial Reporting. Installation and Upgrade Guide Financial Reporting Installation and Upgrade Guide The software described in this document is protected by copyright, and may not be copied on any medium except as specifically authorized in the license

More information

Quest Code Tester for Oracle 3.1. Installation and Configuration Guide

Quest Code Tester for Oracle 3.1. Installation and Configuration Guide Quest Code Tester for Oracle 3.1 Installation and Configuration Guide Contents Introduction to this Guide 3 Installation and Administration of Code Tester for Oracle 4 System Requirements 5 Test Repository

More information

Steel-Belted RADIUS. Digipass Plug-In for SBR. SBR Plug-In SBR. G etting Started

Steel-Belted RADIUS. Digipass Plug-In for SBR. SBR Plug-In SBR. G etting Started Steel-Belted RADIUS Digipass Plug-In for SBR SBR Plug-In SBR Steel-Belted RADIUS G etting Started Disclaimer of Warranties and Limitations of Liabilities Disclaimer of Warranties and Limitations of Liabilities

More information

CalPlan. Creating a Unit Plan Navigating CalPlan Workbook 1/25/18

CalPlan. Creating a Unit Plan Navigating CalPlan Workbook 1/25/18 CalPlan Creating a Unit Plan Workbook 1/25/18 Table of Contents Exercise 1: Log into the Workspace & Run a CalPlan Report... 3 Exercise 2: Launching CalPlan and Setting Your Entity... 10 Exercise 3: Actualized

More information

BIS Database Management Systems.

BIS Database Management Systems. BIS 512 - Database Management Systems http://www.mis.boun.edu.tr/durahim/ Ahmet Onur Durahim Learning Objectives Database systems concepts Designing and implementing a database application Life of a Query

More information

MIS Database Systems.

MIS Database Systems. MIS 335 - Database Systems http://www.mis.boun.edu.tr/durahim/ Ahmet Onur Durahim Learning Objectives Database systems concepts Designing and implementing a database application Life of a Query in a Database

More information

Oracle Warehouse Builder 10g Runtime Environment, an Update. An Oracle White Paper February 2004

Oracle Warehouse Builder 10g Runtime Environment, an Update. An Oracle White Paper February 2004 Oracle Warehouse Builder 10g Runtime Environment, an Update An Oracle White Paper February 2004 Runtime Environment, an Update Executive Overview... 3 Introduction... 3 Runtime in warehouse builder 9.0.3...

More information

Conversion Guide. Introduction Welcome to the Conversion Guide... 2 Copyright & Trademarks... 2 Sales and Support... 2

Conversion Guide. Introduction Welcome to the Conversion Guide... 2 Copyright & Trademarks... 2 Sales and Support... 2 1 Conversion Guide Introduction Welcome to the Conversion Guide... 2 Copyright & Trademarks... 2 Sales and Support... 2 Conversion What is a Conversion?... 3 Key Recommendations... 3 Additional Conversion

More information

Real Application Security Administration

Real Application Security Administration Oracle Database Real Application Security Administration Console (RASADM) User s Guide 12c Release 2 (12.2) E85615-01 June 2017 Real Application Security Administration Oracle Database Real Application

More information

Omnis Programming. TigerLogic Corporation. June

Omnis Programming. TigerLogic Corporation. June Omnis Programming TigerLogic Corporation June 2013 20-062013-02 The software this document describes is furnished under a license agreement. The software may be used or copied only in accordance with the

More information

SyteLine ERP. Installation Guide. MAPICS, Inc Windward Concourse Parkway Suite 100 Alpharetta, GA Version 7.03.

SyteLine ERP. Installation Guide. MAPICS, Inc Windward Concourse Parkway Suite 100 Alpharetta, GA Version 7.03. SyteLine ERP Installation Guide Version 7.03.00 MAPICS, Inc. 1000 Windward Concourse Parkway Suite 100 Alpharetta, GA 30005-8001 www.mapics.com Installation Guide Copyright MAPICS, Inc. 2004 All Rights

More information

Oracle Database 11g: SQL and PL/SQL Fundamentals

Oracle Database 11g: SQL and PL/SQL Fundamentals Oracle University Contact Us: +33 (0) 1 57 60 20 81 Oracle Database 11g: SQL and PL/SQL Fundamentals Duration: 5 Days What you will learn In this course, students learn the fundamentals of SQL and PL/SQL

More information

TIBCO ActiveMatrix BPM Spotfire Visualizations

TIBCO ActiveMatrix BPM Spotfire Visualizations TIBCO ActiveMatrix BPM Spotfire Visualizations Software Release 3.0 May 2014 Two-Second Advantage 2 Important Information SOME TIBCO SOFTWARE EMBEDS OR BUNDLES OTHER TIBCO SOFTWARE. USE OF SUCH EMBEDDED

More information

InQuira Analytics Installation Guide

InQuira Analytics Installation Guide InQuira Analytics Installation Guide Installing and Configuring InQuira Analytics Applications InQuira Version 8.1.2 Document Number IA80-IG-00 August 27, 2008 InQuira 851 Traeger Ave. Suite 125 San Bruno,

More information

Logi Ad Hoc Reporting System Administration Guide

Logi Ad Hoc Reporting System Administration Guide Logi Ad Hoc Reporting System Administration Guide Version 10.3 Last Updated: August 2012 Page 2 Table of Contents INTRODUCTION... 4 Target Audience... 4 Application Architecture... 5 Document Overview...

More information

IBM VisualAge for Java,Version3.5. External Version Control

IBM VisualAge for Java,Version3.5. External Version Control IBM VisualAge for Java,Version3.5 External Version Control Note! Before using this information and the product it supports, be sure to read the general information under Notices. Edition Notice This edition

More information