Omnis Programming
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 terms of the agreement. Names of persons, corporations, or
products used in the tutorials and examples of this manual are fictitious. No part of this publication may
be reproduced, transmitted, stored in a retrieval system or translated into any language in any form by
any means without the written permission of TigerLogic.
TigerLogic Corporation, and its licensors 2013. All rights reserved.
Portions Copyright Microsoft Corporation.
Regular expressions Copyright (c) 1986,1993,1995 University of Toronto.
1999-2013 The Apache Software Foundation. All rights reserved.
This product includes software developed by the Apache Software Foundation
(http://www.apache.org/).
OMNIS and Omnis Studio are registered trademarks of TigerLogic Corporation.
Microsoft, MS, MS-DOS, Visual Basic, Windows, Windows 95, Win32, Win32s are registered
trademarks, and Windows NT, Visual C++ are trademarks of Microsoft Corporation in the US and other
countries.
SAP, R/3, mySAP, mySAP.com, xApps, xApp, and other SAP products and services mentioned herein
as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and
in several other countries all over the world.
IBM, DB2, and INFORMIX are registered trademarks of International Business Machines Corporation.
ICU is Copyright 1995-2003 International Business Machines Corporation and others.
UNIX is a registered trademark in the US and other countries exclusively licensed by X/Open Company
Ltd.
Sun, Sun Microsystems, the Sun Logo, Solaris, Java, and Catalyst are trademarks or registered
trademarks of Sun Microsystems Inc.
J2SE is Copyright (c) 2003 Sun Microsystems Inc under a licence agreement to be found at:
http://java.sun.com/j2se/1.4.2/docs/relnotes/license.html
MySQL is a registered trademark of MySQL AB in the United States, the European Union and other
countries (www.mysql.com).
ORACLE is a registered trademark and SQL*NET is a trademark of Oracle Corporation.
SYBASE, Net-Library, Open Client, DB-Library and CT-Library are registered trademarks of Sybase
Inc.
Acrobat is a trademark of Adobe Systems, Inc.
Apple, the Apple logo, AppleTalk, and Macintosh are registered trademarks and MacOS, Power
Macintosh and PowerPC are trademarks of Apple Computer, Inc.
HP-UX is a trademark of Hewlett Packard.
OSF/Motif is a trademark of the Open Software Foundation.
CodeWarrior is a trademark of Metrowerks, Inc.
This software is based in part on ChartDirector, copyright Advanced Software Engineering
(www.advsofteng.com).
This software is based in part on the work of the Independent JPEG Group.
This software is based in part of the work of the FreeType Team.
Other products mentioned are trademarks or registered trademarks of their corporations.
Table of Contents
Table of Contents
ABOUT THIS MANUAL.....................................................7
CHAPTER 1THE OMNIS ENVIRONMENT ...............8
STUDIO BROWSER ...................................................................9
OMNIS PREFERENCES ............................................................11
STUDIO TOOLBARS AND MENUS ............................................12
CONTEXT MENUS ..................................................................17
FIND AND REPLACE ...............................................................19
COMPONENT STORE ..............................................................20
PROPERTY MANAGER ............................................................21
NOTATION INSPECTOR ...........................................................24
CATALOG...............................................................................27
SQL BROWSER ......................................................................28
SQL QUERY BUILDER ...........................................................31
VERSION CONTROL SYSTEM ..................................................40
OMNIS HELP ..........................................................................41
CHAPTER 2LIBRARIES AND CLASSES ..................43
OMNIS LIBRARIES ..................................................................43
DEFAULT CLASSES ................................................................46
CLASS TYPES.........................................................................48
CLASS TEMPLATES AND WIZARDS.........................................49
DATA CLASSES AND WIZARDS ..............................................50
OMNIS DATA TYPES ..............................................................51
SCHEMA CLASSES ..................................................................61
QUERY CLASSES....................................................................62
TABLE CLASSES ....................................................................62
CHAPTER 3OMNIS PROGRAMMING .....................64
VARIABLES ............................................................................65
METHODS ..............................................................................71
EVENTS .................................................................................93
USING TASKS.......................................................................104
EXTERNAL COMPONENT NOTATION ....................................113
CHAPTER 4DEBUGGING METHODS ....................117
INSERTING AND EDITING METHODS .....................................118
DEBUGGING METHODS ........................................................119
Table of Contents
INSPECTING VARIABLE VALUES ..........................................123
WATCHING VARIABLE VALUES ...........................................124
BREAKPOINTS ......................................................................125
THE METHOD STACK...........................................................127
DEBUGGER OPTIONS ...........................................................128
DEBUGGER COMMANDS ......................................................129
CHECKING METHODS ..........................................................130
METHOD PERFORMANCE .....................................................134
SEQUENCE LOGGING ...........................................................135
CHAPTER 5OBJECT ORIENTED PROGRAMMING136
INHERITANCE ......................................................................136
CUSTOM PROPERTIES AND METHODS ..................................143
OBJECT CLASSES .................................................................147
OBJECT REFERENCES ..........................................................152
EXTERNAL OBJECTS ............................................................154
INTERFACE MANAGER .........................................................156
CHAPTER 6LIST PROGRAMMING .......................158
DECLARING LIST OR ROW VARIABLES.................................159
DEFINING LIST OR ROW VARIABLES ....................................160
BUILDING LIST VARIABLES..................................................163
LIST AND ROW FUNCTIONS ..................................................164
ACCESSING LIST COLUMNS AND ROWS ...............................165
LIST VARIABLE NOTATION ..................................................165
MANIPULATING LISTS ..........................................................171
SMART LISTS .......................................................................174
CHAPTER 7SQL PROGRAMMING.........................181
OVERVIEW...........................................................................182
SETTING UP A DATABASE CONNECTION...............................182
CONNECTING TO YOUR DATABASE ......................................183
INTERACTING WITH YOUR SERVER ......................................185
LISTING DATABASE OBJECTS ..............................................199
REMOTE PROCEDURES ........................................................202
TRANSACTIONS ...................................................................205
CURSOR RESULTS SETS .......................................................208
STRIPPING SPACES ...............................................................213
TREATMENT OF DATE VALUES ............................................213
LARGE OBJECTS ..................................................................214
SESSION POOLS ...................................................................215
DIAGNOSING PROBLEMS ......................................................218
SESSION AND STATEMENT PROPERTIES AND METHODS .......219
SQL MULTI-TASKING AND SQL WORKERS .........................227
4
Table of Contents
CHAPTER 8SQL CLASSES AND NOTATION .......236
SCHEMA CLASSES ...............................................................236
QUERY CLASSES..................................................................238
CREATING SERVER TABLES FROM SCHEMA OR QUERY CLASSES 241
TABLE CLASSES ..................................................................242
TABLE INSTANCES ...............................................................242
SQL CLASSES AND SESSIONS ..............................................254
CHAPTER 9SERVER-SPECIFIC PROGRAMMING257
ORACLE ...............................................................................258
SYBASE ...............................................................................277
DB2 ....................................................................................290
MYSQL...............................................................................295
POSTGRESQL ......................................................................305
SQLITE ................................................................................319
ODBC .................................................................................327
JDBC ..................................................................................341
AMAZON SIMPLEDB DAM..................................................346
CHAPTER 10REPORT PROGRAMMING ..............361
REPORT FIELDS AND SECTIONS............................................361
REPORT WIZARD .................................................................362
REPORT TOOLS ....................................................................362
REPORT SECTIONS ...............................................................363
SECTION POSITIONING .........................................................366
SORTING AND SUBTOTALING ...............................................369
PRINTING REPORTS ..............................................................371
REPORT AND FIELD METHODS .............................................375
PRINT DEVICES AND THE CURRENT DEVICE ........................377
GLOBAL PRINTING PREFERENCES ........................................380
REPORT INSTANCES .............................................................383
REPORT FIELD AND SECTION METHODS ..............................386
REPORT OBJECT POSITIONING .............................................387
REPORT INHERITANCE .........................................................392
REPORT FONTS ....................................................................393
REPORT TEXT LABELS .........................................................394
PORT PROFILES....................................................................395
LABELS................................................................................397
HTML REPORT DEVICE ......................................................398
CHAPTER 11UNICODE .............................................402
WHAT IS UNICODE? .............................................................402
OMNIS DATA FILE CONVERSION ..........................................403
DAMS .................................................................................404
5
Table of Contents
CHARACTER NORMALIZATION .............................................409
CHARACTER TRANSLATION .................................................412
UNICODE CLIENTS ...............................................................412
UNICODE DATA HANDLING .................................................413
IMPORT/EXPORT AND REPORT FILE ENCODING ...................415
CHAPTER 12LOCALIZATION.................................417
LOCALIZING YOUR LIBRARIES .............................................417
LOCALIZING OMNIS .............................................................428
LOCALIZING THE OMNIS RUNTIME.......................................430
CHAPTER 13VERSION CONTROL.........................435
OVERVIEW...........................................................................436
SETTING UP A PROJECT ........................................................437
CHECKING IN COMPONENTS ................................................441
USING THE VCS ..................................................................446
MANAGING COMPONENTS ...................................................458
VCS OPTIONS......................................................................464
REPORTS .............................................................................467
INDEX ...............................................................................468
Studio Browser
Omnis Studio shown here on Windows 7, but it looks virtually the same on OS X or Linux.
Studio Browser
This contains useful information about the product and sample web apps, and it provides
access to the online Tutorial. When you close the Welcome window, you will see the Studio
Browser.
Note: Some editions of Omnis Studio may not provide access to all the development tools
or web/mobile development features, such as the Omnis VCS or the DAMs in the SQL
Browser.
Studio Browser
The Studio Browser is the main window in Omnis Studio for developing your applications
and managing server database sessions. The hierarchical folder list down the left side
contains a list of all open Libraries, Omnis Data Files, SQL database sessions, and provides
access to the Omnis Version Control System (VCS); the SQL Browser and VCS are not
available in some editions of Omnis Studio. The toolbar at the top of the Studio Browser
window lets you navigate around the Omnis environment and change its view options. For
example, the Folders button option lets you hide and show the hierarchical folder list. You
can right-click on the Browser to change its view options (Large or Small icons, or Details
view), and the Save Window Setup option lets you save the current settings.
The Studio Browser showing the contents of a library in Large Icons view.
The right hand pane displays a list of objects or files for the current folder, e.g. it displays
all the classes in a library when a library is selected in the Folders list on the left. The list of
Options (they look like hyperlinks) will change depending on the object currently selected
Library Folders
The Studio Browser lets you create folders in a library so you can organize the classes
within each library. Folders are in fact Omnis classes, but for display only (they are visible
during development only). Folders do not perform any function in your library, other than
organizing your classes, and they are ignored at runtime.
To hide/show library folders within the Browser, select your library and click on the
Library folders option, or alternatively, right-click on the white space of the Browser
(when any library is selected) and select the Library Folders option from the context
menu. You can save the state of this option using the Save Window Setup option for the
Browser.
Displays...
all classes
windows only
files only
reports only
searches only
menus only
object classes only
Shift +
Ctrl/Cmnd +
J
C
T
S
U
B
Y
Displays...
tasks only
code classes only
toolbars only
schemas only
query classes only
tables only
system tables only
The Class Filter allows you to specify which types of class are shown in the Studio Browser
or not. To open the Class Filter, press the F7 key or click on the Class Filter (on/off) option
in the Studio Browser.
Recent Classes
Any classes that you have opened recently are listed in the Recent Classes popup list
displayed at the bottom of the Studio Browser. To open a class, you click on the list and
select the class name. The class will be displayed in the appropriate class editor.
10
Omnis Preferences
You can open the method editor or Interface Manager for a class (that is, a class that can
contain methods) from the Recent Classes list in the Studio Browser. To open the method
editor for a class, click on the Recent Classes list and hold down the Shift key and select the
class, or to open the Interface Manager for a class, hold down the Control/Command key
while selecting the class in the Recent classes list.
Omnis Preferences
The Omnis preferences or Options control the overall behavior of Omnis itself, rather than
individual libraries, and include groups of preferences for: General options, Appearance,
Devices, Methods, and Page Setup. You can change the Omnis preferences in the Property
Manager. The Omnis preferences are sometimes referred to as the Omnis Root
Preferences, since they are properties of the Omnis Root object (in the notation they are
referred to using $root.$prefs.<property-name>).
To view the Omnis preferences
or
Click on Studio in the Studio Browser and click on the Prefs option
11
Standard toolbar
The Standard toolbar has more-or-less the same options as the File menu. In addition, the
File menu lets you create new libraries and open existing libraries.
The Save option (Ctrl/Cmnd-S) saves the class you are currently working on. If a class
design window is not currently selected this option is grayed out.
The Revert option rolls back any changes you have made to the class you are currently
working on. Note that if you close an Omnis class it will be saved automatically and
therefore cannot be reverted.
The Dest option opens the Print Destination (Shift-Ctrl/Cmnd-P) dialog which lets
you set the destination of the current output. Reports are sent to the Screen by default,
but you can choose another destination from this dialog.
The Print option (Ctrl/Cmnd-P) prints the current class or report to current destination,
if applicable. For example, when you are working in the method editor the option prints
the currently selected method or set of class methods.
12
View toolbar
The View toolbar opens the main Studio Browser and other tools available in the Studio
development environment, and has the same options as the View menu. Many of these tools
are described in greater detail later in this chapter.
The Browser option (F2/Cmnd-2) opens the Studio Browser which lets you create and
examine libraries and classes. If the Studio Browser is already open and in Single
Window Mode this option will bring it to the top. If the Browser allows multiple copies
of itself, this option opens the initial Browser displaying the libraries.
The CStore option (F3/Cmnd-3) opens the Component Store which contains data and
GUI objects, as well as external components, to allow you to build windows, web
forms, and reports. This option will be grayed out if there is no design window or
report on top. (Note you create classes from the Studio Browser itself, so this option
will be grayed out when a library is selected in the main Studio Browser.)
The Notation option (F4/Cmnd-4) opens the Notation Inspector which lets you view
the complete Omnis notation tree. If the Notation Inspector is already open and in
Single Window Mode this option will bring it to the top. If the Notation Inspector
allows multiple copies of itself, this option opens a new instance of the Notation
Inspector. When you open the Notation Inspector the Property Manager will also open.
The Props option (F6/Cmnd-6) opens the Property Manager which lets you view or
change the properties of an object; the properties displayed in the Property Manager
will depend on the object or window currently selected or on top in the Omnis
development environment. If the Property Manager is already open, this option will
bring it to the top.
The Catalog option (F9/Cmnd-9) opens the Catalog which lists all the field names and
variables in your library, together with the functions, constants and event messages. If
the Catalog is already open this option will bring it to the top.
In addition, the View menu contains the Inheritance option:
The Inheritance Tree option (F5/Cmnd-5) lets you view the inheritance or
superclass/subclass hierarchy in the current library. If you select a class in the Browser
and open the Inheritance Tree it shows the inheritance for that class.
13
Tools toolbar
The Tools toolbar lets you edit the global Omnis preferences, open the Trace log, the
Omnis Icon Editor, Export & Import data, open the Ad hoc report tool, and so on.
The Trace Log option displays the trace log which is a record of the operations and
commands you have carried out. See the Debugging Methods chapter in the Omnis
Programming manual for further details.
The New Users option lets you open the New Users section of the Welcome
application: in particular you can view many sample Omnis libraries from New Users,
as well as view the tutorial.
The Add-Ons option lets you open various additional tools, including:
Character Map Editor, for mapping local and server character data
Compare Classes tool, for comparing the methods in classes and libraries
Method Checker, for checking methods in classes and libraries
ODBC Admin tool, for setting up ODBC access to Omnis datafiles
Port Profile editor, for setting up your ports
String Table Editor, for providing multi-languages in your application
Web Client Tools, for configuring your Omnis web and mobile apps
14
Desktop toolbar
The Desktop toolbar (hidden by default) lets you toggle between the design environment
and a simulated Runtime environment so you can see your application in user mode. You
can also change the mode using the Desktop option in the File menu.
In Design mode the standard menus, such as File, Edit, View, and Tools toolbars are
visible. In Runtime mode all these are hidden and only user menus, data entry windows and
toolbars defined in your library are visible. Also in runtime mode there is a cut-down
version of the File and Edit menus on the main menu bar. Being able to switch to Runtime
mode lets you see exactly how your application will look when the user runs it. In
Combined mode (the default) all design and user menus, windows, dialogs, and toolbars are
visible. When you select the Runtime option, the Desktop toolbar is installed so you can get
back to the Combined mode.
Under Windows Vista, the main Omnis menu bar may not be visible, but you can press the
Alt key to display it temporarily. To display it permanently, do the following:
Right-click/Ctrl-click on the main Omnis toolbar and
select the Menu Bar option to show it permanently on
the main Studio window.
The other options on the Toolbar context menu let you
configure the main toolbars in Omnis Studio. The
Toolbar Options option let you install or remove the
Standard, View, Tools and Desktop toolbars
15
Tools menu
The New Users option lets you open the New
Users section of the Welcome application: in
particular you can view many sample Omnis
libraries from New Users, as well as view the
tutorial.
The Help Project Manager lets you build help
into your own libraries for the benefit of your own
users; it is described in the Omnis Programming
manual.
The Add-Ons option lets you open various
additional tools (described in the Tools toolbar
section)
The Export Data option lets you export data from
an Omnis data file (not a SQL database) using a
number of different data formats. While the
Import Data option lets you import data into a data file from an existing export file or
text file from
another application. For further details about importing
and exporting data see the
Omnis Programming manual.
The Icon Editor option opens the Icon Editor which lets you add your own icons to
Omnis. It is described in the Library Tools chapter in the Omnis Programming manual.
The Trace Log option displays the trace log which is a record of the operations and
commands you have carried out. See the Debugging Methods chapter in the Omnis
Programming manual for further details.
The Options option opens the Property Manager displaying the main Omnis
Preferences, including settings for the Appearance of the Omnis environment, the Print
devices for Omnis reports, the main Page Setup, and Java.
The Change Serial Number option which lets you re-serialize your copy of Omnis,
and add serial numbers for Omnis plug-ins.
16
Context Menus
Context Menus
A context menu is a useful shortcut when you want to modify an object, or change the
Omnis development environment. You can open context menus from almost anywhere in
Omnis by Right-clicking on the object or browser window. On OS X, you can open a
context menu by holding down the Ctrl key and clicking your mouse on the object. The
options in a context menu depend on the object you click on. For example, if you Rightclick on the Studio Browser its View menu will be opened containing options for changing
its view and creating new classes. Note the Save Window Setup which will save the current
setup or view; this useful option is available for many of the Omnis development windows.
The context menu on the Studio Browser lets you change the current view, or create a new class or
folder when a library is visible in the Browser.
17
18
On the Classes tab you can select the libraries and classes in which you want to perform the
find and replace. For a single library you can select some or all of the classes in the library.
If you select more than one library under the Classes tab, all classes in all selected libraries
are searched.
If you click on the Find First button Omnis will jump to the first occurrence of the text
string in your selected classes or libraries. For example, if the specified item is found in a
method Omnis will open the class containing the method with the found item highlighted.
Find Next (Ctrl/Cmnd-G) will jump to the next occurrence of the text string, and so on. The
Find All button finds all occurrences of the specified item in all the classes or libraries you
selected and lists them in the Find log.
19
Renaming objects
When you rename certain objects in your library, Omnis will replace all references to the
object automatically. For example, if you rename a class variable in the method editor
Omnis will replace all references to the variable within the class automatically. However if
you try to rename most other types of object, such as renaming a class in the Browser,
Omnis will prompt you to find and replace references to the object. If you answer Yes to the
prompt, Omnis will open the Find & Replace tool and the Find log which lets you monitor
the find and replace, or control whether or not certain references are replaced.
Component Store
The Component Store contains the objects and components you need to build web and
mobile forms, reports and toolbars. When you create a new class or modify an existing one,
the Component Store will open automatically. For example, when you create or modify a
remote form in your web or mobile app, the Component Store will display the JavaScript
Components.
To create an object, you can drag the appropriate icon from the Component Store and drop
it onto your remote form, report or toolbar. Alternatively, you can select the button in the
Component Store and draw the object on your remote form or report as required.
You can change the view of the Component Store using the View context menu, by Rightclicking/Ctrl-clicking inside the Component Store and selecting the options you require. For
example, you can select the Text option to display the name of each component (as shown).
You may find this helps you identify each type of component while you become familiar
20
Property Manager
with Omnis. You can also resize the window to place it along the bottom or down the right
side of the Omnis development window.
When you have set up the Component Store how you want it, you can save the view options
using the Save Window Setup option in the context menu.
Property Manager
The Property Manager lets you display or change the properties of the currently selected
object. This could be a library, a window or the Omnis global preferences. The Property
Manager will normally appear automatically when needed; if it is not visible you can
display it either by selecting the View>>Property Manager menu item from the main menu
bar, by pressing F6/Cmnd-6, or by selecting the Properties option from an objects context
menu.
The properties of an object are shown in the
Property Manager in alphabetical order by
default, but you can list them functionally by
unchecking the Sort by Property Name
option in the Property Manager context
menu.
The other options in the Property Manager
context menu affect the behavior of the
Property Manager. If set, the Hold Updates
option stops the Property Manager updating
its contents automatically when you click on
another object. For example, you can click
on a window class to show its properties in
the Property Manager, select the Hold
Updates option, click on a field in the
window, and the Property Manager still
displays the properties of the window. Most
of the time however youll want this option
turned off so the Property Manager updates
itself automatically.
21
Property Descriptions
The Help tips option in the Property Manager context menu displays short descriptive help
messages for each property in the Property Manager: this is particularly useful for showing
the parameters of a method. The Show Runtime Properties option lets you view properties
that are normally available in runtime only, that is, properties of an instance rather than a
design class. When runtime properties are visible in the Property Manager the methods for
the instance are also shown. You cannot set runtime properties or run methods from the
Property Manager itself, but you can drag references to them into your code in the method
editor (see below).
Note you drag a property or a method (and its parameters) from the Property Manager into
the Method Editor when you are writing code: see Dragging Methods below.
Copying Properties
The Copy Properties option lets you copy all the properties of one object and paste or
apply them to another object of the same type: this is useful if you want to reproduce or
duplicate a particular object, or even apply the properties of a built-in field to an external
component.
When you have set up the Property Manager how you want it, you can save the view
options using the Save Window Setup option in the context menu.
22
Property Manager
When you drag a method out of the Property Manager and drop it onto your code, its full path and
parameters are copied as well. You can click in your code and edit the path and replace the parameters
with your own variable names.
23
Notation Inspector
Omnis structures its objects in an object tree, or hierarchical arrangement of objects and
groups that contain other objects. The complete tree contains all the objects in Omnis itself,
together with your design libraries, classes, and other objects created at runtime. You can
view the complete object tree in the Notation Inspector.
To facilitate a system of naming or referring to an object in the object tree, and its
properties and methods, Omnis uses a system called the notation. The notation for an object
is really the path to the object within the object tree. The full notation for an object is shown
in the status bar of the Notation Inspector. You can use the notation to execute a method or
to change the properties of an object, and you can use a notation string anywhere you need
to reference a variable or field name.
The Notation Inspector therefore lets you view the Omnis object tree from the $root object
down. It is particularly useful for viewing the contents of your library and finding the right
notation for a particular object or group of objects in your library. For example, you can get
the notation for an object on a design or open window using the Notation Search tool on the
Notation Inspector toolbar. When you click on an object or group in the Notation Inspector
the Property Manager will display its properties and methods.
The Notation Inspector lets you drill down the hierarchy of objects within the Omnis tree; for example,
you can view the object tree for an open remote form in the $iremoteforms group; when you click on an
24
Notation Inspector
open remote form name, the Property Manager displays the runtime properties and methods of the
form.
When the Notation Inspector opens it shows the $root object which contains all the objects
in the Omnis object tree including all your open libraries and their contents. It also includes
all the objects and groups created at runtime when you run your application. You can
expand each branch of the tree to show the contents of an object or group.
All the different types of class in your library are shown in Notation Inspector within their
respective object group. For example, all the window classes in your library are contained in
the $windows group. Likewise all the toolbar classes are contained in the $toolbars group.
Note that the $classes group contains all the classes in your library. Also note that a group
may be empty if your library does not contain any classes of that type.
You can click the Search button, then click on a button or other object on an open window and view its
notation in the Notation Inspector; the tree is redrawn and you can drill down to the view the contents of
the object.
25
Notation Helper
The Notation Helper is built into the Method Editor and assists you in writing Omnis
notation. When you are typing a notation string into the calculation field of the method
editor you can pause to allow the Notation Helper to popup a list of possible properties,
methods, and variable names that can be used in the current notation string; the list is
context-sensitive, therefore as you type the first few characters of a property, method, or
variable name Omnis modifies the contents of the list accordingly. For example, if you type
Do $cinst.$sen the list pops up containing $sendall(), $senddata(), $setcurfield, and so on.
The list will display all methods and variables from the superclass of the current class if it is
a subclass.
When the list pops up you can use the up and down arrow keys, and then the Return key to
select the property, method, or variable you require, or you can use your mouse.
26
Catalog
Catalog
The Catalog lists all the variables, schema & query class columns, and string tables in your
library, in addition to listing all Omnis functions, constants, event codes, and hash variables.
The Catalog lists all the variables for the current object including task, class, instance, local,
and parameter variables, and also event parameters. For example, if you are working in a
window class the Catalog will show the class and instance variables for that window class.
In addition, when you select a particular method in the method editor, the Catalog will list
the local and parameter variables for that method.
27
SQL Browser
The SQL Browser lets you access and interact with a number of remote server databases,
including Oracle, MySQL, PostgreSQL, OpenBase and SQLite. Omnis Studio provides a
separate Data Access Module (DAM), or Object DAM, to connect directly to each server
database. In addition, the SQL Browser contains a JDBC DAM and an ODBC DAM that
allow you to access JDBC- and ODBC-compliant databases, such as MS SQL Server, and
many others. The SQL Browser contains a session template for each database server
supported in Omnis.
The SQL Browser contains a session template for each supported server database including Oracle,
MySQL, PostgreSQL, OpenBase, and SQLite, as well as generic JDBC and ODBC connections. Note
that, in some cases, a session template may not be displayed if the appropriate clientware is not
installed on your computer.
The SQL Browser also contains an Omnis SQL DAM that lets you access an Omnis data
file using SQL methods rather than the Omnis Data Manipulation Language (DML).
28
SQL Browser
To create a new session to your database
Click on the SQL Browser option in the Studio Browser, then click on the Session
Manager option
Select the type of database you want to connect to and click the Duplicate Session
option
Rename the session using a suitable name for your database
Double-click the session template and modify the parameters in the Modify Session
dialog
When you create or modify a database session you need to select the DBMS vendor, the
Data Access Module (DAM) and version, as well as specifying the Username and Password
for the session. The connection parameters required will vary depending on your database.
29
Click on the Open Session option and then the session name
If you use the Show Data option on the SQLite database used in the tutorial, you can view the text and
images in the database.
Once you have created your database session you can view your data using the Interactive
SQL tool, as above, or create windows and forms based on the session using the SQL Form
Wizard in the Studio Browser.
Note that the Tutorial in this manual shows how you can build a SQL form to access data
via a web browser on a desktop PC or mobile device.
30
31
Creating a Query
The SQL Query Builder allows you to construct most types of query simply using drag and
drop and the context menus available as appropriate in each pane of the main SQB window.
In order to construct a query, you must be logged on to a SQL session via the SQL Browser.
The first time you open the SQB the query list will be empty allowing you to create a new
query. If an existing query is currently displayed pressing either the New toolbar button or
selecting <new query> from the query dropdown list will clear the query from the screen.
Adding a Table
Once a SQL session has been selected a list of tables for the current session is shown in the
left hand pane. To include a table in a SQL Query simply drag the table into the main design
area on the right.
Removing a Table
You can remove a table from a query either by clicking on the X icon for the table or by
opening the context menu for the table and selecting Remove Table. You have to confirm
if you want to remove a table from the current query.
Refreshing a Table
If a table has been modified outside the SQB, you can refresh the table in the SQB by rightclicking on the table and selecting Refresh Table from the context menu. This option will
add any new columns or remove any deleted columns to reflect the current state of the
server table.
Selecting Columns
Once a table has been added, you can select columns by selecting their names individually
or by right-clicking on the table you can check or uncheck all the columns in the table.
Alternatively, you can specify that the SQB checks all columns automatically when a table
is added using the Select all Columns on drop option within the Options dialog (see the
Options section).
32
You can reorder columns in this pane by dragging and dropping column names in the list.
Creating Joins
To construct your queries, you can create joins between tables either using drag and drop in
the main SQB design area or using the Table Joins dialog. To create a join, drag a column
name from one table and drop it onto the column name within the table you wish to join
with. Alternatively, you can right-click on a table to open the Table Joins dialog from the
context menu.
33
34
35
Running a Query
You can run the current query from the main toolbar in the SQB window using the Build
and Run or Run option. Both buttons switch the main pane to the Results pane showing
the SQL script and results generated by the Query. You can make changes to the SQL script
generated if required and the query can be executed again using the Run button. Note that
using the Build and Run option will rebuild the statement from the saved query text and
therefore overwrite any changes you may have made.
Any errors which occur are reported in the status bar. If the full error text is not displayed,
you can click on the status bar to open a dialog showing the full error text.
Saving a Query
You can save a query using the Save or Save As toolbar option. When using Save
option for the first time, or the Save As option, you can add a description for the query.
The description is also available to view/edit via the Query Info option of the main context
menu. Once saved, a Query is added to the list of Queries available in the dropdown list in
the main SQB toolbar.
36
Deleting a Query
The Delete button in the SQB toolbar button lets you delete the currently selected query
(you must confirm the deletion).
Query Reports
There are two types of report available via the Print button on the main toolbar or the
context menu opened by right-clicking on the Query design pane: both these options open
the Print Query dialog that allows you to print either the Structure or the Results of the
current query. In addition, you can include the generated SQL Script from the last executed
SQL query in both reports.
37
Query Info
The Query Info dialog available from the main query context menu displays information
about the current query. You can change the name and description of query.
38
Options
You can set various options for the SQL Query Builder in the Options dialog which is
available from the context menu on the main query window. You can specify the line and
color styles for joins, and you can set preferences for dragging and dropping during table
creation.
For databases where table names are prefixed by a username, the Omit Username option is
particularly useful when running the same query against different databases where the
username is different, but the table and column names are the same.
39
40
Omnis Help
Omnis Help
In design mode, Omnis provides many different types of help: tooltips and helptips over
toolbar controls; help text for the main menus shown in the status bar at the bottom of the
Omnis application window; and a fully context-sensitive Help system, available by pressing
F1 or via the Help menu. Omnis also provides Whats This? help for individual functions
and commands while youre working in the Method Editor; Whats This type help is not
provided for the main tools in the Omnis IDE. (Note that under Windows Vista you need to
press the Alt key to show the main Omnis menus, including the Help menu, or you can show
it by Right/Ctrl-clicking on the Omnis toolbar and selecting the Menu bar option.)
41
You can create your own Help system and add it to your own application; creating your own
help is described in the Omnis Programming manual. Note that the Omnis Help available in
the development version of Omnis is located in the omnis\idehelp folder.
42
Omnis Libraries
Omnis Libraries
Each library file contains a number of system classes and preferences that control the
behavior of your library and its contents. A library has certain properties too, which you can
examine and change using the Property Manager.
You can create and open any number of library files and each library can contain any
number of classes. In fact you may want to split your whole application into one or more
libraries and store different types of objects in different libraries. Alternatively, you can
develop your classes, check them into the Omnis VCS and put them into a library file when
you build your final application.
43
Start Omnis and open the Studio Browser; if the Studio Browser is not open you can
press F2/Cmnd-2 to open it
Click on the New Library option in the Studio Browser
Enter a name for the new library in the New Library dialog, including the file extension
.LBS, and click on OK
When you name a new library you can use the file naming standards for the current
operating system. The .LBS file extension is not obligatory, but it will help you distinguish
library files from other types of file. The new library is opened in the Studio Browser and
shown as a single icon in icon view, or as a single line in details view.
Library Properties
A library has a set of properties or preferences that control how it behaves. You can use the
Property Manager to display or change the properties of a library.
To view the properties of a library
Select the library icon or name in the Studio Browser and press F6/Cmnd-6 to open the
Property Manager
or
The Property Manager displays the properties of the currently selected library. You can
move you mouse over a of the property to display its help text. The library preferences are
displayed under the Prefs tab in the Property Manager.
44
Omnis Libraries
Multi-library Projects
Omnis lets you structure your application into one or more libraries that you can load either
together or separately. This lets you
break up your application into smaller, less complex subsystems
develop the subsystems in different programming groups or departments
test the subsystems or modules separately
reuse libraries in different applications, mixing and matching reusable code without
modification
Although Omnis always ensures the integrity of objects, there is no built-in locking or
concurrency checking to prevent two users from modifying the same object. If more than
one user opens an object in design mode, the last one to close the object overwrites the
changes made by the other users. There is no way to ensure that changes made to an object
are seen by other users before the library is reopened: objects are cached in memory and it
is not possible to predict when Omnis will discard an object from the cache. In a team of
developers you should therefore use the Omnis VCS.
Omnis VCS
The Omnis VCS provides you with a full-featured version control system for your Omnis
libraries and other components. If you put your application under version control, you
eliminate the inherent risks involved in group development. See later in this manual for
details about the Omnis VCS.
Comparing Classes
The Studio Browser includes a tool that lets you compare classes in two different versions
of the same Omnis library or different revisions of the same class in a VCS project. The
Compare Classes tool lets you compare all the classes in one library or VCS project or
individual classes. To use the new tool, click on the Compare Classes option in the Studio
Browser.
45
Default Classes
When you create a new library in Omnis, it contains certain default classes including a task
class called Startup_Task and various System Classes that control the behavior and
appearance of your library. As you begin to prototype your application, you dont need to
modify the default classes, but this section gives you a brief overview of how they affect
your library.
System classes
Every new library contains a number of System Classes, contained in a folder called
System Classes. You can hide or show them using the Class Filter option in the Studio
Browser. Many of the system classes relate to desktop apps only, and are therefore
irrelevant for web and mobile apps.
System classes are special types of class that hold information about the Omnis
environment, including field styles, fonts, input masks, and external components. You can
edit some of the system classes to change the way Omnis behaves. The settings for these
tables are stored for each separate library. You can copy system classes from one library to
another and you can edit them, but some options available for normal classes are not
available for these tables. Like other classes, you can check system classes into the Omnis
VCS.
46
Default Classes
The system classes are as follows.
Name
Description
#BFORMS
#DFORMS
#EXTCOMPLIBS
#ICONS
#MASKS
#NFORMS
#PASSWORDS
#STYLES
#TFORMS
#WIRFONTS
#MARFONTS
#UXRFONTS
#MXRFONTS
#WIWFONTS
#MAWFONTS
#UXWFONTS
#MXWFONTS
You can edit a system table by double-clicking on it in the Browser. For example, you can
double-click on #DFORMS which opens the Date formats dialog showing all the date
formats for the current library.
47
Class Types
There are several different types of class in Omnis, each one performing a particular
function in your library, or your app as a whole. In general, classes are either Data classes
or GUI classes, depending on whether they define the data structures or certain visual
elements in your application. The types of class are:
Schema
data class that defines a server table and its columns on your server database
Query
data class that defines one or more server tables and their columns on your server
database
Table
data class that maps to a schema class and contains default methods for processing your
server data
Remote form
GUI class that defines the forms to be displayed on web or mobile devices (JavaScript
Client, or iOS Client)
Remote task
class that controls remote form instances (web forms) and maintains the connection
between a client and the Omnis Server in web applications
Object
class that contains methods and variables defining your own structured data objects
Report
GUI class that defines the reports you can print in your application (Desktop/Local
apps only)
Task
class that contains or controls other instances, and handles events in your application
(Desktop/Local apps only)
Code
class that contains methods you can use throughout a library, for example, a menu and
toolbar in a desktop application could access the same methods stored in a code class
The following classes are used for Desktop/Local applications only, therefore you
should not use them for web and mobile apps:
File
data class that defines the structure of a file (the Omnis equivalent of a table) in an
Omnis data file
48
Class Wizards
The Class Wizards option in the Studio Browser (available when a library is selected) lets
you create fully functioning classes based on the selections you make during the wizard, and
in the case of GUI wizards, the class you are building can be linked to other classes in your
library. The class wizards are good for building or prototyping your application very
quickly and save you building classes from scratch. You can create a JavaScript remote
form based on a schema class in your library using the SQL JavaScript Remote Form
wizard.
49
Omnis Datafiles
If you want to store and retrieve your data using a non-client/server setup, you can store it in
an Omnis data file. In this case you need to design the structure for your data using Omnis
file classes. In addition, you can use an Omnis search class to filter the data stored in an
Omnis data file.
50
Description
Character
National
Number
Boolean
Date Time
Sequence
Picture
List
Row
Object
Binary
Item Reference
Field Reference
Object Reference
51
Character
Character data can contain characters from any of the various single-byte standard character
sets. You can define a Character column of up to 10 million (10,000,000) bytes in length.
Character columns or fields generally correspond to SQL VARCHAR data and have a
varying length format.
In Omnis character data is sorted according to its ASCII character set representation, not the
server representation. The ASCII character set sorts any upper case letter in front of any
lower case letter. For example, these character values
adder, BABOON, aSP, AARDVARK, Antelope, ANT
are sorted as
AARDVARK, ANT, Antelope, BABOON, aSP, adder
National
Like Character data, National data can contain characters from any of the various singlebyte standard character sets. You can define a National column of up to 10 million
(10,000,000) bytes in length. However, when you sort National data, Omnis sorts the values
according to the ordering used by a particular national character set.
The ordering for the English language follows: A, a, B, b, C, c, D, and so on. For example,
if the previous values were values of a national column or field, Omnis would sort them as
follows:
AARDVARK, ANT, Antelope, adder, aSP, BABOON.
If you store data in an Omnis data file, Omnis stores a copy of the ordering in the file along
with the data. If you use the data file on another machine, Omnis preserves the original
ordering.
52
Number
A number variable can be an integral or floating point number having various storage and
value characteristics, depending on its subtype. The following table summarizes the
different subtypes for numbers.
Number type
(dp = "decimal
places")
Storage
(bytes)
Range
Integer
Short integer
0 to 255
32 bit integer
-2,000,000,000 to +2,000,000,000
64 bit integer
-9,223,372,036,854,775,808 to
+9,223,372,036,854,775,807
Short 0 dp
-999,999,999 to +999,999,999
Short 2 dp
-9,999,999.99 to +9,999,999.99
Floating dp
Number 0 dp
-999,999,999,999,999 to +999,999,999,999,999
Number 1 dp
-99,999,999,999,999.9 to +99,999,999,999,999.9
Number 2 dp
-9,999,999,999,999.99 to +9,999,999,999,999.99
Number 3 dp
-999,999,999,999.999 to +999,999,999,999.999
Number 4 dp
-99,999,999,999.9999 to +99,999,999,999.9999
Number 5 dp
-9,999,999,999.99999 to +9,999,999,999.99999
Number 6 dp
-999,999,999.999,999 to +999,999,999.999,999
Number 8 dp
-9,999,999.999,999,99 to +9,999,999.999,999,99
Number 10 dp
-99,999.999,999,999,9 to +99,999.999,999,999,9
Number 12 dp
-999.999,999,999,999 to +999.999,999,999,999
Number 14 dp
-9.999,999,999,999,99 to +9.999,999,999,999,99
Number
53
Boolean
The boolean data type represents single-byte values of true (yes), false (no), empty, or null.
You should take care to give each Boolean column or field an initial value, because Omnis
initializes boolean data to empty, not NO or null.
When used in a data entry field in a window, boolean data is treated as three characters in
which any data entry is interpreted as a YES or NO. A `Y', 'YE' or 1 is seen as YES while
an 'N' or 0 will suffice for No. If the field is a check box, you enter the boolean value by
clicking on the box. If you don't initialize the field and the user does not click on the box,
the field has an empty value.
You can use boolean values in expressions. The numeric value is 1 for Yes values and 0 for
No and empty values. NULL values are treated as undefined in numeric calculations. For
example, (null+1) is null and (null>1) is null.
When converted to character strings, Boolean columns or fields can take values "YES",
"NO", "NULL", or empty, "". In some cases, for example when setting up search criteria,
you can enter values other than these for a Boolean field; in this case, Omnis converts them
and matches them with empty. Thus, for example, the value 'FALSE' is converted to empty,
as are values like SAM, HAPPY, and so on.
54
Date time
The date and time group of data types contains three basic subtypes: a four-byte Short date,
a two-byte Short time, and an eight-byte Long date and time. The following table
summarizes the date and time subtypes.
Date Time
subtypes
Storage
(bytes)
Range
Short date
1900..1999
Short date
1980..2079
Short date
2000..2099
Short time
Minute resolution
Date time(#FDT)
Formatted #FDT, to
centiseconds
Date time(D m Y)
Formatted D m Y, to
centiseconds
Note that the display of dates depends on the settings in the #DFORMS system table. Also
the long date and time subtypes are identical in value, only displaying differently in window
fields.
Short Date
The short date type spans the range JAN/1/0000 to DEC/31/9999. There are three specific
built in ranges: 1900 to 1999, 1980 to 2079, and 2000 to 2099. By choosing the appropriate
range, you can enter just two digits for the year and Omnis recognizes the century correctly.
For example, if you select the range as 2000 to 2099, a date you enter as 7,12,57 will be
read as 7,12,2057 rather than 1957. To enter a date outside the three specific year ranges,
you need to set up your own date display format.
Omnis accepts dates in different formats automatically, with the exact format depending on
whether your system is US or European. For example, you could enter the 7th of December,
1998, as any of the following strings.
US system
European system
12-7-98
07-12-98
12/7/98
7/12/98
12%7%98
7%12%98
DEC 7 98
7 DEC 98
You can use any character to delimit the day and month figures. If you don't specify the year
or month and year, Omnis assumes the current year or month and year, respectively.
55
Short Time
Short time types have two-byte values in the form HH:NN. The range of possible time
values is from 00:00 to 23:59.
You can use time in expressions. Omnis automatically converts the time into numeric values
using the conversion HH*60+NN, giving the total number of minutes. The #FT string
variable controls conversions between time and string types.
You should try to use straight date comparisons if you are comparing full dates. Dont try to
convert them into integers or other types of data. Let Omnis do the work for you.
Century ranges are used when dates are entered from the keyboard or when a character
string is converted to a date. If you enter a date that includes the century, the century range
is ignored. Century ranges do not affect how a date value is stored or displayed, Omnis
always stores the full date including the century.
Sequence
Every time Omnis inserts a new record into an Omnis data file, it assigns a unique number,
a record sequencing number or RSN to that record. There is a special data type, the
sequence, for this type of data. Each RSN references a location in the data file. If you delete
a record, Omnis does not reuse the RSN. The RSN is stored as a 32-bit integer so its
maximum value is 2^32-1, which is approximately 4,295 million! The sequence type is not
applicable to client/server data.
Omnis assigns record sequencing numbers (RSNs) according to the following rules:
The first record in a file has RSN 1, the second record RSN 2, and so on
57
Picture
The picture data type holds color graphics with a size limited only by memory. The space
each picture consumes depends on the size and resolution of the image. The internal storage
of a picture is either in native format (Windows bitmap or DIB or metafile or Macintosh
PICT) or in Omnis shared color format. Server databases store picture data as binary
objects (BLOBs).
List
The list is a structured data type that can hold multiple columns and rows of data. A list can
hold an unlimited number of lines and can have up to 400 columns. When you create a list
variable you set the type of each column. The data type of each column in your list can be
any one of the other data types including Character, Number, Date, Picture, and List: Yes,
you can even have lists within lists!
Omnis makes use of the list data type in many different kinds of programming tasks.
Normally you would create a variable with list data type and build your list in memory from
your server data or Omnis data file. Then you could use your list data as the basis for a grid
or list field on a window, or you could use it to generate a report.
You can store lists in Omnis data files directly. To store a list in a SQL table on a server,
you can map it to a binary field of some kind.
Row
The row is a structured data type, like a list, that can hold multiple columns and types of
data, but has one row only: it is essentially a list type with a single row. A row can have up
to 400 columns. When you create and define a row variable, you set the type of each
column. As with lists, the data type of each column in your row can be any one of the other
data types including Character, Number, Date, Picture, List, and Row.
Object
Object classes let you define your own structured data objects. Their structure, behavior,
and the type of data they can hold is defined in the variables and methods that you add to
the object class. A variable with object type is a variable based on an object class: the
subtype of the variable is the name of an object class. For example, you can create an
58
Object reference
The Object reference data type provides non-persistent objects that you can allocate and
free using notation. Non-persistent means that objects used in this way cannot be stored on
disk, and restored for use later.
You can use the Object reference data type with local, instance, class and task variables. It
has no subtype. To create a new Object instance, referenced by an Object reference
variable, you use the methods $newref() and $newstatementref(). These are analogous to the
$new() and $newstatement() methods, and they can be used wherever $new() and
$newstatement() can be used.
Refer to the Omnis Programming manual for information about using object references.
Binary
The binary type can store structured data of unlimited length up to your maximum available
memory. Omnis does not know anything about the format and structure of the data in a
binary column or field. In this type of column or field you could place, for example, desktop
publishing files, MIDI system exclusive files, CAD files, and so on. You could store the
definition of an Omnis class in a binary field.
Binary data corresponds to binary large objects (BLOBs) on most database servers.
Item reference
You can use a variable of type Item reference to store an alias or reference to an object in
Omnis or in your library. You assign the notation for the object to the item reference
variable using the Set reference command. You can use an item reference variable in
calculations or expressions which saves you having to quote the full path to the object. You
can also use an item reference variable with the Do command to return a reference to the
object or instance created by the command.
59
Field reference
You can pass a reference to a field using the field reference data type, available for
parameter variables only. A parameter variable with the field reference type must have a
valid field in the calling method. Once the field reference parameter variable is set up, a
reference to the parameter is the same as using the field whose name is passed.
The result of arithmetic, comparison, and logical operators on null data is always null. With
string functions such as con() and jst(), however, Omnis translates null to empty. The
isnull() function returns kTrue if the value is null and kFalse if not.
When you use an Omnis sort on columns or variables with nulls, Omnis sorts the nulls first
and separately from the empty values (or, for a descending sort, last). In a sorted report the
nulls come first and do generate a break.
When exporting records in a text format, null values export as an unquoted string NULL,
unless a particular format doesnt support nulls. In this case, Omnis translates the null to
empty. Occurrences of this unquoted string in an import file import as nulls.
60
Schema classes
Schema classes
A schema class is a type of data class that represents a table or view on your server
database. A schema class contains the name of the server table or view on your server, and a
list of column names and Omnis data types that map directly to the columns in your server
table or view. The Omnis data types defined in a schema class should map to the equivalent
server types, and the column names must conform to any conventions about case used by
the server. For example, if the server column names are case sensitive, the column names in
your schema class must be in the correct case.
Schema classes do not contain methods, and you cannot create instances of them. You can
however use a schema class as the definition for an Omnis list using the
$definefromsqlclass() method, which lets you process your server data using the SQL
methods against your list.
To create a new schema class
Click on the New Class option, then click on the Schema option
The schema editor lets you enter the name of the server table or view and the column
definitions You can move from column to column in the editor either using the Tab key, by
clicking in the column, or with the keyboard Up and Down arrows.
Having created a schema (or query) class, you can use the SQL Form Wizard to create a
SQL form based on the class to view and enter data into your server database.
61
Query Classes
A query class is a type of data class that lets you combine one or more schema classes or
individual columns from one or more schemas, to give you an application view of your
server database. A query class contains references to schema classes or individual schema
columns.
Query classes do not contain methods, and you cannot create instances of them. You can
however use a query class as the definition for an Omnis list using the $definefromsqlclass()
method, which lets you process your server data using the SQL methods against your list.
To create a new query class
Click on the New Class option, then click on the Query option
When you open the query class editor the Catalog pops up which lets you double-click on
schema class or column names to enter them into the query editor. Alternatively, you can
drag schema class or column names into the query editor. Furthermore, you can reorder
columns by dragging and dropping in the fixed-left column of the query editor, and you can
drag columns from one query class onto another. You can also drag a column from the
schema editor to the query editor.
Table Classes
A table class provides the interface to the data modeled by a schema or query class. When
you create a list based on a schema or query class, a table instance is created automatically
which contains the default SQL methods. You should only need to create a table class when
you want to override the default methods in a table instance, or you want to add methods to
a table. A table class contains the name of the schema or query class it uses, and your own
custom methods that override or add to the default table instance methods.
To create a new table class
62
Click on the New Class option, then click on the Table option
Table Classes
You add methods to a table class in the method editor, and change its properties in the
Property Manager. To associate a table class with a schema or query class, you need to set
its $sqlclassname property to the name of a schema or query class.
Like Schema and Table classes, you can use a table class as the definition for an Omnis list
using the $definefromsqlclass() method, which lets you process your server data using the
methods you added to the table class. See the Omnis Programming manual for further
details about the SQL lists and their methods.
63
Chapter 3Omnis
Programming
Omnis Studio has a powerful programming environment that lets you create almost any type
of enterprise or web application. The Omnis programming environment contains hundreds
of 4GL commands and functions, as well as a low-level scripting language, called Omnis
Notation, that allows you to manipulate objects dynamically in the runtime environment. To
program in Omnis, you must consider the following things:
Variables
variables are the principal data container in Omnis; most objects in Omnis can contain
variables, but their scope and the kind of data they can contain depends on the type of
variable; you can use the method editor to add variables to an object; the definition and
dynamic manipulation of variables is at the heart of programming
Methods
methods are pieces of Omnis code contained within the objects in your application,
each performing a particular operation specific to the object or the application as a
whole; creating and modifying methods in your library is key to creating an application.
Events
almost all user actions in Omnis generate an event; when an event occurs a message is
sent to the object in which the event occurred; you need to write methods behind the
objects in your library to handle the events.
Tasks
when your application runs in Omnis many object instances are created, such as
windows, reports, and web forms; these instances are opened and handled within a task.
Omnis creates a default task, but you can create your own tasks that allow you to
handle the objects in your application.
All the above topics are covered in this chapter. You create and modify methods in Omnis
using the method editor.
64
Variables
Variables
Variables can hold different types of data and are visible in different parts of your
application depending on their data type and scope. For example, if you create a variable of
list data type in a window class, the list variable and hence its data is visible within the
window class and all its instances, but is not accessible elsewhere in your library. The data
types available in Omnis are described in detail in the Introducing Omnis manual.
When Initialized
When Destroyed
Scope
Parameter
on calling the
method
Local
on running the
method
on terminating a
method
the method
Instance
on opening an
instance
a single instance of a
class
Class
on opening a
library
on clearing class
variables or closing a
library
Task
on opening an
instance of the task
Hash
on starting Omnis
on quitting Omnis
global
Apart from hash variables which are permanently built into Omnis, you must create all
variables with the appropriate type and scope in the objects in your library using the method
editor. After you have declared them, variables that are in scope are listed in the Catalog.
You can remove a variable using the Delete Variable option in the variable pane context
menu. Declared variables are removed from memory when they are destroyed.
65
Parameter Variables
You can use a parameter variable to receive a value in a method, for example, a value that
has been passed to the method using the Do method. You would normally do something
with the value in the method and possibly return a new value. Parameter variables are
visible within the called or recipient method only. They are initialized when the method is
called, and cleared when the method returns to its caller.
Local Variables
Local variables are local to the method. You can refer to the variable within that method
only. Local variables are initialized when the method begins execution, and are cleared
automatically when the method terminates.
Instance Variables
Instance variables are visible to the instance only, that is, all methods and objects in the
instance. You can define an instance variable only for classes that can be opened or
instantiated, that is, tasks, tables, windows, remote forms, remote tasks, reports, menus,
toolbars and object classes. Note that you cannot declare instance variables in code classes.
There is a set of the declared instance variables for each instance of a class: these are
initialized when the instance is constructed and cleared when the instance is destructed.
Class Variables
Class variables are visible within the class and all its instances. You can declare class
variables for tasks, tables, windows, reports, menus, toolbars, and code classes. Any object
or method in the class can refer to a class variable, and all instances of the class also have
access to the class variable.
Class variables are not automatically cleared from memory. You can remove them from
memory by closing the library containing the class, or using the Clear class variables
command.
Task Variables
Task variables are visible within the task, all its design classes and instances. In practice,
you can refer to a task variable from any method within any class or instance that belongs to
the task. Omnis initializes task variables when you open the task: for the Startup_Task this
is when the library opens. Note that you cannot declare a task variable for a class until you
have set the $designtaskname property for the class.
66
Variables
Hash Variables
Omnis has a built-in set of global variables, called hash variables since they start with the
symbol "#". You can view them in the Catalog (F9/Cmnd-9). Hash variables are global,
unlike any other variables, so all libraries have access to them. The advantage of having
global variables is that you can use these variables to pass data between libraries in an
application. The disadvantage is that any data you place in hash variables remains there
when you switch between libraries or combine libraries, with potentially unpredictable
results.
Adding a Variable
You add variables to a class or object in the variable pane of the method editor. If the
variable pane is not visible you can show it using the View>>Show Variable Panes menu
option on the method editor menu bar.
The tabs in the variable pane let you define task, class, instance, local and parameter
variables; note that the local and parameter tabs only appear after you have added or
selected a method in the method editor. You can add up to 400 variables of each type to the
current object, including 400 local and parameter variables for each method in the current
object. The name, type, subtype, and initial value of each variable is listed in the variable
pane. You can size the columns in the variable pane by sizing the column headers.
You cannot declare a task variable within a class until you have set the $designtaskname
property for the class: see the section below on Adding Task Variables.
To add a new variable
Right-click on the background of the class to open the class context menu
or
67
Tab to the Type box and choose the type from the droplist using the mouse or arrow
keys
Type the first letter(s) of a data type to select it, for example, you can type nu to
select the Number data type, or b for Boolean and bi for Binary type
Tab to the Subtype box and choose a subtype; again, you can type the first letter(s) of a
subtype, for example, for Numbers you can type L to select the Long Integer subtype
You can enter an initial value or calculation for all types of variable. The initial value
allowed for a variable depends on its type. See Variable Values below.
Variable Naming
Variable names can be up to 255 characters long, although in practice you should keep them
as short but descriptive as possible. When you name a variable you should prefix its name
with one or more letters to indicate its scope. For example, parameters variables can begin
with the letter p, local variables lv or just the letter l, instance variable iv or just the
letter i, and so on.
When two or more types of variable use the same variable name, a reference to that variable
could be ambiguous. In a situation where more than one variable of the same name exists,
Omnis automatically uses the variable with the smallest scope. Therefore, it is possible,
though not good practice or recommended, to have local, class, and task variables called
"MYNAME". As Omnis resolves ambiguity, a reference to MYNAME will refer to the
local variable if it exists for the current method. To avoid all ambiguity you should use a
naming convention similar to the one described above
68
Variables
names directly into your code in the method editor, at which time their names are added to
the Local variables pane.
Click on the droplist in the $designtaskname property to view the current tasks
The list of tasks will contain a Startup_Task, and any tasks you may have created.
You will now be able to define task variables for this class.
Variable Values
When you declare a variable in the variable pane of the method editor you can assign it an
initial value. The first time a variable is referenced in a method, Omnis assigns the specified
initial value to the variable. You can set the initial value to be a number, string, calculation,
some notation, an Omnis constant, or another variable name. In the latter case, when you
first use the variable it gets the value in the other variable, regardless of the order of
declaration.
69
Variable Tips
You can pass the mouse over a variable or constant and a variable tip will pop up
displaying the variables current value. Variable tips are available wherever variable names
appear in Omnis including the method editor and Catalog. However, they are not available
if Help tips are enabled for the tool containing the variable. For some variable types, such as
list or binary variables, the tip may say not empty which tells you the variable has a value,
but it is too long to display.
70
Methods
Methods
Omnis provides a complete 4GL programming language comprising over 400 commands,
each command performing a specific function or operation. In addition, Omnis provides a
means to manipulate the objects in your library called the notation: this accesses the
standard properties and methods contained in the objects in your library.
A method can contain up to 1024 lines of code. Each method line can contain an Omnis
command, or some notation, or often a combination of these; you can also add comments to
method lines. For example, to open a window from a menu line you only need one
command in your method, that is the Open window instance command, which as the name
suggests opens an instance of a window. A method that connects you to a server database
requires several commands executed in a particular order. You can perform most operations
using the notation and the Do command. For example, you can open a window using the Do
command and the $open() method.
For further details about specific commands and notation used throughout this chapter, see
the Omnis Help (press F1 to open it), or the Omnis Reference manuals. When you start to
program methods you will need to use the debugger which is described in the Debugging
Methods chapter.
71
Commands
The following sections outline the more important commands or groups of commands in
Omnis. The commands that you can use in your methods are listed in the command list at
the bottom of the method editor. If the command list is not showing in the method editor
you can show it using View>>Show Command Palette, or by pressing Shift-F6 under
Windows or Shift-Cmnd-6 under MacOS.
Double-click on each group in the command list to get an idea of the full range of
commands available in Omnis.
Each group in the command list contains a number of commands that manipulate a
particular type of object or perform related operations. For example, the Calculations...
group contains the Calculate command that lets you do calculations and assign a value to a
variable, and the Do command that lets you execute and modify objects using the notation.
The Constructs... group contains programming constructs such as If...Else If, Repeat...Until,
and For loops.
The Flag
Some of the commands set a Boolean Omnis variable called the flag, or #F, to true or false
depending on the success of an operation. Other commands test the current value of the flag
and branch accordingly. The Omnis Studio Help documents whether or not a command
affects the flag.
Notation
Omnis structures its objects in an object tree, or hierarchical arrangement of objects and
groups that contain other objects. The complete tree contains all the objects in Omnis itself,
together with your design libraries, classes, and other objects created at runtime. You can
view the complete object tree in the Notation Inspector.
The object at the base of the tree is called $root. The $libs group contains all the current
open libraries and lets you access each library and its classes at design time. The classes and
objects in each library are stored in their own separate groups; for example the $windows
group contains all the window classes in a library. Most of the other groups directly under
$root contain the objects created at runtime when you run your application; for example the
$iwindows group contains all the window instances currently open, or $iremotetasks
contains all the remote task instances currently open.
When you want to reference a particular object, a class or instance perhaps, you must access
the right branch of the object tree. For example, you must access the $windows group to
reference a window class. Whereas, to access a window instance, say an instance of the
same window class, you must reference the window instance via the $iwindows group,
which is contained directly under the $root object.
To facilitate a system of naming or referring to an object in the object tree, and its
properties and methods, Omnis uses a system called the notation. The notation for an object
72
Methods
is really the path to the object within the object tree. The full notation for an object is shown
in the status bar of the Notation Inspector. You can use the notation to execute a method or
to change the properties of an object, and you can use a notation string anywhere you need
to reference a variable or field name.
In the notation all property and standard method names begin with a dollar sign $, and
methods are further distinguished from properties by having parentheses after their name.
Standard objects and group names also begin with a dollar sign. To write the full notation
for an object you need to include each object and group in the path to the object, separating
each object using . a dot. For example, to refer to a window class in a library you would
use the following notation
$root.$libs.LIBRARYNAME.$windows.Windowname
This notation includes $root as the base object, the $libs group containing all the open
libraries, the name of your library, the $windows group containing all the window classes in
your library, and lastly the name of the window itself. If you want to refer to a particular
object on your window you need to add the $objs group and the name of the object
$root.$libs.Libraryname.$windows.Windowname.$objs.Objectname
You can omit certain object names from a notation string to make it shorter, and when you
have only one library open usually you can omit the library name as well. You can omit the
following objects: $root, $constants, $clib, $hashvars, $libs, $extobjects, $tvars, $datas,
$cvars, $files, $lvars, $vals. In most cases therefore, you can refer to an object on a window
as
$windows.Windowname.$objs.Objectname
In addition, there are a number of shortcuts that let you reference objects, without always
referring right back to the $root object, and certain global objects that you can use to make
your code more generic. These are described below.
Item References
To save you time and effort, and to make your code more efficient, you can create an alias
or reference to an object which you can use in place of the full notation for the object. To
do this, you create a variable of type item reference and use the Set reference command to
assign the notation to the variable. The item reference variable can be of any scope, and the
notation can be any valid Omnis notation for an object, a group, or even an object property.
For example
; Declare variable WinRef of type Item reference
Set reference WinRef to Libraryname.$windows.Windowname
; creates a reference to the window which you can use in your code
Do WinRef.$forecolor.$assign(kBlue) ;; changes the window forecolor
You can enter the notation for an object in the initial value field for the item reference
variable. You can also find the full notation for an object in the Notation Inspector and drag
it to the notation field when you enter the Set reference command.
73
Current Objects
Under $root, Omnis contains a number of global state variables that tell you about how
Omnis is currently executing, or what objects, instances, and methods are currently being
used. These objects provide a shortcut to the current object or instance that is currently
executing. Mostly their names begin with $c, and they include
$cclass
the current class
$cdata
the current open data file
$cinst
the current instance; usually the instance containing the currently executing method
$cfield
the field where the current method is executing
$clib
the current library
$cmethod
the current executing method
$cobj
the current object within a class or instance
$cparmcount
the number of parameters that the caller has passed to the current method
$crecipient
the current recipient of an event; if a custom method is being processed, $crecipient is
the recipient of that method
$ctarget
a reference to the target field, that is, the field which currently has the focus (shows the
caret and is sent keyboard events)
$ctask
the current task; is usually the startup or default task until you open another task
$cwind
the current window instance
74
Methods
$topwind
the topmost open window instance
You can use the current objects in place of the full notation for a specific object to make the
object and its code reusable and portable between libraries. For example, you can use $cinst
in a method within a window instance to refer to itself, rather than referring to it by name
$cinst
; rather than
$root.$iwindows.WindowInstanceName
You can refer to the current library using $clib. For example, to make the current library
private use
Do $clib.$isprivate.$assign(kTrue)
; is more generic than
Do $libs.MyLibrary.$isprivate.$assign(kTrue)
75
Do command
You can use the Do command in Omnis to do almost anything: execute some notation,
evaluate an expression, and so on. Specifically, you can use it to execute a method for an
object or assign a value to one of its properties. The Do command returns a value to
indicate whether the operation was successful or not, or for some methods a reference to the
object operated upon. This section shows you how you can use the Do command and
introduces some of the most useful methods.
$open() method
Using the Do command with the notation you can perform many operations that are
otherwise performed with a command. For example, the class types that you can open
contain an $open() method which you can execute using the Do command. For example,
you can open a window using
Do $windows.WINDOWNAME.$open(INSTANCENAME,kWindowCenter)
; opens a window in the center of the screen
The $open() method returns a reference to the instance created. For example
; Declare variable WindRef of type Item reference
Set reference WindRef to LIB1.$windows.WindowName
Do WindRef.$open('WindowInstance') Returns WindRef
; WindRef now contains a reference to the window instance
; $root.$iwindows.WindowInstance which you can use elsewhere, e.g.
Do WindRef.$forecolor.$assign(kBlue)
;; changes the instance
You can use a null value instead of an instance name; therefore CLASS.$open() would
force Omnis to use the class name as the instance name. Alternatively you can use an
asterisk in place of the instance name and Omnis assigns a unique name to the instance,
76
Methods
using the notation CLASSNAME_number. You can return the instance name in an item
reference variable and use the reference in subsequent code. For example
; Declare variable iMenuRef of type Item reference
Do $menus.MCUSTOMERS.$open('*') Returns iMenuRef
; iMenuRef now contains a reference to the menu instance, which
; will be something like $root.$imenus.MCUSTOMERS_23
You can close an instance using the $close() method. For example, the following method
opens a window instance, lets the user do something, and closes the instance
; initially WindRef contains a reference to the window class
Do WindRef.$open('WindowInstance') Returns WindRef
; let the user do something
Do WindRef.$close()
You can close the current window from inside the instance using
Do $cwind.$close()
Classes that contain the $open() methods also have the $openonce() method. This method
opens an instance if one does not already exist (excluding window menus, window toolbars,
and cascaded menus). In the case of a window, $openonce() brings the window to the top if
it is already open. $openonce() returns an item reference to the new or existing instance,
like $open().
$assign() method
You can change the properties of an object, including the properties of a library, class, or
field, using the Do command and the $assign() method. The syntax for the $assign() method
is NOTATION.PROPERTY.$assign(VALUE) where NOTATION is the notation for the object,
PROPERTY is the property of the object you want to change, and VALUE is a value depending
on the context of the object being changed. Usually you can use an Omnis constant to
represent a preset value, and for boolean properties, such as preferences, you can use kTrue
or kFalse to set the property as appropriate. For example
Do $clib.$prefs.$mouseevents.$assign(kTrue)
; turns on mouse events for the current library
Do $cclass.$closebox.$assign(kTrue)
; adds a close box to the current window class
Do $cfield.$textcolor.$assign(kGreen)
; makes the text in the current field green
$add() method
You can create a new object in your library using the $add() method. In the notation you are
really adding a new object to a particular group of objects. For example, to create a new
field on a window you need to add the object to the $objs group of objects for the window,
as follows
77
When using $add(), you can return a reference to the new object in a return field of type
item reference. You can use the reference to change the properties of the new object. For
example
; Declare variable WindRef of type Item reference
Do $windows.$add('NewWindowName') Returns WindRef
; now use the reference to change the new window
Do WindRef.$style.$assign(kPalette)
Do WindRef.$title.$assign('Window title')
Do WindRef.$clickbehind.$assign(kTrue)
Do WindRef.$keepclicks.$assign(kFalse)
Do WindRef.$modelessdata.$assign(kTrue)
Do WindRef.$backcolor.$assign(kRed)
Do WindRef.$forecolor.$assign(kWhite)
Do WindRef.$backpattern.$assign(2)
$redraw() method
Note the $redraw() method is only relevant for fat client windows, not JavaScript Remote
Forms which redraw content automatically.
When you change an object or several objects on an open window using the Do command,
you often need to redraw the window. However if you change an object before $construct()
completes execution for the window instance, you dont need to redraw the window. You
can redraw an object, window, or all open windows using the $redraw() method. For
example
Do $cfield.$redraw()
; redraws the current field
Do $cwind.$redraw()
; redraws the current window
Do $root.$redraw()
; redraws all window instances
The $redraw() method has three parameters that allow you to specify the extent of the
redraw for window fields and/or background objects: the parameters are:
$redraw(bSetcontents,bRefresh,bBackObjects) where bSetcontents defaults to true,
bRefresh defaults to false, and bBackObjects defaults to false.
$root.$redraw(kTrue,kTrue)
; redraws the contents and refreshes all the field in all window
$root.$redraw(kFalse,kFalse,kTrue)
; redraws all background objects for all open windows
78
Methods
$sendall() method
You can send a message to all the items or objects in a group using the Do command and
the $sendall() method. For example, you can redraw all the objects in a group, you can
assign a value to all the members of an object group, or you can hide all the members of a
group using the $sendall() method and the appropriate message. The full syntax for the
method is:
$sendall({message|message,condition
[,bIgnoreUnrecognizedCustomAttribute=kFalse]})
where message is the message you want to send to all the objects and condition is a
calculation which the objects must satisfy to receive the message. For example
Do $iwindows.$sendall($ref.$objs.FIELDNAME.$redraw())
; redraws the specified field on all window instances
Do $cwind.$objs.$sendall($ref.$textcolor.$assign(kYellow))
; makes the text yellow for all the fields on the current window
Do $cwind.$objs.$sendall($ref.$visible.$assign(kFalse),$ref.$order<=5)
; hides the first five objects on the current window; useful
; for window subclasses if you want to hide inherited objects
$sendallref ()method
When using $sendall(), you can use $ref to refer to the group member receiving the
message. However you can use $sendallref, which is an item reference to the item currently
receiving the message sent with $sendall (note that $sendallref is not supported in client
methods). Consider the case where a parameter passed to the message is evaluated by
calling another method, or a function implemented in an external component. In this case, if
you use $ref in the parameters passed to this other method or function, it will actually refer
to the item involved in making the call to evaluate the parameter. This is where
$sendallref() could be used, if you wish to pass some property of the group member
receiving the message to the other method or function.
For example:
Do $cinst.$bobjs.$sendall(
$ref.$text.$assign(
StringTable.$gettext(
$cclass.$bobjs.[$sendallref.$ident].$text)))
The example uses the text stored in the class as the row id in the string table, and assigns the
text stored in the string table to the background object. In the example, $sendallref.$ident
returns the ident of the background object receiving the message. If you were to use
79
$makelist() method
Quite often you need to build a list containing the names of all the objects in a group, and
you can do this using the makelist() method. For example
Do $clib.$classes.$makelist($ref.$name) Returns cLIST
; builds a list of all the classes in the current library and
; places the result in cLIST
Do $imenus.$makelist($ref.$name) Returns cLIST
; builds a list of all the currently installed menus
Do inherited
The Do inherited command runs an inherited method from a method in a subclass. For
example, if you have overridden an inherited $construct() method, you can use the Do
inherited command in the $construct() method of the subclass to execute the $construct()
method in its superclass.
Do default
You can use the Do default command in a custom method with the same name as a standard
built-in method to run the default processing for method. For example, you can use the Do
default command at the end of a custom $print() method behind a report object to execute
the default processing for the method after your code has executed.
Do redirect
You can use the Do redirect command in a custom method to redirect method execution to
another custom method with the same name that is contained in another object in your
library. You specify the notation for the instance or object you want execution to jump to.
Inheritance and custom methods are further discussed in the Object Oriented Programming
chapter.
Methods
Calculate var1 as con('Jon', 'McBride')
Here the expression uses the con() function which joins together, or concatenates, the two
strings Jon and McBride. You must enclose literal strings in quotes.
See the Omnis Studio Help for a complete list of functions. In expressions, functions appear
as the function name followed by parentheses enclosing the arguments to the function. The
function returns its result, substituting the result into the expression in place of the function
reference. Calling a function does not affect the flag.
The Omnis operators are shown below, in precedence order, that is, the order in which they
get evaluated by Omnis. Operators in the same section of the table are of equal precedence,
and are evaluated from left to right in an expression.
Parentheses
Unary minus
Multiplication
Division
Addition
Subtraction
Less than
Greater than
Equal to
Less than or equal to
Greater than or equal to
Not equal to
Logical AND
Logical OR
()
*
/
+
<
>
=
<=
>=
<>
&
|
When you combine expressions with operators, the order of expressions will often make a
difference in the interpretation of the expression; this is a consequence of the mathematical
properties of the operators such as subtraction and division. You can group expressions
using parentheses to ensure the intended result. For example
Calculate lv_Num as 100 * (2 + 7)
evaluates the expression in parentheses first, giving a value of 900. If you leave off the
parentheses, such as
Calculate lv_Num as 100 * 2 + 7
Omnis evaluates the * operator first, so it multiplies 100*2, then adds 7 for a value of 207.
81
window or report fields; you can include values in text objects, such as
Your current balance is [lv_curbalance]
82
Methods
; Declare local variable LBOOL of type Boolean
Calculate LBOOL as 1
;; is the same as...
Calculate LBOOL as 'Y' ;; or 'YES'
; the opposite is
Calculate LBOOL as 0 ;; or 'NO' or 'N'
OK message { The answer is [LBOOL] }
Calculate LBOOL as 'fui' ;; is the same as...
Calculate LBOOL as ''
You can convert any number to a string and any string that is a number in string form to a
number.
; Declare local variable lChar of type Character
; Declare local variable lNum of type Number floating dp
Calculate lChar as 100
OK Message { [lChar], [2 * lChar], and [con(lChar,'XYZ')] }
; Gives message output 100 200 and 100XYZ
Calculate lNum as lChar
Calculate lChar as lNum
OK Message { [lChar], [lNum * lChar], and [con(lChar,'ABC')] }
; Gives message output 100 10000 and 100ABC
Constants
You will often find situations in Omnis where you must assign a value that represents some
discrete object or preset choice. Omnis has a set of predefined constants you should use for
this kind of data. For example, a class type can be one of the following: code, file, menu,
report, schema, and so on. Each of these is represented by a constant: kCode, kFile, kMenu,
kReport, kSchema, respectively. You can get a list of constants from the Catalog; press
F9/Cmnd-9 to open the Catalog. You can use constants in your code, like this
Calculate obj1.$align as kRightJst
;; or use Do
Do obj1.$align.$assign(kRightJst)
; aligns the object obj1 to the right
Although you can use the numeric value of a constant, you should use the predefined string
value of a constant in your methods. In addition to ensuring you're using the right constant,
your code will be much more readable. Moreover, there is no guarantee that the numeric
value of a particular constant will not change in a future release of Omnis.
Calling Methods
You can execute another method in the current class using Do method, or call a method in a
code class using Do code method. These commands let you pass parameters to the called
method and return a value in a return field. For example, the following method named Setup
calls another method named Date and returns a value.
83
Note that when you call a code class method from within an instance the value of $cinst, the
current instance, does not change. Therefore you can execute code in the code class method
that refers to the current instance and it will work.
WARNING Omnis does not stop a method calling itself. You must be careful how the
method terminates: if it becomes an infinite loop, Omnis will exhaust its method stack.
Quitting Methods
You can use the Quit command, and its variants, to quit methods at various levels.
Quit method
quits the current method and returns a value to the calling method, if any
Quit event handler
quits an event handling method
Quit all methods
quits all the currently executing methods, but leaves Omnis running
Quit all if canceled
quits all methods if you press Cancel
Quit Omnis
exits your application and Omnis
You can also clear the method stack with the Clear method stack command, which does the
same thing as the debugger menu Stack>>Clear Method Stack; it removes all the methods
except for the current one. If you follow Clear method stack with Quit method, it has the
same effect as Quit all methods.
The Quit method command allows you to exit a method and return a value to the calling
method. For example:
84
Methods
;
;
It is possible to call another method in the return value of a Quit method command, but this
can lead to unpredictable results, especially if the called method contains an Enter Data
command, e.g.
Quit method Returns iOtherObject.$doSomeThingThatContainsEnterData
Branching Commands
The If command lets you test the flag, a calculation, or a Cancel event. The Flag is an
Omnis variable with a True or False value which is altered by some commands to show an
operation succeeded, or by user input. The Else command lets you take an alternative action
when the If evaluates to false, Else if gives you a series of tests. You must use the End If
command to terminate all If statements.
A simple test of the flag looks like this:
If flag true
Do method Setup
End if
85
While Loops
The While loop tests an expression at the beginning of a loop. The While command will not
run the code block at all if the expression is false immediately. You would use a While
command when you want to loop while an expression is true.
; Declare Count with initial value 1
While Count <= 10
OK message {Count is [Count]}
Calculate Count as Count + 1
End While
This loop will output 10 messages. If the condition was Count <= 1, it would run only
once.
Repeat Loops
A Repeat loop lets you iterate until an expression becomes true. Repeat loops always
execute at least once, that is, the test specified in the Until command is carried out at the
end of the loop, after the commands in the loop are executed, whereas While loops carry out
the test at the beginning of the loop.
; Declare Count of Integer type with initial value 1
Repeat
OK message {Count is [Count]}
Calculate Count as Count + 1
Until Count >= 10
86
Methods
For Loops
The For field value command lets you loop for some specific number of iterations, using a
specified variable as the counter. The following example builds a string of ASCII characters
from their codes using the functions con() and chr().
; Declare Count
Calculate cvar1 as ''
;; clear the string
For Count from 48 to 122 step 1
;; set the counter range
Calculate cvar1 as con(cvar1,chr(Count)) ;; add char to string
Do $cwind.$redraw()
End for
The For each line in list command loops through all the lines in the current list.
Set current list LIST1
For each line in list from 1 to LIST1.$linecount step 1
; process each line
End for
Switch/Case Statements
The Switch statement lets you check an expression against a series of values, taking a
different action in each case. You would use a Switch command when you have a series of
possible values and a different action to take for each value.
The following method uses a local variable lChar and tests for three possible values, A,
B, and C.
; Parameter pString(character 10)
;; receives the string
Calculate lChar as mid(pString, 1, 1)
;; takes the first char
Switch lChar
Case A
; Process for A
Case B
; Process for B
Case C
; Process for C
Default
; do default for all cases other than A, B, or C
End switch
It is a good idea to use the Switch command only for expressions in which you know all the
possible values. You should always have one Case statement for each possible value and a
Default statement that handles any other value(s).
87
The If canceled command detects the Cancel event and quits the method. To turn on testing
for a break, you can use the Enable cancel test at loops command.
The Break to end of loop command lets you jump out of a loop without having to quit the
method, and the Until break provides an exit condition which you can fully control. For
example
Repeat
Working message (Cancel box) {Repeat loop...}
If canceled
Yes/No message {Are you sure you want to break out?}
If flag true
Break to end of loop
End If
End If
Until break
OK message {Loop has ended}
88
Methods
If you have not disabled the cancel test at loops, a Ctrl-Break/Cmnd-period/Ctrl-C
terminates all methods and does not execute the OK message. Having turned off the
automatic cancel test at loops, you can still cause a Quit all methods when canceled. For
example
Disable cancel test at loops
Calculate Count1 as 1
Calculate Count2 as 1
Repeat
Repeat
Working message (Cancel box) {Inner repeat loop}
Calculate Count2 as Count2 + 1
Until Count2 > 12
Calculate Count2 as 1
Working message (Cancel box) {Outer repeat loop...}
Quit all if canceled
Calculate Count1 as Count1 + 1
Until Count1 > 20
If the user selects Cancel in the outer loop, the method quits, but from the inner loop there is
no escape.
89
Reversible Blocks
A reversible block is a set of commands enclosed by Begin reversible block and End
reversible block commands; a reversible block can appear anywhere in a method. Omnis
reverses the commands in a reversible block automatically, when the method containing the
reversible block ends, thus restoring the state of any variables and settings changed by the
commands in the reversible block.
; commands...
Begin reversible block
; commands...
End reversible block
; more commands...
Reversible blocks can be very useful for calculating a value for a variable to be used in the
method and then restoring the former value when the method has finished. Also you may
want to change a report name, search name, or whatever, knowing that the settings will
return automatically to their former values when the method ends.
The Omnis Help (press F1) indicates which commands are reversible.
Consider the following reversible block.
Begin reversible block
Disable menu line 5 {Menu1}
Set current list cList1
Define list {cvar5}
Build window list
Calculate lNum as 0
Open window instance Window2
End reversible block
; more commands...
Methods
the commands in each block, starting from the last reversible block. If you nest reversible
blocks, the commands in all the reversible blocks are treated as one block when they are
reversed, that is, Omnis steps backward through each nested reversible block reversing each
command line in turn. You cannot reverse any changes that the reversible block makes to
Omnis data files or server-based data unless you carefully structure the server transaction to
roll back as well.
Error Handling
When you enter a command, Omnis automatically checks its syntax. When a command is
executed in a method, you can get a runtime error, a processing error rather than a syntax
error. Fatal errors either display a message and stop method execution or open the
debugger at the offending command.
You can cause a fatal error to occur with the Signal error command, which takes an error
number and text as its argument. This lets you define your own errors, but still use the
standard Omnis error handler mechanism.
In addition, Omnis maintains two global system variables #ERRCODE and #ERRTEXT
that report error conditions and warnings to your methods. Fatal errors set #ERRCODE to a
positive number greater than 100,000, whereas warnings set it to a positive number less than
100,000.
You can trap the errors and warnings by adding a method to test for the various values of
#ERRCODE and control the way Omnis deals with them; this is called an error handler.
The command Load error handler takes the name of the method and an optional error code
range as its parameters:
Load error handler Code1/1 {Errors}
; warnings and errors will be passed to handler in code class
Once you install it, Omnis calls the error handler when an error occurs in the specified
range. Please refer to the Omnis Studio Help for a detailed description of the Load error
handler command and examples of its use.
There are several commands prefixed with SEA, which stands for Set error action. Using
these commands, you can tell Omnis what to do after an error:
91
Calculation Errors
The library preference $reportcalculationerrors (default is true) specifies whether or not
calculation errors are reported. When true, Omnis will report errors that occur when
evaluating calculations, such as divide by zero errors. The report message is sent to the trace
log, containing the error and code that caused the problem.
In addition, when executing calculations using Do and Calculate, Omnis enters the
debugger when the error occurs (provided debugging is allowed). This will not occur when
these commands execute in the Omnis web client.
Redrawing Objects
There are a number of commands that let you redraw a particular object or group of objects.
The Redraw command has the following variants.
Redraw field or window
redraws the specified field or window, or list of fields or windows; note this command
with refresh all instances of the window
Redraw lists
redraws all list fields on the current window or redraws all lists in your library
Redraw menus
redraws all the currently installed menus
Redraw toolbar
redraws the specified custom toolbar
You can use the $redraw() method to redraw a field or fields, a window or all windows, as
described earlier in this chapter.
92
Events
Message Boxes
There are a number of message boxes you can use in your library to alert the user. The
commands for these messages are in the Message boxes... group. They include
OK message
displays a message in a box and waits for the user to click an OK button. For emphasis
you can add an info icon and sound the system bell. You can use square bracket
notation in the message text to display the current value of variables or fields. For
example, OK message {[sys(5)]} will display the users serial number. You can use the
kCr constant enclosed in square brackets to force a line break in the message, e.g. 'First
line[kCr]Second line'.
Yes/No message, and No/Yes message
displays a message in a box and waits for Yes or a No answer from the user. Either the
Yes or the No button is the default. You can use the kCr constant enclosed in square
brackets to force a line break in the message, e.g. 'First line[kCr]Second line'.
Prompt for input
displays a dialog prompting the user for input
Working message
displays a message while the computer is processing data or executing a method; with a
Cancel button the user can break into the processing with Ctrl-Break/Cmndperiod/Ctrl-C
Events
Events are reported in Omnis as event messages. These messages are sent to the event
handling methods as one or more event parameters. The first parameter of an event
message, pEventCode, contains an event code representing the event. Event messages may
contain a second or third parameter that tell you more about the event. For example, a click
on a list box will generate an evClick event plus a second parameter pRow telling you the
row clicked on. Note that all event codes are prefixed with the letters ev, and all event
parameters are prefixed with the letter p. You can use the event codes in your event
handling methods to detect specific events, and the event parameters to test the contents of
event messages.
93
The method editor opens showing the first method in the list for the field or object. If this is
not the $event() method, select it from the list to view it. Some event handlers will contain
code to handle a range of possible events in the object.
The event handling method for some types of field may be empty, because there is only one
possible event for the object. For example, the event handling method for a menu line is
empty since you can only select a menu line. Therefore any code you put in the $event()
method for a menu line runs automatically when you select the line.
94
Events
To enter the code for an event handling method
Assuming you have opened a default $event() method for a field, click on the next
command line after the On command
For example, you can open the event method for a pushbutton, that contains a single On
evClick command which will detect a click on the button.
You could use the Do command and some notation in your event handling method, or you
can use the Do method command to run another method in the current class or instance, or
the Do code method command to run a method in a code class; in all cases, you can put
literally any code in an event handling method and it will run given the right event.
The On Command
You can use the On command to detect events in your event handling methods. Fields from
the Component Store may contain a default event handling method with one or more On
commands to detect different events. For example, an entry field contains the method
On evBefore
On evAfter
These lines detect the events evBefore and evAfter, which are the event codes contained in
the message sent when the user enters or leaves the field, respectively. The in-line
comments indicate which event parameters Omnis supplies for that event. In most cases, the
event parameters are references containing values to do with the context of the event: the
field clicked on, the list row number, the menu line number, and so on.
When you select the On command in the method editor, the list of possible events changes
to reflect the events supported by the object to which $event belongs. You can also view
events divided into categories, by using the Events tab of the Catalog.
You can use the default event handling method for a field or add your own. The following
event handler for a data entry field detects an evBefore as the user enters the field and
performs a calculation changing the value of the field.
On evBefore
Calculate cDate as #D
Redraw {DateField}
Quit event handler
95
When you enter the On command in an event handling method, it displays a list of all the
available event codes in the command palette. You can click on the one you want, or you
can enter more than one event code for a single On command, for example On evClick,
evDoubleClick. On commands cannot be nested or contained in an If or loop construct.
When you have entered the On command line for a particular event and selected the next
command line, you can open the Catalog to view the event parameters for that event code.
For example, an On evClick command displays the parameters pEventCode and pRow in
the Catalog. You can use these event parameters in your event handling methods to test the
event message. A click on a list box generates an evClick event message containing a
reference to the row clicked on, held in the pRow event parameter. You can test the value of
pRow in your code
On evClick
;; method behind a list box
If pRow=1
;; if row 1 was clicked on
; Do this...
End If
If pRow=2
;; if row 2 was clicked on
; Do that...
End If
96
Events
All events return the parameter pEventCode, which you can also use in your event handling
methods.
On evAfter,evBefore
;; method behind field
; Do this code for both events
If pEventCode=evAfter
; Do this for evAfter events only
End If
If pEventCode=evBefore
; Do this for evBefore events only
End If
The parameters for the current event are returned by the sys(86) function, which you can use
while debugging or monitoring which events are handled by which methods. For example,
you could use the Send to trace log command and the functions sys(85) and sys(86), to
report the current method and events, in the $event() method for a field
; $event() method for field 10 on the window
Send to trace log {[sys(85)] - [sys(86)]}
; sends the following to the trace log when you tab out of the field
WindowName/10/$event - evAfter,evTab
WindowName/10/$event - evTab
You can use any of the parameters reported for an event in your event handling methods.
However, if you enter an event parameter not associated with the current event, the
parameter will be null and lead to a runtime error.
Mouse Events
Mouse events allow you to detect user mouse clicks inside fields and the background of a
window. Mouse and right- mouse button events are generated only if the $mouseevents and
$rmouseevents library preferences are enabled. Under Mac OS, right-mouse events are
generated when you hold down the Ctrl key and click the mouse.
evMouseDouble and evRMouseDouble
the mouse, or right-mouse button is double-clicked in a field or window
evMouseDown and evRMouseDown
evMouseUp and evRMouseUp
the mouse, or right-mouse button is held down in a field or window, or the mouse
button is released; for the mouse-down events you can detect the position of the mouse,
se below
evMouseEnter and evMouseLeave
the mouse pointer enters, or leaves a field
97
98
Events
The Quit event handler command has two options
Discard event
for some events you can discard the event and stop the default action taking place
Pass to other handlers
passes the event to the next handler in the chain
Discarding Events
In certain circumstances you might want to detect particular events and discard them in
order to stop the default action from occurring. You can discard or throw away events using
the Quit event handler command with the Discard event option enabled. Note however, you
cannot discard some events or stop the default action from taking place since the event has
already occurred by the time it is detected by an event handling method. In this case, a Quit
event handler (Discard event) has no effect for some events.
Being able to discard an event is useful when you want to validate what the user has entered
in a field and stop the cursor leaving the field if the data is invalid. The following method
displays an appropriate message and stays in the field if the user does not enter the data in
the correct format.
On evAfter
;; as user leaves the field
If len(CustCode <> 6)
;; check a value has been entered
If len(CustCode = 0) ;; field left blank
OK message {You must enter a customer code}
Else
;; wrong length code entered
OK message {The customer code must have 6 digits}
End If
Quit event handler (Discard event) ;; stay in the field
End If
You can also handle or discard events using the Quit method command with a return value
of kHandleEvent or kDiscardEvent, as appropriate.
Window Events
So far the discussion has focused on field events, which you would normally handle in the
field using an event handling method. However you can enter methods to handle events that
occur in your window as well. Like fields, the event handling method for a window class is
called $event(), and you enter this method in the Class Methods for the window class.
Window classes do not contain an $event() method by default, but you can insert a method
with this name. You enter the code for a window $event() method in exactly the same as for
fields using the On command to detect events in your window.
Window events affect the window only and not individual fields. They include clicks on the
window background, bringing the window to the front or sending it to the back, moving it,
99
The following window $event() method checks for events occurring in the window and runs
the appropriate methods elsewhere in the class. Note you cannot trap an evResize and
discard it since the resizing has already occurred, but you can reverse the resizing by setting
the size of the open window back to the size stored in the class.
On evToTop
Do method Activate
Quit event handler
On evWindowClick
Do method Deactivate
Quit event handler
On evClose
Do method Close
Quit event handler
On evResized
Do $cwind.$width.$assign($cclass.$width)
Do $cwind.$height.$assign($cclass.$height)
Quit event handler (Discard event)
100
Events
Key events
You can detect which key or key combination is pressed by trapping the evKey event. The
evKey event is sent to the target field when a key is pressed, and has three parameters as
follows:
pEventCode
The event code
pKey
The key pressed
pSystemKey
The system key pressed represented by a code, as follows:
0
Letter/Number
26
End
1...12
F1...F12
27
Tab
17
Up Arrow
28
Return
18
Down Arrow
29
Enter
19
Left Arrow
30
Backspace
20
Right Arrow
32
Esc
21
Page Up
34
Delete
22
Page Down
35
Insert
25
Home
53
Context Menu
101
102
Events
Queuing Events
Some user actions generate a single event which is handled as it occurs by your event
handling methods. The event may be dealt with completely in the field or it may be passed
up the event chain as required. However some user actions generate a whole series of
events, one after another. These events are placed in an event queue. Each event is handled
by your event handling methods strictly in turn on a first-in, first-out basis. For example,
when the user tabs from one field to another the current field is sent an evAfter and then an
evTab event, then the new field is sent an evBefore event: all these events are placed in the
event queue in response to a single user action, the tab. Similarly when you close a window,
the current field is sent an evAfter, the window is sent an evCloseBox event, then it is sent
an evClose event. Each one of these events is sent to the appropriate object and is handled
by your event handling methods before the next event in the queue is handled.
In addition to events generated by user actions, you can append an event to the event queue
using the Queue commands in the Events... group.
103
bring to top
close
cancel
set current field
click
double-click
keyboard event
OK
scroll (Left|Right|Up|Down)
tab
quit
These commands let you simulate user actions such as key presses and clicks on buttons or
windows. For example, the Queue bring to top {WINDOWNAME} command brings the
specified window instance to the top and simulates a user clicking behind the current
window. Events generated by these commands are handled after those that are currently
queued. You can queue several events in succession.
Using Tasks
Omnis contains two environments, a design mode and a runtime mode. In design mode, you
can create and store classes in your library. In runtime mode, various objects or instances
are created as you run your application. You can group and control the runtime objects in
your application by opening or instantiating them in a task. You can manipulate whole
groups of instances by manipulating their task, rather than having to deal with each separate
instance. You define a task in your library as a task class.
Task classes can contain variables and methods, and you can define custom properties and
methods for a task class as well. When you open a task you create an instance of that task
class. The task instance is unique in Omnis in that it can contain other instances including
window, report, toolbar, and menu instances. Task instances cannot contain other tasks.
When you open an instance from within a task it belongs to or is owned by that task.
By opening and closing different tasks, or by switching from one task instance to another,
you can control whole groups of objects. Omnis provides certain default actions which
happen as the task context switches. You define exactly what happens in the task by
creating methods in the task class. For example, in the task you can specify which windows
are opened and which menus are installed using commands or the notation.
Each library contains a group of task classes called $tasks, and Omnis has a group
containing all open task instances called $root.$itasks in the order that they were opened.
For web applications, Omnis provides remote tasks to handle client connections and remote
form instances. These are described later in this chapter.
104
Using Tasks
M a in M e n u
in s ta n c e
Mytask1 instance
W in d o w
in s ta n c e X
M enu
in s ta n c e A
It is not essential to add tasks to your library, your library will safely execute in the startup
task, or the default task along with the IDE objects.
The startup task instance has the same name as your library. For a simple application, the
startup task will probably be all you need, with all the other class instances belonging to it.
The startup task remains open for as long as the library is open, but you can close it at any
time using a command or the notation. You can change the name of the task to be opened on
startup by setting the library preference $startuptaskname; for all new libraries this is set to
Startup_Task by default.
If you have an application that spans multiple libraries, often only the library used to start
the application will have a startup task. If a library is opened using the Open library
105
You modify a task class in the method editor. You can place in the $construct() method any
code that you want to run when the task is opened. For the Startup_Task, the $construct()
method is executed when you open your library. You can add any other custom properties
and methods to the task, as well as any type of variable.
106
Using Tasks
Opening Tasks
Apart from the startup task instance, which is opened automatically when you open your
library, you can open a task using the Open task instance command or the $open() method.
Any parameters you supply with the command are sent to the tasks $construct() method.
Open task instance MyTask/TaskInstance2 (p1,p2,...)
; opens the task, assigns an instance name, and sends parameters
Alternatively you can open a task instance using the $open() method.
Do MyTask.$open(TaskInstance2,p1,p2,...) Returns iTaskRef
; does the same as above & returns a reference to the task instance
107
Closing Tasks
You can close a task instance using the Close task command or the $close() method. When
you close a library all its task instances are closed, and when you quit Omnis the default
task is closed and all instances belonging to the default task are closed.
When you close a task, all instances belonging to that task are closed or destructed
providing they can be closed. When instances are closed, a message is sent to the instance
asking it to confirm whether or not it can be closed. If the instance returns a false message,
Omnis will not close that instance. For tasks, each instance belonging to the task is sent the
message, and then the task itself is sent the message. If any of the instances belonging to the
task cannot be closed, none of the instances nor the task instance are closed.
Task Variables
Task classes can contain both class and instance variables of any standard Omnis data type.
Tasks can also contain task variables, which are accessible to any instance owned by the
108
Using Tasks
task. As with other variables, you create task variables in the variable pane of the method
editor.
When two or more types of variable use the same variable name (this is not recommeded), a
reference to that variable may be ambiguous. In this situation, Omnis uses the variable with
the smallest scope automatically. All other variable scopes have precedence over task
variables.
When a method in a code class is called from another class or instance using the Do code
method command, the current task continues to point to the calling method. This allows
methods in a code class to have access to the task variables from the calling method.
Private Instances
Normally an instance is visible to other tasks and you can reference it using the notation
from anywhere in your library. However you can override this default behavior by making
an instance private to the task that owns it. You can do this by setting the instances
$isprivate property to kTrue.
When you make an instance private, you cannot destruct it, make references to it, or even
see it unless you are within the task that owns it. A task can even be private to itself, so it
can be closed only when it is the current task. If access to a private instance is required from
109
Private Libraries
Libraries can be private to a task, and both the library and its classes are visible only to that
task.
The group of open libraries, $libs, contains a private library only when the task which owns
that library is the active task. The Browser does not display classes from a private library.
Standard entry points to the debugger such as shift-click on a menu line do not enter the
debugger if the menu belongs to a private library.
As with private instances, if an item reference to any object within a private library is
passed to an object outside the library, it is able to access the library using notation.
You can make a library private by setting its $isprivate property to true. This is normally
done immediately after opening the library, but can be done at anytime as long as the task
which owns the library is the active task. Libraries also have the $alwaysprivate property,
which, if set, means they are always and immediately private to their startup task.
Private libraries have an additional property, $nodebug, which keeps the debugger from
being entered for any reason when code from that library is executing, including errors,
breakpoints, and the stop key. Code from a private library with $nodebug set does not
appear in the stack menu or the trace log.
When a task is closed, it closes all its private libraries unless they cannot be closed. This
can occur if, for example, the library has instances belonging to other tasks. If a private
library cannot be closed, it will become non-private.
110
Using Tasks
Multiple Tasks
When designing an application, you might want to partition your library by creating
modules containing all of the windows, reports and methods of like functionality. Each
module can have its own menus and toolbars. An example containing such modules might
be an accounting package, with General Ledger, Accounts Payable and Accounts
Receivable modules.
In a totally modal application, where the user switches between modules, it is easy to ensure
that the user sees the correct menus and tools for the current module. In a modeless, multiwindow environment, controlling this can sometimes be difficult. Tasks automate the
process of creating modular applications by providing all the management of menus and
tools for you.
Consider the following example in which a single library is running three tasks: the
Startup_Task and two user tasks Task1 and Task2. The startup task, which opens
automatically when the library opens, contains an About window. The other two tasks each
contain a window, a menu, and a toolbar. When the user selects a window from either Task1
or Task2, you may want Omnis to display the correct tools and menus for that window
automatically.
About window
Menu 1
Toolbar 1
Menu 2
Toolbar 2
Window 1
Startup_Task
Window 2
Task1
Task2
When the library opens, the startup task opens and displays the About window and then
opens the other tasks, each of which opens its window and installs its menu and toolbar. The
startup task can close itself once the About window is closed if its no longer needed.
To open the two tasks, you should execute the following in the $construct() method of the
startup task
Open window instance AboutWindow
Open task instance MyTaskClass1/Task1
Open task instance MyTaskClass2/Task2
Close task instance LibraryName ;; close Startup_Task instance
Every task has a property $autoactivate, that allows the task to take control whenever the
user tries to bring a window it owns to the front. If the property is set to false, the window
wont come to the front. To activate each task automatically, you need to execute the
following in the $construct() of each task
Do $ctask.$autoactivate.$assign(kTrue)
111
This functionality will change menus and toolbars as you switch from one window to the
other.
Mac OS X Preferences
The Mac OS X application menu has a Preferences item. You can arrange for Omnis to call
a method in a task, when the user selects this menu item. To do this, define a method called
$prefs in your task. When the user selects Preferences from the application menu, Omnis
calls the $prefs method.
If more than one task defines $prefs, Omnis installs a hierarchical menu on the Preferences
menu item. Each task has an item in the hierarchical menu. In this case, each task must also
contain a method called $prefsmenutext. This method must return the text to display for the
tasks item in the hierarchical menu, for example
Quit Method My Library
112
You can drag a reference to any of the components from the Notation Inspector to your
code, in the same way as other built-in objects. You can click on a component library in the
Notation Inspector and view its properties in the Property Manager. Each component library
has the following properties
$name
the name of the component which must be unique
$pathname
the name and path of the external library file; this will vary across different platforms
$functionname
the name of the external function
$controlhandler
Boolean that indicates whether the external is a control handler, for example, an
ActiveX is a control handler
$constprefix
String used as a prefix for all constants within the external
$flags
indicates the external flags, for example, whether it is loaded
$usage
Current number of controls that are using this external
$version
the version information
You can view the contents of an external library in the Notation Inspector. Each component
library has a group called $controls containing all the controls in the library. Some libraries
may contain only one control, for example, the Slider Component Library contains the
113
In general, the properties of an external component are unique to the object and their names
will not clash with standard Omnis field properties. However when an external component
property has the same name as an Omnis property, you must access the external property
using a double colon (::) before its name. For example, the Icon Field control has the
property $backcolor which you must refer to using
Do $cinst.$objs.iconfield.$::backcolor.$assign(kRed)
; would not work without the ::
At runtime you can add an external component to an open window using the $add() method.
You need to specify the kComponent object type, external library name, external control
name, and the position of the field. For example, the following method adds the Marquee
Control to the current window instance, positions the new object, and sets some of its
properties
; declare local variable Objref of type item reference
Do $cinst.$objs.$add(kComponent,'Marquee Library','Marquee
Control',0,0,15,100) Returns Objref
Do Objref.$edgefloat.$assign(kEFposnStatusBar)
; repositions the object at the bottom of your window
Do Objref.$message.$assign('I hope you can read quickly!')
Do Objref.$steps.$assign(20)
;; number of pixels to step
Do Objref.$speed.$assign(20)
;; lower number is faster
Do Objref.$::textcolor.$assign(kBlue)
;; note :: notation
Do Objref.$::backcolor.$assign(kRed)
114
Version Notation
All external components have the $version property. To get the version of an external
component you must access it via the $root.$components group, not the external component
field on a window or report. For example
Do $root.$components.Marquee Library.$version Returns lvXversion
; returns 1.2 for example
If you have created any external components of your own to run under Omnis Studio
version 1.x, you must recompile them for Omnis Studio 2.0.
Java Beans
The Java Bean external component has commands that let you control it in a Runtime
Omnis. Note the Java Beans external is available under Windows only.
You request a command using the $cmd() method as follows:
$root.$components.JavaBean.$cmd(parameter list)
Command
"GetPaths", List
Populates the specified single column list with the Java Bean
search paths; no return value
"AddPath", NewPath
Adds the specified path to the Java Bean search paths; returns
true for success, or if the path is already present in the search
paths
"DeletePath", DelPath
Deletes the specified path from the Java Bean search paths;
returns true for success
"EnumBeans"
"StartVM"
"SetupDialog".
"RequestPath"
Opens the Prompt for Java Bean Path dialog; returns a string
containing the new path; empty if none selected
115
116
Chapter 4Debugging
Methods
You add variables and methods to the objects in your library using the Method Editor. You
can edit and debug the methods in your library using the Omnis debugger which is an
integral part of the method editor. Using the method editor, you can:
Insert and Edit methods
Run and step through methods
Set breakpoints
Trace the execution of method lines and field values
View and alter fields and variables
Inspect the method stack
Debug your code using the debugger commands
The Omnis debugger provides several tools to help you monitor the execution of a method,
including the ability to create watch variables, interrogate and edit the contents of variables
during execution, and place a variety of breakpoint conditions, which when met will
interrupt execution.
The debugger operations are controlled from the Debug and Options menus on the method
editor menubar. The debug options are also on the toolbar, which you can show using the
View>>Toolbar menu option. The hierarchy of methods calling other methods is saved in
the method stack and shown on the Stack menu.
You can also check your code using the Method Checker, available under the Tools menu
and described in this chapter.
117
Open the design screen for the class from the Browser
Code, task, table, and object classes contain methods only, so when you modify these
classes you go straight into the method editor. To add methods to these classes you can
double-click on the class name in the Studio Browser.
The method editor has several different areas, each doing a different job. These are
Menubar and Toolbar
let you add, edit, and execute methods, in addition to debugging the methods in your
application
Variables panes
lets you add variables to the class or method, for example, instance or local variables
Method names and Method definition
lets you add methods to the object, lists existing methods for the object, lets you add
the code for a method, or view the code for an existing method; the method tree list
shows the methods for the class and the individual objects in the class.
You can Right-click on the method tree list to insert a new method (at the end of the
list, or before/after the currently selected method), delete or rename a method, Cut or
Copy a method, or Expand/Collapse the entire method tree.
Command palette
lists all the commands, and the parameters for the current command
118
Debugging Methods
Watch variables pane
lets you monitor variable values while debugging
To insert a method
Right-click on the method list and select Insert New Method, Insert New Method
Before, or Insert New Method After
or
Click on the Modify menu in the method editor toolbar and select Insert New Method
or
When you have entered the new method name, you can begin to add the code for the
method in the right-hand pane of the method editor.
Line Numbers
You can display a line number for each method line in your code. You can enable line
numbers using the View menu in the Method Editor.
Debugging Methods
You can open most class and field methods and run them from the debugger menu bar or
toolbar. Note that event handling methods will not run from the On command without the
event, but you can try out most types of methods while you are in design mode. You cannot
execute methods that contain instance or task variables at design time since these variables
are only available when the objects are instantiated.
To run or execute a method
or
Execution will begin from the selected line. When you first open the method editor the first
line of the first method is selected. You can halt execution by pressing the stop key
combination Ctrl-Break/Cmnd-period/Ctrl-C. When you break into a method the debugger
completes the current command and halts execution.
The basic debugging operations on the Debug menu are
Go executes from the Go point
119
The Go Point
A method normally runs from the start, but you can start execution from any method line by
setting it as the Go Point.
To set the Go point
or
Select the method line and choose the Debug>>Set Go Point menu option
or
Select the method line and click the Set Go Point button on the toolbar
The debugger highlights this line and puts a yellow arrow in the left margin pointing to the
method line where execution will begin. You can move around the program, changing the
code, without changing the go point, which is independent of the current line. The name of
the method containing the Go point is shown in the Debug menu and choosing this option
from anywhere returns you to the Go point. You can clear the Go point using Stack>>Clear
Method Stack.
Commenting Methods
You can add comments to your code using the ; Comment command. Comments are useful
to document your methods, or temporarily comment out or disable individual lines or
blocks of code. The latter is useful when you are debugging methods.
120
Debugging Methods
To enter a new comment in a method, insert a new line and type ; (semi-colon) while the
focus is in the Command list in the method editor to locate the Comment command. Enter
your comment text in the text box provided.
To comment out existing commands, select the lines of code in the method editor and
press Ctrl/Cmnd-; (semi-colon). To uncomment code, that is, to remove the comment
marks, select the line or lines of code and press Ctrl/Cmnd- (apostrophe). You can also
Right-click on selected lines of code to Comment or Uncomment them.
Execution Errors
When an error occurs in a running method, Omnis takes you into the debugger. The
offending method is displayed with the go point at the method line that encountered the
error, and an error message is shown in the status area. Error messages include the error
number and text, for example E108139: Set main file command with no valid file name.
You can use the various inspection tools to find out why the error occurred, fix it, and
continue.
You can use the Debug>>From Line submenu to run the method from the currently selected
line rather than the go point. The submenu items let you Go, Step, Step Over, or Trace from
the current line instead of from the go point. The To Line submenu lets you Go or Trace
from the go point to the current line, which becomes a one-time breakpoint.
Choose Debug>>Step from the debugger menubar, or click on the Step In button
Every time you click on the Step In button, Omnis executes the line at the go point and sets
the go point to the next line. If a command at go point calls another method, the debugger
loads the recipient method on the method stack and sets the go point to the first line in that
method.
The Step In option steps into a recipient method. You can avoid this with Step Over where
the debugger executes the recipient method without stepping into it. This speeds up
debugging if you have a lot of method calls.
121
Tracing a Method
As well as stepping through your code, you can record or trace method execution.
To trace a method
Choose Debug>>Trace from the debugger menubar, or click on the Trace button
The debugger steps through your code automatically, including stepping into recipient
methods, and adds each method line and its parameters to a trace log. You open the log
from the Tools menu.
The first column in the trace log shows the name of the currently executing method, and the
class it belongs to. The second column shows the method line and parameters of the
currently executing command. When you double-click on a line in the trace log, the
debugger goes to and highlights that method line.
You can open the trace log from within a method using the Open trace log command. For
example, you can place the Open trace log command in the startup task of your library to
trace method execution immediately after your library opens.
You can specify the maximum number of lines in the log in the Max lines entry field. When
the log contains that many lines, it discards the earliest lines when new ones are added.
Private Methods
When you step or trace through the methods in your library the debugger will normally
enter each method that is called, even if a method is in a private library. However if you set
the library property $nodebug to true, the debugger will not display methods contained in
private libraries. You need to set this property each time you open the library.
122
This menu contains the variable name, value, parent group and data type, and a series of
debugging options you can apply to the variable. If you click on a variable name in the
variable pane of the method editor, the context menu has the Insert New and Delete
Variable options as well. The other options at the bottom of the context menu are discussed
under Breakpoints. The first option Variable opens the Variable Value window, except that
for Item References with a value, it opens the Notation Inspector.
This window shows the variable name and type at the bottom and displays the value, which
you can edit. Omnis updates the value in the window whenever you bring the window
containing the method to the top, but you cannot observe the value change dynamically
through this window.
On the Variable Value windows View menu
Redraw Values redraws the variable on any window
Single Window Mode shows subsequent variable values in the same window
You can show and edit a list variable in a value window in just the same way. Note you
cannot edit the binary variable.
The value window for a variable is valid only for as long as the variable is current.
Select the Class Variables option from the variable context menu
123
or
In the method editor, drag the variable from the variable pane into the watch pane
The Watch Variable item on the context menu is now checked. You can enlarge the watch
pane by dragging its borders. The watch variable value is only updated when stepping,
unless the method redraws it.
To remove a watch variable
124
Right-click on the variable name and uncheck Watch Variable on the popup menu
Breakpoints
Breakpoints
A breakpoint is a marker on a method line. When the debugger reaches that line, it stops
execution and makes that line the go point. When a breakpoint is encountered and you have
switched to a different application (such as a browser in the case of debugging JavaScript
Client methods) the Omnis entry in the Windows Task bar will flash and you have to click
the button to return to Omnis to continue debugging.
To set a breakpoint
or
When you set a breakpoint for a line, a red dot appears in the left margin. A one-time
breakpoint is a breakpoint that the debugger removes immediately after you break on it. It is
marked by a blue dot in the margin.
When you close a library, you lose all breakpoints in the methods in that library. You can
use the Breakpoint command in a method to set permanent breakpoints, but you must be
careful using permanent breakpoints since you may forget to remove them and they may be
encountered in your application when it is deployed to end users!
The Breakpoint menu lets you create and clear breakpoints.
Breakpoint (Ctrl/Cmnd-Shift-B)
sets a full breakpoint at the current line
One-time Breakpoint (Ctrl/Cmnd-Shift-O)
sets a one-time breakpoint at the current line
Clear Breakpoints (Ctrl/Cmnd-Shift-C)
clears all the breakpoints
Clear Field Breakpoints (Ctrl/Cmnd-Shift-F)
clears all the field change breakpoints, calculation breakpoints, and min and max
settings (see below)
The rest of the Breakpoint menu is a list of all the current breakpoints. Choosing a
breakpoint from this menu displays the line in the debugger.
You can also set breakpoints and from line to line execution, by right-clicking in the left
margin of the method line or by using the appropriate tools on the toolbar.
125
Breaking on Calculation
You can also create a variable value breakpoint with a calculation. For example, to stop a
method when a local variable lvLines becomes equal to the number of lines in list cvList,
the calculation is entered as
lvLines = lst(cvList,cvList.$linecount)
The menu option Break On Calculation sets the breakpoint, and the following line Set
Calculation prompts for the calculation. The debugger treats the calculation value as a
boolean value where zero corresponds to No and anything else corresponds to Yes.
Execution breaks when the calculation evaluates to Yes, but with a qualification: the break
happens only when the calculation changes from No to Yes. This means that if the
calculation is always Yes, the break never happens; it also means that the break happens
only when the change is from No to Yes, not every time the calculation evaluates to Yes.
For example, the calculation break
(lvNumber<10) | (lvNumber>20)
ensures that local variable lvNumber stays within the range 10-20.
Each variable or field can have one calculation breakpoint. There is no requirement that the
calculation refers to the variable.
The Store Min And Max option adds the minimum and maximum variable values to the
end of the menu as execution proceeds, along with the item Clear Min and Max that lets
you turn off the feature. If you choose either menu item, Omnis writes a line to the trace log.
Turning on Store Min And Max slows down the debugger a good deal.
126
127
Description
classitem
object
method
line
linetext
params
The sys(192) functions works in both the development and runtime version of Omnis.
Debugger Options
The debugger Options menu appears with the other debugger menus.
Debug Next Event
stops at the first line of a method executed for an enter-data event with a control
method (a field method, a window control method or a timer method). Note this option
is not saved with other debugger options and defaults to off whenever Omnis is started
Trace All Methods
sets trace mode permanently on.
Open Trace Log
opens the trace log window or brings it to the top
Disable Debugger at Errors
stops Omnis from breaking into the debugger on program errors; this is what the end
user of your application would see
Disable Debugger Method Commands
deactivates any debugger commands in the methods
Save Debugger Options saves all the debugger options, and Revert To Saved Options
reverts back to the last saved set of debugger options
128
Debugger Commands
Debugger Commands
You can control the debugger using the commands in the Debugger... group. See the Omnis
Help for a complete description of the following commands. Note that none of the
Debugger commands will work in client executed methods in the JavaScript Client,
however, while developing your app, you can use the Send to trace log command in a client
method to write a line to the JavaScript console.
Breakpoint breaks the program when Omnis executes it. If you specify a message, it appears
on the status line when the break happens. Trace on switches trace mode on, optionally
clearing the trace log, and Trace off switches trace mode off.
Send to trace log adds a new line to the trace log containing the specified text. The text can
contain variable names enclosed in square brackets. You can then use the log as a notepad
for your comments, variable or field values, and bookmarks in the code. If you enable the
Diagnostic message option in the Send to trace log command Omnis will send the message
to the trace log substituting any variable values where appropriate. To enable diagnostic
messages in the trace log, you must right-click on the trace log and select the Log
Diagnostic Messages option.
You can double-click on lines in the trace log to open the method editor at the appropriate
point in the method.
The Variable menu command applies a variable context menu option to a list of variables.
The list has the same format as Define list, and for fields can include file names and so on.
This command has several options.
Set break on field change
sets a field change breakpoint for each field in the list
Clear break on field change
clears any field change breakpoints for each field in the list or all breakpoints if you
dont specify a field list
Set break on calculation
sets a calculated breakpoint for each field in the list; set the calculation for each field
with Set break calculation
Clear break on calculation
clears any calculated breakpoints for each field in the list or all calculated breakpoints
if you dont specify a list
Store min and max
stores minimum and maximum values for each field in the list
Do not store min and max
clears store min and max mode for each field on the list or all modes set if you dont
specify a list
129
Checking Methods
You can check the methods in your library using the method checker. The method checker
is available under the Tools menu on the main Omnis menu bar. It checks your code for
syntax errors, unused variables, methods without code, and so on. It provides various levels
of checking and reports errors in individual classes or all classes in the current library. It is
particularly useful for checking libraries converted from an earlier version of Omnis.
Note that the method checker does not correct the code in your libraries automatically, it
simply reports any errors and potential problems in your code.
When you open the method checker it loads all libraries that are currently open.
Alternatively you can open a particular library from within the method checker.
130
Checking Methods
To check the methods in your library
Select the Tools>>Add-ons>>Method Checker menu item from the main Omnis menu
bar
If you need to load a library, click on the Open Library button on the method checker
menu bar
Double-click on the library you want to check
Shift-click or Ctrl/Cmnd-click to select the classes you want to check, or click on the
Select all classes button to select them all
The method checker works through the classes you selected displaying their statistics in the
Method Checker Error Log. You can cancel checking at any time by pressing CtrlBreak/Cmnd-period/Ctrl-C.
When checking is complete, you can sort the log by clicking on one of the headers in the
list. You can print the log or save it to a text file.
You can show a summary of the errors for each class by clicking on the Show Summary
button.
Fatal Errors
These are the type of errors that you must fix.
131
Level 1 warnings
These are the type of problems that you ought to fix.
Class variable with the same name as a library variable
Could cause precedence problems at the class level.
Optimize method command not in first line of method
The Optimize method command should be the first line of a method.
132
Checking Methods
Code in an unnamed method
Named method with no code
Check to see if this code/method is required.
Debugging code?
You should remove all breakpoints before deploying your application. One of the following
was encountered: Breakpoint, Trace on/off, Field menu command, Set break calculation,
Send to trace log.
Debugging message?
Either OK message or Sound bell was encountered: remove messages inserted for
debugging purposes.
Obsolete command
You should not use obsolete commands: remove them from your code. For example you can
replace Call method with Do method or Do code method.
Command removed by converter
In converted libraries certain commands are commented out: you should use another
command or use the equivalent notation.
Level 2 warnings
These are the type of problems that you should investigate that might require fixing.
Unused variable
Variable defined but unused, or referenced and not defined.
Unfriendly code: Code which could affect other libraries if running in a multi-library
environment
For example, Clear method stack, Quit all methods, Close all windows, Remove all menus.
Unfriendly code: Code which would cause the current library to be closed
The following commands will close the current library if the Do not close other libraries
is not set: Open library, Create library, Prompt for library.
Class name specified in an internal method call
Inefficient code.
Code that modifies a library or class
One of the Classes... group of commands, such as New class, Rename class, Delete class.
Platform-dependent code
Functions which return different values depending on which platform they are executed,
including sys(6), sys(10) to sys(22), sys(103) to sys(114).
Comment containing a question mark
Usually indicates code that needs to be tested, completed, or fixed.
Reference to hash variable
Avoid using hash variables: replace with variable of appropriate scope.
133
Method Performance
Omnis Studio allows you to collect data about the performance of method execution in your
application.
134
Sequence Logging
Classes that contain methods, and can therefore collect method performance data, have two
new methods:
$clearperformancedata()
Clears the performance data for all methods in the class
$makeperformancedatalist()
Returns a list containing the performance data collected for all methods in the class
There is a very small overhead when data is collected, while there is no impact on
performance when performance data is not being collected.
Sequence Logging
Sequence logging allows you to record all method execution in the Development version of
Omnis or on the Omnis Server which is used for deploying Omnis web and mobile
applications. If your Omnis Server is running multi-threaded mode, sequence logging can
log method execution on multiple server threads.
Sys(3000) turns on sequence logging, and sys(3001) turns it off. Sequence logging writes
every method command executed to a file in the Omnis directory. The name of the file is
reported by an OK message when logging starts. Logging is thread-safe.
The log file can be up to 2mb in size, and when that limit is reached it discards all but the
most recent 256kb and continues logging. Logged lines can be of any length. The log file
name includes the date. The log file is UTF-8 and has a signature to mark it as such.
Each line in the file is prefixed with "N: " where N identifies the thread. Zero is the main
thread. 1-N are Omnis Server threads.
When logging starts, Omnis writes a message to the log file, to allow the developer to
identify logging being started and stopped.
135
Chapter 5Object
Oriented Programming
This chapter discusses the object-oriented features used in Omnis Studio, including
inheritance, custom properties and methods, and creating and using object classes and
external objects.
Inheritance
When you create a new class you can derive it from an existing class in your library. The
new class is said to be a subclass of the existing class, which is in turn a superclass of the
new class. You can make a subclass from all types of class except code, schema, file, and
search classes. The general rule is that if you can open or instantiate a class, you can make a
subclass of that type of class. Omnis does not support mixed inheritance, that is, you cannot
make a subclass of one type from another type of class.
When you make a subclass, by default, it inherits all the variables, methods, and properties
of its superclass. Window subclasses inherit all the fields and objects on the window
superclass, and menu and toolbar subclasses inherit all menu lines and tools from their
respective superclass.
Inheritance saves you time and effort when you develop your application, since you can
reuse the objects, variables, and methods from a superclass. When you make a change in a
superclass, all its subclasses inherit the change automatically. From a design point of view,
inheritance forces uniformity in your GUI by imposing common properties, and you get a
common set of methods to standardize the behavior of the objects in your library.
Making a Subclass
You can make subclasses from the following types of class.
Window
inherits variables, methods, and properties from its superclass, as well as all fields on
the window superclass
Menu
inherits variables, methods, and properties from its superclass, as well as the menu lines
in the menu superclass
136
Inheritance
Toolbar
inherits variables, methods, and properties from its superclass, as well as the toolbar
controls in the toolbar superclass
Report
inherits variables, methods, and properties from its superclass: note that a report class
does not inherit the fields, sections, and graphics from its superclass
Task
inherits variables and methods from its superclass, but none of its properties
Table
inherits variables and methods from its superclass, and only some of its properties
Object
inherits variables and methods from its superclass, but none of its properties
To make a subclass
Right-click on a class and choose Make Subclass from its context menu
When you make a subclass Omnis creates a new class derived from the selected class. The
new class inherits all the objects, variables, and methods from its superclass. Omnis
supports up to 10 superclass levels, that is, a single class can inherit objects from up to ten
other superclasses that are directly in line with it in the inheritance tree. If you create further
levels of subclass they do not inherit the objects from the superclasses at the top of the tree.
You can view and edit a subclass, as you would any other class, by double-clicking on it in
the Browser. When you edit the methods for a subclass in the method editor, you will see its
inherited variables and methods shown in a color. When you view the properties of a
subclass its inherited properties are shown in a color in the Property Manager. You can set
the color of inherited objects using the inheritedcolor Omnis preference. Note that all the
Appearance and Action properties for a window are inherited too.
Standard properties for the class, such as the window name and class type, are not inherited,
neither are the grid properties. The properties to do with the general appearance of the
window, such as title and hasmenus, are inherited and shown in a color, which defaults to
bright blue. You cannot change inherited properties unless you overload them: their values
are grayed out in the Property Manager. If you change the properties of the superclass, the
changes are reflected in the subclass when you next open it in design mode.
137
inheritedorder
issupercomponent
componenticon
Right-click on the property and select Inherit Property from its context menu
If the property cannot be inherited the context menu will display Cannot Inherit and will be
grayed out. If the class does not have a superclass the inheritance context menu does not
appear or is grayed out.
To inherit a method manually
Right-click on the method and select Inherit Method from its context menu
When you inherit a method in this way, Omnis will delete the current method.
138
Inheritance
fields, menu lines, or toolbar controls. If you dont want certain objects to be displayed in a
subclass you can hide them temporarily at runtime using the notation.
To overload a property
When you overload a property its inherited value is copied to the class and becomes
editable in the Property Manager. You can overload any number of inherited properties in
the class and enter values that are local to the class.
To reverse overloading, you Right-click on a property and select Inherit Property: the local
value will be overwritten and the value inherited from the superclass will appear in the
Property Manager.
To override a method
Right-click on the inherited method and select Override Method from its context menu
When you override a method it becomes like a non-inherited method in the class, that is,
you can select it and add code to it.
To reverse this process and inherit the method with the same name from the superclass, you
can right-click on the method and select Inherit Method: the code in the non-inherited
method will be deleted and the inherited method will now be in place. Alternatively, if you
override a method and then delete the local one, the inherited method will reappear when
you close and reopen the class.
To override a variable
View the methods for the subclass in the method editor and click on the appropriate tab
in the variable pane to find your variable
Right-click on the inherited variable and select Override Variable from its context
menu
When you override a variable it becomes like a non-inherited variable in the class and is
only visible in that class.
To reverse this process and inherit the variable with the same name from the superclass, you
can Right-click on the variable and select Inherit Variable.
139
Inheritance Tree
The Inheritance Tree shows the superclass/subclass structure of the classes in your library.
All classes below a particular class in the hierarchy are subclasses of that class. When you
select a class in the Browser and open the Inheritance Tree it opens with that class selected,
showing its superclasses and subclasses above and below it in the tree.
To open the Inheritance Tree for a class
Right-click on the class and select Inheritance Tree from its context menu
At this stage, all the supercomponents of that type (i.e. classes that have their
$issupercomponent set to kTrue) should be displayed in the wizard.
Enter a name for the subclass and click on the Create button
Such supercomponents will only appear in the Studio Browser if the library containing it is
open, since the class actually remains in your library and is only displayed in the Studio
Browser.
Note that classes that appear in the Studio Browser in this way cannot be made the default
object for that class.
140
Inheritance
Inheritance Notation
You can use the $makesubclass() method to make a subclass from another class. For
example
Do $windows.Window1.$makesubclass(Window2) Returns ItemRef
; creates Window2 which is a subclass of Window1 in the
; current library, ItemRef contains a reference to the new class
You can test if the current class can be subclassed by testing the $makesubclass() method
with the $cando() method, as follows
If $cclass.$makesubclass().$cando()
Do $cclass.$makesubclass(sClass) Returns ItemRef
; creates a subclass of the current class
If a property can be inherited, you can overload or inherit the property by assigning
$isinherited. For example, to overload a property
Do $cclass.$PROPERTYNAME.$isinherited.$assign(kFalse) Returns lresult
However, if you have overridden a property or method in the subclass the method in the
subclass is called. You can still access the inherited property or method using the $inherited
property. For example, assuming $MethodName() has been overridden in the subclass
Do $cinst.$inherited.$MethodName()
; will call the subclass method
Do $windows.MySubWin.$MethodName().$inherited
; will call $MethodName() in the superclass
Referencing Variables
When a variable is referenced in a subclass, Omnis looks for its value first in the subclass
and progressively up the chain of superclasses in the inheritance tree for the current library.
Therefore if you havent overridden the variable in the subclass, or at any other level, the
value at the top of the inheritance tree is used.
However, if you have overridden a variable in the subclass the value in the subclass is used.
You can access the inherited variable using $inherited.VarName, in which case, the value at
the top of the inheritance tree is used.
A superclass cannot use the instance and class variables of its subclasses, although the
subclass can pass them as parameters to superclass methods. References to class and
instance variables defined in a superclass are tokenized by name and the Remove Unused
Variables check does not detect if a variable is used by a subclass. If an inherited variable
does not exist, its name is displayed as $cinst.VarName in design mode and will create a
runtime error.
Do inherited Command
You can use the Do inherited command to run an inherited method from a method in a
subclass. For example, if you have overridden an inherited $construct() method, you can use
142
$addafter
$addbefore
$appendlist
$assign
$att
$attcount
$attributes
$canassign
$cando
$canomit
$chain
$chaincount
$class
$count
$data
$default
$deletelines
$desc
$findident
$findname
$first
$fullname
$group
$ident
$insertlines
$insertlist
$inst
$isinherited
$last
$lib
$minparms
$makelist
$maxcachedclasses
$maxparms
$method
$name
$next
$prev
$obj
$ref
$remove
$runapplescript
$sendall
$serialize
$sublen
$subtype
$type
$wind
Any class that can be instantiated can contain custom notation, including window, report,
table, and object classes. In practice you can use custom notation to override the behavior of
the standard notation, or to add your own properties and methods to an object.
With the exception of the names in the above table, if the name of a custom property or
method is the same as a standard one, such as $printrecord(), it will override the standard
one.
143
Userinfo property
File, window, report, menu, toolbar, schema, and query classes have the $userinfo property
which you can use to store your own value. The Property Manager only allows you to assign
to $userinfo if its current value is empty, null or has character or integer data type. The data
stored in $userinfo can be of any other type but it must be assigned to the class at runtime
using the $assign() method.
144
The $printprinter() method sets the print destination and calls another class method
depending on whether the user is accessing SQL or Omnis data; it contains the following
code
; $printprinter() custom method
Begin reversible block
Send to printer
Set report name REPORT1
End reversible block
If iIsSQL
Do method printSQLData
Else
Begin reversible block
Set search name QUERY1
End reversible block
Do method printOmnisData
End If
The next example uses a window that contains a pane field and a toolbar with three buttons.
When the user clicks on a button, the appropriate pane is selected and various other changes
are made. Each button has a $event() method that calls a custom method called $setpage()
contained in the window class. Note that you can send parameters with the custom method
call, as follows
; $event() method for second toolbar button
Do $cwind.$setpage(2)
145
The final example uses a window containing a subwindow, which in turn contains a tree list.
The subwindow contains a custom method called $buildtree() that builds and expands the
tree list. You can call the $buildtree() method from the parent window and send it
parameters, using the notation
Do $cwind.$objs.SubWin.$buildtree(lv_ClassList)
The $buildtree() method contains a parameter variable called pv_SourceList of List type
that receives the list passed to it, and a reference variable called TreeRef set to the tree list
field, and contains the following code
; $buildtree() custom method
Do TreeRef.$setnodelist(kRelationalList,0,pv_SourceList)
Do TreeRef.$expand()
146
Object Classes
Object Classes
Object classes let you define your own structured data objects containing variables and
methods. You can create an object variable based on an object class which contains all the
variables and custom methods defined in the class. When you reference an object variable
an instance of the object class is created containing its own set of values. You can store an
object variable instance and its values on a server or Omnis database. The structure and data
handling capabilities of the object instance is defined by the types of variables you add to
the object class; similarly, the behavior of an object variable is defined by the methods you
add to the object class.
Object classes have the general properties of a class and no other special properties. They
can contain class and instance variables, and your own custom methods. You can make a
subclass from an object class, which inherits the methods and variables from the superclass.
To create an object class
Alternatively, you may want to create an object class using one of the wizards. In this case,
you should click on Class Wizard, then Object, and select one of the wizards.
When you modify an object class, Omnis opens the method editor for the class. This lets
you add variables, and your own custom properties and methods to the class.
When you have set up your object class you can create any other type of Omnis variable
based on your object class: an object variable has type Object and its subtype is the name of
your object class. For example, you can create an instance variable of Object type that
contains the class and instance variables defined in the object class. When you reference a
variable based on an object class you create an instance of that object class. You can call
the methods in the object class with the notation ObjVarName.$MethodName(), where
$MethodName() is any custom method you define in the object class.
You can store object variable instances in an Omnis data file, or in a server database that
stores binary values. When you store an instance of an object variable in a database, the
value of all its contained instance variables are also stored. When the data is read back into
memory the instance is rebuilt with the same instance variable values. In this respect you
can store a complete record or row of data in an object variable.
You can store object instances in a list. Each line of the list will have its own instance of the
object class. Object instances stored in a task, instance, local, or parameter variable belong
147
If you right click on an object variable, and use the Variable <name>... entry in the context
menu, the variables list window opens, initially showing instance variable values.
148
Object Classes
; $SaveInvoice() method contains
; local var lv_InvoiceRow of type Row and
; local var lv_Bin of type Binary and
; parameter var pv_Object of type Field reference
Do lv_InvoiceRow.$definefromtable(t_Invoices)
Calculate lv_bin as pv_Object
Calculate lv_InvoiceRow.InvoiceObject as lv_bin
Do lv_InvoiceRow.$insert() Returns #F
; $SelectInvoice() method contains
; local var lv_Row of type Row
Do lv_Row.$definefromtable(t_Invoices)
Do lv_Row.$select()
Do lv_Row.$fetch() Returns #S1
Quit method lv_Row.InvoiceObject
; $FetchInvoice() method contains
; local var lv_Row of type Row
Do lv_Row.$definefromtable(t_Invoices)
Do lv_Row.$fetch()
Quit method lv_Row.Inv_Object
; $total() method
Quit method iv_QTY * iv_Value
The invoice window can contain any fields or components you want, but would contain
certain fields that reference the instance variables in your object class, and buttons that call
the methods also in your object class.
The invoice window contains no class methods of its own. All its functionality is defined in
the object class. The window contains a single instance variable called iv_Invoice that is
based on the o_Invoice object class.
The instance variable would have the type Object and its subtype is the name of your object
class, o_Invoice in this case. If the object class is contained in another library, the object
class name is prefixed with the library name.
When you open the invoice window an instance of the object class is created and held in
iv_Invoice. Therefore you can access the instance variables and custom methods defined in
the object class via the instance variable in the window; for example, iv_Invoice.iv_QTY
accesses the quantity value, and iv_Invoice.$SaveInvoice() calls the $SaveInvoice()
method. Each field on the invoice window references a variable in the object class; for
example, the dataname of the quantity field is iv_Invoice.iv_QTY, the dataname of the item
or description field is iv_Invoice.iv_Item, and so on.
The buttons on the invoice window can call the methods defined in the object class, as
follows.
149
When you enter an invoice and click on the Save button, the $SaveInvoice() method in the
object class is called and the current values in iv_Invoice are passed as a parameter. The
$SaveInvoice() method receives the object instance variable in the parameter pv_Object and
executes the following code
Do lv_InvoiceRow.$definefromtable(t_Invoices)
Calculate lv_bin as pv_Object
Calculate lv_InvoiceRow.InvoiceObject as lv_bin
Do lv_InvoiceRow.$insert() Returns #F
The row variable lv_InvoiceRow is defined from the table class t_Invoices which is linked
to the schema class called s_Invoices which contains the single column called
InvoiceObject. The binary variable lv_bin, which contains the values from your object
instance variable, is assigned to the row variable. The standard $insert() method is executed
which inserts the object variable into your database. The advantage of using an object
variable is that all the values for your invoice are stored in one variable and they can be
inserted into a binary column in your database via a single row variable. If you want to store
object variables in an Omnis database you can create a file class that contains a single field,
called InvoiceObject for example, that has Object type, rather than Binary, and use the
appropriate methods to insert into an Omnis data file.
150
Object Classes
where parameters parm1 and parm2 are the $construct() parameters for the object instance.
When the instance is assigned, any existing instance in the object variable is destroyed. It
would be normal practice to put no class in the variable pane for object variables which are
to be set up dynamically using $new(), but there is no class checking for instance variables
so no error occurs if the class shown in the variable pane is different from the class of the
new instance.
You can do a similar thing with an external function library if it contains instantiable
objects, such as Fileops. For example
Do Fileops.$objects.fileops.$new() Returns objectvar
Do objectvar.$openfile(pFilename)
The following example uses an Object variable ivSessionObj which has no subtype defined
in the method editor. When this code executes ivSessionObj is instantiated based on the
object class SessionObj which was created using the Session Wizard in Omnis. Once the
object instance exists the $logon() method is called.
Do $clib.$objects.SessionObj.$new() Returns ivSessionObj
; runs $construct() in the SessionObj object class
Do ivSessionObj.$logon()
; runs the $logon() method in SessionObj
causes the class definition stored inside objvar1 to be replaced by the current method and
variable definitions for objectclass1. The instance variable values are maintained provided
the new instance variable definitions are compatible with the old ones (Omnis can handle
151
Object References
The Object reference data type provides non-persistent objects that you can control using
notation. Non-persistent means that objects used in this way cannot be stored on disk, and
restored for use later.
You can use the Object reference data type with local, instance, class and task variables.
Object references have no subtype. To create a new Object instance, referenced by an
Object reference variable, you use the methods $newref() and $newstatementref(). These
are analogous to the $new() and $newstatement() methods used to create object variables,
and they can be used wherever $new() and $newstatement() can be used. When created, an
object reference will belong to the current task.
Once you have associated an Object instance with an Object reference variable, you can use
it to call methods just like you would with an Object variable.
The instance associated with an object reference variable will only be destroyed in the
following circumstances:
If you use the $deleteref() method to delete the object.
The library is closed.
Until one of these occurs, Object reference variables can be passed as parameters, copied,
stored in a list column, and so on. All copies of the variable address the same single
instance of the object. As soon as the object is deleted, other references to the object
become invalid. Prior to deleting the object, Omnis calls the destructor method.
Note that this approach means that you must delete objects when you have finished with
them, otherwise significant memory and resource leaks can occur.
There is also a method $listrefs() which you can call to list the instances of an object class,
external object, or in fact all instances created in this way. This is useful both for leakchecking, and for clean-up.
You can use $newref() in conjunction with session pools. The only differences are that
$deleteref() returns the object instance to the pool, rather than destroying it, and $listrefs()
does not include objects from a session pool.
152
Object References
There are two further methods that can be used with object reference variables. $copyref()
creates an object instance which is a copy of the instance referenced by the variable, and
$validref() returns a Boolean which is true if and only if the variable references a valid
object instance. Note that if $copyref() takes a copy of a DAM session object, both copies
reference the same DAM session.
The method $objref() can also be used. If there is an object reference associated with the
instance, the method returns the object reference, otherwise returns #NULL, that is, the
object MUST have been created with a $newref().
153
Destructing objects
using an object reference variable
Do myObjectReference.$deleteref()
;; Calls the destructor of
the object instance
all instances referenced by a list column of type Object reference
Do myList.$sendall($ref.1.$deleteref())
using the $listrefs() method
Do
$extobjects.ODBCDAM.$objects.ODBCSESS.$listrefs().$sendall($ref.1
.$deleteref())
Do $libs.DAMTEST.$objects.Doracle8.$listrefs().$sendall(
$ref.1.$deleteref())
External Objects
External objects are a type of external component that contain methods that you can use by
instantiating an object variable based on the external object. External objects can also
contain static functions that you can call without the need to instantiate the object. These
functions are listed in the Catalog under the Functions pane.
Some external objects are supplied with Omnis Studio; these include equivalents to the
FileOps and FontOps externals, a Timer object, as well as the new multi-threaded DAMs.
Writing your own external objects is very similar to writing external components, which is
described in a separate manual available to download from the Omnis website. The FileOps
and FontOps functions are documented in the Omnis Help.
External objects are created and stored in component libraries in a similar manner to
external components, and in future releases are intended to replace external functions and
commands, although to maintain backward compatibility, the old external interface is still
supported at present.
154
External Objects
External object libraries are placed in the XCOMP folder, along with the visual external
components. They must be loaded in the same way as external components using the
External Components option, available in the Browser when your library is selected.
155
Interface Manager
The Interface Manager displays the public methods and properties for objects in Omnis
Studio, that is, any class that can contain methods and can be instantiated, including
window, menu, toolbar, report, task, table, and object classes (not available for code
classes). Furthermore, for window, report, toolbar, and menu classes the Interface Manager
displays the methods for the objects in the class. For each class or object, the Interface
Manager displays all built-in methods, including those available in the instance of the class,
as well as any custom methods you have added to the object.
Private methods, namely methods with a name that does not begin with a dollar sign, are not
included in the Interface Manager since these methods are confined to the class or instance.
For each method in the class or object, the Interface Manager displays the method name, its
parameters, return types, and a description, if any are present.
You can view the Interface Manager for a class via its context menu or the method editor.
To view the Interface Manager
Right-click on the class in the Browser and select Interface Manager from the context
menu
The Interface Manager contains a list of objects in the class, that is, for windows and reports
a list of window or report fields, for toolbars a list of toolbar controls, and for menus a list
of menu lines. For other types of class or instance that do not contain objects, such as object
classes, the Interface Manager contains the class methods only. You can click on each
object or field in the left-hand list to view its methods. Built-in methods are shown in the
color specified in the $nosetpropertycolor preference. Inherited methods are shown in the
color specified in the $inheritedcolor preference. The properties tab similarly shows the
objects properties.
156
Interface Manager
The Details pane shows the parameters for the currently selected method. It also lets you
add a description for your own custom methods. The status bar shows the return type for
built-in methods, but not for your own methods, since these can return any type.
The View menu on the Interface Manager menubar lets you open the method editor for the
class, in addition to hiding or showing the built-in methods and details pane.
157
Chapter 6List
Programming
Omnis has two structured data types; the list and the row. A list can hold multiple columns
and rows of data each row having the same column structure, while a row is effectively a
single-row list. You can create lists of strings, lists of records, or lists of lists. You can
define a list from individual variables, or base a list on one of the Omnis SQL data classes,
such as a schema, query, or table class. In this case, the list gets its column definitions from
the columns defined in the SQL class. Each list can hold an unlimited number of lines with
up to 32,000 columns, although you should be aware that the limitations on memory may
limit the number of rows in lists with many columns.
Omnis makes use of lists in many different kinds of programming tasks such as generating
reports, handling sets of data from the server, and importing and exporting data. The list is
the single most important data type in Omnis programming. List variables provide the data
(content) and formatting for many of the visual list components available for JavaScript
remote form classes: the different types of list controls are described in the JavaScript
Components chapter in the Creating Web & Mobile Apps manual.
In this chapter, rows are generally treated the same as lists, that is, you can use a row name
in any command that takes a list name as a parameter. In addition, references to SQL lists in
this chapter refer to lists based on either schema, query, or table classes, which are referred
to collectively as SQL classes.
158
When created?
Where visible?
When removed?
Task variable
on opening task
on closing task
Class
variable
on opening the
library
on clearing class
variables or closing
library
Instance
variable
on opening
instance
on closing instance
Local
variable
on running
method
when method
terminates
Parameter
variable
on calling the
method
Click in the Type box and choose List or Row from the droplist
159
This method will define the list cvList1 with the columns cvCol1, cvCol2, cvCol3. You can
define a list with up to 255 columns. The data type of each field or variable defined in the
list determines the data type of the corresponding column in the list.
The following example defines an instance row variable from a schema class called
'MyPictures':
; create iSqlRow of Row type
Do iSqlRow.$definefromsqlclass('MyPictures')
160
Where class is a schema, query, or table class (name or item reference to it), and the row
and parameters are optional.
The row parameter affects the columns used when the SQL class is a schema or table
referencing a schema. A row with no columns (or the parameter is omitted) means that the
list is defined using all the columns in the schema. Otherwise if the row is specified each
column in the row becomes the name of a column to add to the list definition from the
schema. The parameters can be a list of parameter values that are passed to $construct() of
the table class instance created by the method.
For example:
Do list.$definefromsqlclass('schema',row('c1,'c2'))
This method passes parameters 1, 2, 3 to $construct and includes all the columns from the
schema.
161
List/Row subtypes
A schema, query, or table class name can be used as the subtype of a list or row variable,
that is, a class, instance, local, task or parameter variable, or a column in a list or row
defined from a SQL class.
Omnis uses the subtype class to define the list or row, or in the case of parameters, to
identify the expected definition of the list or row, although Omnis does not do anything if
the definition does not match.
Schema classes have a property $createinstancewhensubtype that controls whether or not
there is a table instance associated with a List or Row variable with a schema class as its
subtype; you can set this property in the Property Manager when editing the schema class.
The property defaults to kTrue for existing and newly created schema classes. When using
the schema class exclusively with Web Services, it is likely that the table instance will not
be required, and in this case turning off $createinstancewhensubtype will therefore improve
performance.
162
To transfer the whole select table use the Build list from select table command:
; Declare class variable cvList of type List
Set current list cvList
Define list {fItems,LVAR1,LVAR5}
; defines the list with all fields from fItems, plus LVAR1 & LVAR5
Build list from select table ;; builds list from SQL query
When loading large select tables into the list, you should avoid making the user wait for the
whole set of rows to arrive before refreshing the screen to display the first fifty or so rows.
You can retrieve the rows in batches using the $linemax property which limits the size of
the list, pausing after each batch to redraw the list field.
163
You can also apply a search and sort with this command; see the Omnis Data Files chapter.
For a list defined from file class or other variables you can add values either as variables or
literals using Add line to list. This adds a line to the end of the list, or inserts a line at the
specified line and shifts other lines down.
Add line to list {('Jones','Ipswich',fCountry)}
;; adds at the end
Add line to list {10('Jones','Ipswich',fCountry)} ;; adds at line 10
164
You can use the lst() function as part of a calculation to extract a particular cell of
information from a list.
Calculate MyVar as lst(MyList, rowNumber, ColumnName)
You can address cells directly by referring to them as ListVarName.ColumnName for the
current row or ListVarName.RowNumber.ColumnName for a specified row. Omnis also
recognizes the syntax ListName(ColumnName,RowNumber). The column name must be
in quotes.
You can use RowVarName.ColumnName or RowVarName.ColumnNumber when you
assign a row variable to a window edit field. Remember that your list and row variables
should be defined in the $construct() of a form or window so they are available to edit fields
and other data bound objects when the form or window opens.
Since ListName.ColumnName and ListName.RowNumber could be ambiguous, Omnis
assumes character values are column names. In the case of the row number being contained
by a character variable, this should be indicated by adding +0.
Calculate MyNum as MyList.Amount ;; the current row
Calculate MyNum as MyList.5.Amount ;; row 5
Calculate MyNum as MyList(Amount,5) ;; Amount column, row 5
The two types of statement above are also used to assign a value to a list element.
Calculate MyList.5.Amount as 100 ;; sets Amount column, row 5 to 100
165
166
167
168
169
170
Manipulating Lists
$name
returns the column name for the list cell
$line
returns the row number for the list cell; not necessarily the current line in the list
Manipulating Lists
You can change both the structure and data of a list variable using both commands and
notation.
171
Note you cannot add a column to a list using square bracket notation or using the fld()
function. In addition, you cannot insert, remove, or move columns in a list defined from a
SQL class, since you cannot redefine schema-, query-, or table-based lists. However you
can use List.$cols.$add() to add extra columns to a SQL list.
Searching Lists
You can search a list using the $search() method, and a successful search sets the flag. You
can use a search calculation to search a list as follows:
Do MyList.$search(calculation [,bFromStart=kTrue,
bOnlySelected=kFalse, bSelectMatches=kTrue,
bDeselectNonMatches=kTrue])
For example, to search the Country column for USA you can use:
Do MaiList.$search(Country = USA) Returns myFlag
The search calculation can use list_name.colname to refer to a list column. When searching
a list column in a client method in the JavaScript Client you must prefix the column name
with $ref. For example:
Do iList.$search($ref.iCol="ABC")
With bSelectMatches or bDeselectNonMatches the first line number whose selection state is
changed is returned (or 0 if no selection states are changed), otherwise the first line number
which matches the selection is returned (or 0 if no line is found).
172
Manipulating Lists
Some of the commands that operate on a list variable use $selected to indicate their result.
For example, Search list (Select matches) will set $selected for each line that matches the
search criteria.
Each list variable has two select states, the saved and current selections. The current
selection is the set of lines currently selected, whereas the saved selection is the previous set
of lines that was selected before the current selection changed.
There are a number of commands that you can use to manipulate selected lines,
save the current selection, and swap between the selected and saved states. These
commands are described in the Omnis Studio Help.
Merging Lists
You can copy lines from one list to another using the Merge list command or the $merge()
method. Merging copies a specified set of lines from one list, and appends them to another .
The following example copies the selected lines from LIST1 to LIST2 by checking each
lines $selected property.
Set current list LIST2
Set search as calculation {#LSEL}
Merge list LIST1 (Use search)
$merge() provides slightly different capabilities in that it can match the destination columns
by column name as well as by column number. Merge list works by column number only.
The syntax is
$merge(listName, byColumnName, selectedOnly)
Sorting Lists
You can specify up to nine levels of sorting using the Sort list command or $sort() method.
To use Sort list you need to set up the sort fields first, and clear any existing sort levels
since these are cumulative. $sort() clears existing sort fields automatically. For example
Set current list {MyList}
Clear sort fields
Set sort field Country
Set sort field Town
Set sort field Name
Sort list
Redraw lists
173
Smart Lists
You can track changes made to a list by enabling its $smartlist property. A smart list saves
any changes, such as deleting or inserting rows, in a parallel list called the history list. Smart
lists can be filtered, a process which allows data not meeting a particular criteria to be made
invisible to the user while being maintained in the history list.
A smart list variable therefore contains two lists:
the normal list containing the list data, and
the history list containing the change tracking and filtering information
If you store a smart list as a binary object is a SQL database, all the smart list information is
stored automatically.
174
;; to enable it
Smart Lists
Setting $smartlist to kTrue creates and initializes the history list. If it is already kTrue, then
setting it again has no effect.
Setting $smartlist to kFalse discards the history list completely. The current normal list
remains unchanged, so the current contents of the normal list are preserved, but all history
and filtering information is lost.
If you define or redefine a list using any mechanism, or add columns to a list, its $smartlist
property is set to kFalse automatically.
175
Smart Lists
The above row properties are also properties of the list rows in the normal list, and provide
a means of going directly to the history data for a line. In this case, $rowpresent is always
kTrue, but can be set to kFalse.
177
Filtering
Filtering works only for smart lists. You apply a filter by using the $filter() method, for
example
Do ListName.$filter(COL1 = 10) Returns Count
$filter() takes one argument, which is a search calculation similar to one used for $search().
It returns the number of rows rejected from the list by the filter.
Filtering uses the row present indicator of the history list to filter out rows. In other words,
after applying a filter, Omnis has updated $rowpresent to kTrue for each row matching the
search criterion and kFalse for the others. Filtering applies only to the rows in the normal
list, that is, rows where $rowpresent is kTrue, with the result that repeated filtering can be
used to further restrict the lines in the list.
Filter Level
Each history row contains a filter level, initially zero. When you apply the first filter, Omnis
sets the filter level of all rows excluded by the filter to one; that is, for each row in the
normal list, for which $rowpresent becomes kFalse, $filterlevel becomes one. Similarly for
the nth filter applied, Omnis sets $filterlevel for the newly excluded rows to n. You can
apply up to 15 filter levels.
178
Smart Lists
Whenever a row is made present, for whatever reason, the filter level is set back to zero,
and whenever the row is made not present, for any reason other than applying a filter, the
filter level is also set back to zero.
Undoing a Filter
You can restore filtered rows to the normal list using the $unfilter() method, for example:
Do ListName.$unfilter() Returns Count
When called with no parameters, $unfilter() removes the latest filter applied. Otherwise,
$unfilter removes filters back to the level indicated by the parameter. Thus $unfilter(0)
removes all filters, $unfilter(1) removes all but the first, and so on.
Reapplying a Filter
You can reapply all the filters which have already been applied, in the same order, to all
lines present in the normal list using the $refilter() method. For example
Do ListName.$refilter() Returns Count
identifies the Nth filter currently applied to the list, that is, the filter which filtered out rows
at filter level N. Each member of the $filters group has a single property,
$searchcalculation, which is the text for the search calculation passed to $filter() when
applying the filter.
179
180
Smart Lists
Chapter 7SQL
Programming
The SQL Browser lets you connect to your server database quickly and easily, and the SQL
Form wizards let you build the interface to your server database. However you may want to
modify the SQL forms created automatically or create forms from scratch to enhance your
web and mobile apps. To do this, you use the SQL methods.
This chapter covers features of SQL programming that are common to all supported
databases. The current version of Omnis Studio supports the following server databases:
Oracle 7, 8, 9i, 10g & 11g
Sybase Adaptive Server Enterprise 12 and Sybase SQL Anywhere 9-11
DB2 Universal Server 7 9.x
PostgreSQL 8.x
MySQL 4.1 5.x
all ODBC- and JDBC-compliant databases, such as MS SQL Server 200x & MS
Access 2000
plus you can access an Omnis database (data file) using Omnis SQL
For information about features that are particular to individual supported databases, see the
Server-Specific Programming chapter.
181
Overview
The Object DAMs (Data Access Modules) provide an object-oriented mechanism for
establishing connections to a variety of SQL databases and enable you to perform multithreaded database access as part of an Omnis Server in a web application. The DAM
interface uses objects to represent a database session and session statements. These objects
provide properties and methods that let you invoke the required database functionality.
Using the object-oriented approach, an application creates object variables of a particular
DAM class that are instantiated when the object is created by the component. This is known
as a session object and represents a session of one of the supported DAM types. There is a
group of common operations that apply to all session objects and a set of database specific
operations based on the type of session object. For example, if an application requires an
ODBC session, it uses an ODBCSESS session object. The session object controls the
connection environment used to pass commands to the database server. The application
creates a statement object in order to issue SQL. A statement object can be used for all
types of statements, e.g., SQL, PL/SQL, cursors and remote procedures. There can be
multiple statement objects which share a common context provided by a single session
object.
In the Omnis Server multi-threaded environment there will be multiple clients each
accessing session objects on the same server. Although it is possible to allow each client to
use its own object this may use large amounts of system resource. Therefore, additional
functionality is provided to create and maintain session object pools where each is of the
same type. An application can allocate session objects from this pool. Each object in the
pool is connected with the same attributes when the pool is created. This has an advantage
in performance when a client requests an object since the connection is immediately
available.
182
183
Session Type
Oracle
ORACLE8SESS
Sybase
SYBASESESS
DB2
DB2SESS
PostgreSQL
PGSQLSESS
MySQL
MYSQLSESS
ODBC
ODBCSESS
JDBC
JDBCSESS
Omnis SQL
OMSQLSESS
Note that most of these will only appear in the list of available session types if the relevant
client software has been installed on your computer. DAM objects that fail to load due to
missing or incompatible client software will leave an entry in the Trace Log when Omnis is
started.
Any type of variable may be used to create a session object. However, a task variable is
particularly suitable since it enables a variety of objects within your library to easily access
the database session.
See the section on External Objects in the Object Oriented Programming chapter for further
information about creating object variables.
184
There is no limit to the number of session objects that you can create, except the limits
imposed by memory resources and server restrictions.
You need to log your session off from the server when you have finished with it using the
$logoff() method.
The connection is dropped and the session $state property is set to kSessionLoggedOff.
Depending on the session state, statements are cleared, cursors used by statements are
closed and pending results are cleared. This call will fail if the session is not currently
logged on. If it fails for any other reason, the connection may be in an undefined state and
the current object should be destroyed. If there was an active transaction on this session, the
behavior of the DBMS will determine if that transaction is committed or rolled back. The
$hostname, $username and $password properties are cleared.
The statement object can then be used to send commands and process results.
The variable StatementObj is defined as an object variable with no subtype. Again any type
of variable may be used but a task variable is convenient to enable a variety of objects
within your library to easily access the statement and its results.
185
A value of kTrue is returned if the statement was successfully prepared, kFalse otherwise
indicating that an error occurred. See the section on Error Handling for more information.
Once a statement has been successfully prepared, the value of the $state property is set to
kStatementStatePrepared.
186
The Begin statement and End statement block contains the SQL statement each line of
which is contained in an Sta: command. Other method commands such as If, End if etc. may
be included inside the block in order to build up the SQL statement using logic.
Note that in this case a $prepare() method with no parameters is used to prepare the
statement block.
When an Omnis web server is operating in a multi-threaded mode, the $prepare() method
uses the statement buffer of the current method stack.
Once a SQL statement has been prepared it is possible to obtain the contents of the
statement as a text string using the $sqltext property, for example
OK message The current SQL is {[StatementObj.$sqltext]}
The Get statement command returns a copy of the statement buffer created by the Begin
statement, End statement and Sta: commands. Get statement also replaces the bind variable
place-holders in the copy of the statement it returns, with the normal Omnis syntax for bind
variables ("@[...]").
A value of kTrue is returned if the statement was successfully executed, kFalse otherwise
indicating that an error occurred. If the statement $state property is kStatementStateClear
prior to the execution of this method it will fail. Once a statement has been successfully
executed, the value of the $state property is set to kStatementStateExecuted.
If the SQL statement generates results (e.g. a SELECT command), the $resultspending
property of the statement is set to kTrue. These results may be retrieved using the $fetch()
method.
Once a statement has been executed it may be re-executed as many times as is required
using the $execute() method. There is no need to prepare it again unless a different SQL
command is required. Re-executing a statement that has $resultspending set to kTrue will
clear the results set however.
187
Fetching Results
When a SQL statement is executed that returns results (e.g. a SELECT statement), these can
be retrieved using the $fetch() method in the form
Do StatementObj.$fetch(pTableRef,pRowCount,pAppend) Returns
lFetchStatus
The results are placed in pTableRef, which may be a list or row variable. The pTableRef
parameter may be omitted only if a previous $fetch() defined the row or list to use for
returning data.
The pRowCount is a positive integer used to specify the number of results rows to return. It
can also be set to kFetchAll to signal that all remaining rows in the result set should be
returned. When pTableRef is a list, the number of rows returned is pRowCount or less. If
pTableRef is a row variable, $fetch() always returns 1 row. If pRowCount is greater than the
number of rows in the current result set, only the available rows are returned. If there are no
more rows left in the current set, kFetchFinished is returned, otherwise kFetchOK is
returned. If the pAppend parameter has a value of kTrue, the rows returned are appended to
the list, or if kFalse, replace the previous contents of the list.
If the row or list is undefined, its column definition is created based upon the names of the
columns in the result set and the results are retrieved. This can be forced by defining the
variable as empty prior to fetching any rows. For example
Do iResultsList.$define()
Do StatementObj.$fetch(iResultsList,9999) Returns lFetchStatus
If the variable was previously defined and the definition of the list or row columns do not
match the data returned, any valid conversions are performed. If there are no more results
pending, the $resultspending property of the statement is set to kFalse. An attempt to fetch
when $resultspending is kFalse will result in a return status of kFetchError.
To limit the number of rows returned to a list use set the value of pRowCount to a value
that will not make the list too big. For example
Do StatementObj.$fetch(iResultsList,100,kTrue) Returns lFetchStatus
The number of rows to be returned is in this case up to 100. If there were more than 100
rows in the results set, the extra rows will remain waiting to be fetched. The pAppend
188
Any results generated by a statement will be available until either they have all been fetched
or another query is executed using the same statement object, in which case the previous
results set is destroyed.
$fetchinto() returns a row of data directly into the parameters supplied. A variable number
of parameters can be supplied corresponding to each column in the result set .
cFilename is the full path of the export file, formatted as required by the curremt operating
system. The filename will usually be given the extension .txt
iRowCount is an optional parameter which specifies the number of rows to write to the
export file. If iRowCount is less than the number of rows in the result set, $fetchtofile () can
be executed again in which case the result set will be fetched from the last unread row. To
retrieve all rows in the result set to the file, specify kFetchAll. If omitted, a single row is
written.
bAppend is an optional parameter which specifies whether the existing file contents should
be appended to or over-written. The default is to append the data (kTrue).
189
Batch Fetching
Where the DBMS is capable, it is possible to reduce network traffic when fetching multiple
rows of data from the database by fetching several rows simultaneously (as a single batch),
thus reducing the number of fetches required to return the entire result set.
There are three statement properties to manage batch fetching; $batchsize,
$effectivebatchsize and $maxbuffersize.
By default $batchsize is set to 1, but this can be set to any long integer value. $batchsize
should be set before the SQL SELECT statement is prepared. Changing the $batchsize
automatically clears any results which may be pending on the statement object. When
increasing the batch size, it should be noted that the memory resources required to receive
the row set will increase proportionately.
$maxbuffersize can be used to limit the batch size such that for a given column of result
data, the buffer size calculated as columnSize * batchSize will not exceed the imposed
maximum value. If the maximum buffer size would be exceeded, the batch size is revised
downward at prepare time to accommodate the maximum number of result rows per fetch.
The default value of $maxbuffersize is 32KB but will accept any long integer value greater
than 255.
190
The following object DAMs currently support batch fetching: DAMODBC, DAMORA8,
DAMSYBSE & DAMDB2. For database servers which do not support batch fetching, the
$batchsize and $maxbuffersize properties are also read-only.
Describing Results
After executing a SQL statement, you can use the $results() method to obtain information
about the columns contained in the current results set.
The only parameter required is a list variable where the information is to be placed. For
example
Do StatementObj.$results(iResultsList) Returns #F
191
Name
Meaning
ColumnName
Name of column.
OmnisData typeText
SQLData type
Length
Scale
Null
Note the use of double-quotes around the statement string, since it is necessary to embed
single quotes around the value for the character column.
If you are using the Sta: command to build up a statement, a variable may be substituted
using square bracket notation. For example,
Begin statement
Sta: SELECT * FROM authors
If iState<>''
Sta: WHERE state='[iState]'
End if
Sta: ORDER BY au_lname,au_fname
End statement
Do StatementObj.$prepare() Returns #F
192
Bind Variables
A bind variable allows an Omnis variable to be passed to a SQL statement. Instead of
expanding the expression, Omnis associates, or binds the memory address of the variable to
a SQL variable. To specify a bind variable you place an @ before the opening square
bracket. Omnis evaluates the expression and passes the value to the server directly rather
than substituting it into the SQL statement as text. You can also use this syntax to bind large
fields such as binary, pictures and lists into a SQL statement. For example
Do StatementObj.$prepare('SELECT * FROM authors WHERE state =
@[iState] ORDER BY au_lname,au_fname') Returns #F
Do StatementObj.$prepare(INSERT INTO authors (au_lname,au_fname)
VALUES (@[iRow.au_lname],@[iRow.au_fname]) Returns #F
Note that you do not need to place quotes around a value to be substituted by a bind
variable. You must include quotes when using square bracket notation to substitute
character variables, but you dont need to when using bind variables.
Not all database systems allow bind variables; in these cases Omnis will behave as though
they do, but will instead perform literal expansion as though you had entered square bracket
notation instead of bind variables
Generally, using bind variables results in better performance than using square bracket
notation and is more flexible with respect to data representation. You should use square
bracket notation only when the notation expression evaluates to a part of a SQL statement
other than a value reference- such as an entire WHERE clause, or where you know that
simple value substitution is all you need.
If you are inserting NULL data into the database, you should use bind variables, to ensure
that SQL nulls, rather than empty strings are inserted.
Be careful to ensure when using a variable such as a local or instance variable, that it will
still exist at the time when the SQL is executed using the $execute() method. This is not
193
$createnames()
To create a new table on the server, you can use the $createnames() method. $createnames()
returns a text string which is a comma delimited list of column names and data types. Use is
of the form:
Calculate lColList as SessObj.$createnames(pRowRef)
Note that you need to include the parentheses around the column list because they are not
provided by the method.
Depending on the session object, this will create a SQL command similar to
CREATE TABLE publishers (pub_id varchar(4),pub_name varchar(40),city
varchar(20),state varchar(2),country varchar(30))
$insertnames()
To insert a row into a table, you can use the $insertnames() method. $insertnames() returns
a text string that is a comma delimited list of column names and values to be inserted. Use is
of the form:
Calculate lColList as SessObj.$insertnames(pRowRef)
Parameter pRowRef is a row or list variable. If it is a list variable, the values from the
current line (pRowRef.$line) are used.
194
Note that the method provides the parentheses around the column and values lists and the
VALUES clause automatically.
This will create a SQL command similar to
INSERT INTO publishers (pub_id,pub_name,city,state,country) VALUES
(@[iPublishersRow.pub_id],@[iPublishersRow.pub_name],@[iPublisher
sRow.city],@[iPublishersRow.state],@[iPublishersRow.country])
$updatenames()
To update a row in a table, you can use the $updatenames() method. $updatenames() returns
a text string that is a comma delimited list of column names and values to be updated. Use is
of the form:
Calculate lColList as SessObj.$updatenames(pRowRef)
Parameter pRowRef is a row or list variable. If it is a list variable, the values from the
current line are used.
This can be used in a SQL UPDATE statement. For example, to update a row in the table
publishers containing data from the row variable iPublishersRow:
Do StatementObj.$execdirect(con('UPDATE publishers ',
SessObj.$updatenames(iPublishersRow),' WHERE pub_id =
@[iPublishersRow.pub_id]')) Returns #F
$selectnames()
To select all columns in a table, you can use the $selectnames() method. $selectnames()
returns a text string that is a comma delimited list of column names to be selected. Use is of
the form:
Calculate lColList as SessObj.$selectnames(pRowRef,pTableName)
$wherenames()
To locate a row or rows in a table to be updated or deleted you can use the $wherenames()
method. $wherenames() returns a text string that is a comma delimited list of column names
and values. Use is of the form:
Calculate lColList as
SessObj.$wherenames(pRowRef,pTableName,pComparison,pOperator)
Parameter pRowRef is a row or list variable. If it is a list variable, the values from the
current line are used. The remaining parameters are optional, pTableName will prefix
column names with the specified table name, pComparison (default =) is used to specify
an alternative comparison operator (e.g. >, <, >= etc.), pOperator (default AND) is used
to specify an alternative logical operator (i.e. OR.)
This can be used in a SQL UPDATE or DELETE statement. For example, to delete a row in
the table publishers where the column values exactly match all columns in the row
variable iPublishersRow:
Do StatementObj.$execdirect(con('DELETE FROM publishers ',
SessObj.$wherenames(iPublishersRow))) Returns #F
SQL Errors
It is possible for an error to occur when a session or statement method is executed. The
error may originate from the session object or in the database. The session or statement
method will indicate that an error has occurred by returning the value kFalse. The value
196
The methods will also return a generic (i.e. database independent) code and message
describing the error in the properties $errorcode and $errortext. For example, in the event of
an error occurring, SessObj.$logon() would return an error code in the property
SessObj.$errorcode and an error message in SessObj.$errortext whilst
StatementObj.$execute() would return an error code in StatementObj.$errorcode and
message in StatementObj.$errortext. You can create a method to display the error code and
message. For example:
OK message SQL Error {Code = [StatementObj.$errorcode], Msg =
[StatementObj.$errortext]}
If smart lists are used, the history list row properties $errorcode and $errortext contain the
value of StatementObj.$errorcode and StatementObj.$errortext for each row updated.
Additionally, you can obtain the native error code and message from the server using the
session and statement properties $nativeerrorcode and $nativeerrortext. Some servers may
return more than one combination of native error code and message for a single error.
Currently only Sybase and Microsoft SQL Server behave in this way. When an error occurs
the $errorcode and $errortext will contain a generic error from the session object and the
$nativeerrorcode and $nativeerrortext will contain the first error reported by the server. If
there are further error messages, $nativeerrorpending (a Boolean property of the statement
object) will be set the kTrue. In order to access the next native error code and message, use
the $nextnativeerror() method that will set the $nativeerrorcode and $nativeerrortext
properties to the next error. You can repeatedly call the $nextnativeerror() method until all
errors have been processed ($nativeerrorpending=kFalse). For example
While StatementObj.$nativeerrorpending
Do StatementObj.$nextnativeerror()
OK message SQL Error {Code = [StatementObj.$nativeerrorcode], Msg
= [StatementObj.$nativeerrortext]}]}
End While
All server errors cause the statement method to return a value of kFalse. If you get an error
from a method it does not prevent execution of further methods. You should always test the
return value after execution of a session or statement method and take an appropriate action.
197
When used with a statement, the $clear() method will cancel any pending results or
operations on the statement object and set all properties to their default values (except for
$statementname, $usecursor.) The statement object is placed in the kStatementStateClear
state. If the statement is using a cursor, it will be closed.
When used with a session object the $clear() method will clear all statements controlled by
the session object instance. For example:
Do SessObj.$clear() Returns #F
All of the statement objects are placed in a kStatementStateClear state. Depending on the
session state this will clear all SQL text, close all cursors and destroy pending results of all
statement objects owned by the session.
198
The parameter pType is used to indicate what types of object are to be listed and may
contain kStatementServerTable to obtain details of all tables, kStatementServerView to
obtain details of all views, or kStatementServerAll (default) to obtain details of all tables
and all views. The parameter pOwner is used to list only objects belonging to a single
named owner and defaults to all owners. For example to create a list of all available tables
and views for all owners:
Do StatementObj.$tables() Returns #F
Do StatementObj.$fetch(iResultsList,9999) Returns lFetchStatus
Name
Description
Owner
TableOrViewName
TableType
Description
DamInfoRow
199
Listing Columns
The $columns() method generates a results set containing details of columns for a specified
table or view.
The only parameter required is the name of the database table or view for which column
details are required. For example to create a list of columns in the authors table:
Do StatementObj.$columns('authors') Returns #F
Do StatementObj.$fetch(iResultsList,9999) Returns lFetchStatus
Name
Description
DatabaseOrCatalog
Owner
ColumnName
Name of column
OmnisData typeText
OmnisData type
OmnisDataSubType
SQLData type
Length
Scale
10
Null
11
Index
12
PrimaryKey
13
Description
14
DamInfoRow
Listing Indexes
The $indexes() method generates a results set containing details of index columns for a
specified table. Use is of the form:
Do StatementObj.$indexes(pTableName,pType) Returns #F
The parameter pTableName is the table of which indexes are to be listed. The parameter
pType is used to indicate what types of indexes are to be listed and may contain
kStatementIndexUnique (default) to obtain details of unique indexes,
200
Name
Description
DatabaseOrCatalog
Owner
ColumnName
IndexName
Name of index
Unique
ColumnPosition
DamInfoRow
The parameter pSchema is a reference to an existing schema class that will be overwritten
with the definition from the server table pTableName.
For example, to create a schema called scAuthors from the server table authors:
Do $schemas.$add('scAuthors') Returns #F
Do SessObj.$makeschema($schemas.scAuthors,'authors') Returns #F
Using the $tables() and $makeschema() methods you can obtain a list of tables on the server
and build a schema class for each server table.
201
Remote Procedures
Omnis provides methods that enable you to list and execute remote procedures that exist in
the database. Support for these methods varies from one database to another, see the chapter
on Server-Specific Programming for more details.
The optional parameter pOwner is used to list only objects belonging to a single named
owner and defaults to all owners. For example to create a list of all available remote
procedures for all owners
Do StatementObj.$rpcprocedures() Returns #F
Do StatementObj.$fetch(iResultsList,9999) Returns lFetchStatus
Name
Description
DatabaseOrCatalog
Owner
ProcedureName
DamInfoRow
The parameter pProcedureName is the name of the remote procedure. This parameter may
take the form Database.Owner.Procedure name depending on whether database and owner
qualifiers are supported. The Database and Owner are optional. The use of the qualifier is as
follows.
202
Remote Procedures
Only Procedure name specified
Owner.Procedure name specified
Database.Owner.Procedure name
specified
For example, to create a list of all parameters for remote procedure byroyalty:
Do StatementObj.$rpcparameters('byroyalty') Returns #F
Do StatementObj.$fetch(iResultsList,9999) Returns lFetchStatus
Name
Description
OmnisData type
OmnisDataSubType
Length
PassType
C5
C6
DatabaseOrCatalog
Owner
ParameterName
10
OmnisData typeText
11
SQLData type
12
Scale
13
DamInfoRow
Note that columns 1, 2 and 3 are the closest Omnis type to the server type specified in the
server definition of the procedure parameter.
203
The parameter pProcedureName is the case-sensitive name of the remote procedure that
must exist on the server. If the procedure has previously been defined, the new definition
replaces the old one. The parameter pList defines the parameters and the return value of the
remote procedure. The list must have the same layout as that returned by
$rpcparameters(pProcedureName), except that only the first 4 columns are required. See the
section on Listing Remote Procedure Parameters ($rpcparameters) for details of the list
layout.
The easiest way to define a procedure is to first call $rpcparameters(), fetch the result set
into a list, and pass the list to $rpcdefine(). For example:
Do
Do
Do
Do
iResultsList.$define()
StatementObj.$rpcparameters('byroyalty') Returns #F
StatementObj.$fetch(iResultsList,9999) Returns lFetchStatus
SessObj.$rpcdefine('byroyalty',iResultsList) Returns #F
Once a remote procedure has been defined, it can be invoked using the statement method
$rpc().Use is of the form:
Do StatementObj.$rpc(pProcedureName,pParam1,pParamN) Returns #F
The call to $rpc() will fail if pProcedureName has not been defined using $rpcdefine() or
does not exist on the server. The session object will invoke the specified remote procedure,
using the procedure definition to determine the parameters it needs. If the optional
parameters pParam1pParamN are included, they are passed to the stored procedure.
If the call is successful, any output parameter values are returned. If the procedure has a
return value specified in its definition, it is written to the statement property
$rpcreturnvalue, if not, $rpcreturnvalue is Null. If the call to the procedure generates a
result set, the statement property $resultspending is set to kTrue and these results may be
retrieved using the $fetch() method. Following successful execution of the remote
procedure, the statement $state property will be set to kStatementStateExecDirect. If the
state prior to this call was not kStatementStateClear, any pending result set or unexecuted
SQL statement is cleared.
For example, to invoke the stored procedure byroyalty passing the variable lPercentage to
the 1st parameter and fetch the results set generated by the stored procedure:
Do StatementObj.$rpc('byroyalty',lPercentage) Returns #F
Do StatementObj.$fetch(iResultsList,9999) Returns lFetchStatus
204
Transactions
Transactions
The $transactionmode session property controls the way that transactions are managed.
Depending on the value of this property the session object may automatically manage
transactions or it may be necessary to manage transaction using explicit method calls or
SQL statements.
Some servers do not provide support for transactions. You can determine whether a
particular server allows transactions using the read-only Boolean session property
$allowstransactions which contains kTrue if the server supports transactions or kFalse
otherwise. Some session objects will contain a value of kUnknown in this property until the
session is logged on. If your server does not allow transactions, the properties and methods
described in the section on Transaction Modes below should not be used.
Transaction Modes
You can set the $transactionmode session property using a command of the form:
Do SessObj.$transactionmode.$assign(kSessionTranManual) Returns #F
Automatic Mode
After a SQL statement has successfully executed, i.e. $execute() or $execdirect() returns
kTrue, the current transaction is automatically committed by the session object. If the
command fails, the transaction is rolled back automatically. A new transaction is started
automatically if required after a successful commit or rollback.
Note that since each individual SQL command is committed immediately that it is executed,
automatic mode does not allow for the creation of transactions that contain a number of
SQL commands to be individually prepared and executed prior to a single commit. If this is
required, you should use Manual or Server mode.
Manual Mode
In kSessionTranManual mode you manage transactions manually using session methods.
205
The $begin() method should only be executed where the DBMS does not implicitly start a
transaction. The read-only session property $autobegintran will contain the value kTrue to
indicate for a particular session object that a transaction is automatically started when a
connection is established to the database or the previous transaction is committed or rolled
back, and in this case the $begin() method should not be used. This method may fail if there
is a current transaction or the server does not support nested transactions.
$commit()
Use the $commit()method to commit the current transaction, for example:
Do SessObj.$commit() Returns #F
The $commit() method will fail if the session $state property is kSessionLoggedOff, if the
transaction mode is not kSessionTranManual or if there is no current transaction. With
certain types of session objects this will commit and clear all statements, close any cursors
used by a statement and clear pending results. This will not destroy the statement objects
used by a session. Depending on the value of the session property $autobegintran, the server
may begin a new transaction automatically.
$rollback()
Use the $rollback()method to roll back the current transaction, for example:
Do SessObj.$rollback() Returns #F
The $rollback() method will fail if the $state property is kSessionLoggedOff, if the
transaction mode is not kSessionTranManual or if there is no current transaction. This
method cancels the current transaction. With certain types of session objects this will
rollback and clear all statements, close any cursors used by a statement and clear pending
results. This will not destroy the statement objects used by a session. Depending on the
value of the session property $autobegintran, the server may begin a new transaction
automatically.
The read-only session properties $commitmode and $rollbackmode describe the effect that
the $commit() and $rollback() methods have on statements and their cursors.
206
Transactions
kSessionCommitDelete
kSessionRollbackDelete
kSessionCommitClose
kSessionRollbackClose
kSessionCommitPreserve
kSessionRollbackPreserve
Note that with some session objects these properties may change once a session is logged
on.
Server Mode
Transaction management is provided by the DBMS. The default behavior is determined by
the database, which may for example automatically commit each SQL statement unless you
override the default.
You may also execute SQL BEGIN, COMMIT and ROLLBACK or other statements
depending on the DBMS SQL dialect, to manage transactions manually.
The read-only session property $autobegintran will contain the value kTrue to indicate for a
particular session object that a transaction is automatically started when a connection is
established to the database, or after a SQL COMMIT or ROLLBACK statement. If
$autobegintran is kFalse, an explicit SQL BEGIN statement is required. SQL based
transaction commands should not be used other than in kSessionTranServer mode.
As a general rule it is recommended that either automatic or manual mode should be used in
preference to server mode.
In kSessionTranManual or kSessionTranServer mode the behavior of the DBMS dictates
whether closing a connection commits the current transaction.
The effect of a commit or rollback on existing statement cursors is dependant on the
behavior of the DBMS. In most cases, a commit or rollback will close all cursors in the
session and clear all results sets. This does not destroy the statement object. It may be
possible to re-execute the statement but generally the statement will need to be prepared
again.
Care should be taken to note the circumstances in which commits occur as this can have a
side effect on the processing of other statement objects associated with the session.
207
It is important that $sqltext specifies a SQL SELECT statement. Note that the syntax of the
DECLARE and associated SELECT command may vary slightly if a particular server does
not adhere to the SQL-92 standard.
A subsequent $execute() and $fetch() will issue an
OPEN CURSOR <$name> and FETCH CURSOR <$name>.
Depending on the value of $commitmode and $rollbackmode, any pending results set may
be destroyed when a transaction is committed or rolled back.
To ensure that the results sets are not destroyed by an update command you need to set the
transaction mode to kSessionTranManual and commit updates manually when ready using
the $commit method.
208
Non-Unicode Compatibility
The DAMs provided with Studio 5.0 are able to function in Unicode or 8-bit compatibility
mode. This means that after converting your existing libraries for use with Studio 5.0, it
should be possible to continue interacting with non-Unicode databases.
In 8-bit compatibility mode, all DAMs
Return non-Unicode character data types via the $createnames() and $coltext
attributes
Bind outgoing character variables using the databases non-Unicode data types
Convert all data inside outgoing character bind variables to single-byte characters
Define incoming character columns using the databases non-Unicode data types
Convert all data inside incoming character bind variables from bytes into the
Omnis character set
Character Mapping
This section is applicable to session objects operating in 8-bit compatibility mode only.
When reading data from a server database, Omnis expects the character set to be the same
as that used in an Omnis data file. The Omnis character set is based on the MacOS extended
character set, but is standard ASCII up to character code 127. Beyond this value, the data
could be in any number of different formats depending on the client software that was used
to enter the data.
When assigned, the $maptable session property identifies files containing translation tables
for character codes read into and sent out of Omnis. For example, suppose you are working
with a database that stores EBCDIC characters. In order to accommodate this database, you
209
In this example, the two map files are called pubs.in and pubs.out.
The session property $charmap controls the mode of character mapping that is to be applied
to the data. Set the character mapping mode using a command of the form:
Do SessObj.$charmap.$assign(pCharMap) Returns #F
210
211
Stripping Spaces
The ODBC DAM provides $nationaltowchar which performs a similar function. These
properties are documented further in the Server Specific Programming chapter.
The onus is upon the developer not to put Unicode characters into Character subtypes when
using these properties, otherwise data insertion/encoding mismatch errors will occur.
Stripping Spaces
The session object can automatically strip trailing spaces from data returned from the
server. This functionality is switched on by setting the statement $sqlstripspaces property to
kTrue. The default value for a statement is taken from the session object $sqlstripspaces and
the default for the session is read from $clib.$prefs.$sqlstripspaces.
Some data sources may strip trailing spaces prior to sending it to the session object in which
case this property has no effect.
213
Use value
$defaultdate
$emptydateisnull
#NULL
or
<empty>
Ignored
Ignored
Ignored
kTrue
<empty>
<empty>
kFalse
Datetime
value
Default
datetime
kTrue
Datetime
value
Default
datetime
kFalse
Large Objects
When working with large objects (LOBs) there are some properties that may be used to tune
the system so that data is handled and transferred in an efficient way. Large objects include
large text, list, binary, picture data and instances of object classes.
Blob Size
The session property $blobsize defines the maximum size of a binary data item. The default
value for this property is 10MB, but it may be adjusted to conserve memory. Some session
objects may take this value into account when executing a $createnames() method and
resulting data types may vary according to the value of $blobsize.
214
Session Pools
in bytes and the size of object in bytes at which chunking starts. The default value of both of
these properties is 32KB.
This only applies to Omnis Character, Picture, Binary, List and Object data types that are
greater than 255 bytes.
The value of $lobthreshold may be set to any value between 256 bytes and 2GB. Note that
if not set judiciously, this may cause resource problems due to the amount of memory
required to cache an object.
The value of $lobchunksize may be set to any value between 256 and the $lobthreshold.
Due to limitations in the database vendor client API, certain session objects may impose
their own values for the default and maximum chunk sizes.
Session Pools
Pools of session instances can be created when Omnis starts up and made available to any
methods running within Omnis. They are designed to be used by the multi-threaded server
and allow client methods to quickly obtain SQL sessions without the burden of constructing
their own instances.
There is a notation group $root.$sessionpools that contains the current session pools.
Normally the session pools are created by the startup task and exist until Omnis is shut
down. Pooled sessions do not appear in the SQL Browser.
When a session is required in order to perform a SQL query, it is obtained from the pool
using an object variable and a statement object created in the normal way in order to
execute the query and fetch any results. When the session object variable is destroyed the
session instance is returned to the pool for later reuse.
The call to $makepool() will only be successful if used with an external object that is a
session object or an object class that has a session object as its subtype, that is, the external
server object is its superclass. The $makepool() method returns a reference to the pool if it
is successfully created and the required number of session instances are constructed,
otherwise it returns NULL. Once a session pool has been created there is no need to
maintain it further during the time that the library is open, however it is possible to change
the number of available instances using notation.
215
DAMobject is the name of the external component. You can find out what DAM objects are
available on your workstation by examining the $root.$extobjects branch of the notation
tree using the Notation Inspector. SessObject is the name of the session object. You can find
out what session object is available by expanding the $objects group for a particular DAM
object using the Notation Inspector. The pPoolName parameter is the name of the pool and
must be unique amongst session pools and the pCount parameter is the number of object
instances to be initially contained in the pool. The other parameters are optional and if
specified are passed to the $logon() method for the instance. If they are not specified, the
instance is constructed but not logged on.
For example, to create a session pool called poolone containing 5 sessions all logged on
to SQL Server
Calculate lHostName as 'SqlServer'
Calculate lUserName as ''
Calculate lPassword as ''
Do $extobjects.ODBCDAM.$objects.ODBCSESS.$makepool('poolone',5,
lHostName,lUserName,lPassword) Returns lPoolRef
ObjectClass is the name of an object class that must have a session object as its superclass.
You can achieve this by selecting the object class in the browser and clicking on the
$superclass in the Property Manager, click the arrow and select External Objects and
double-click on the required session object.
For example:
Do $objects.odbcobj.$makepool('pooltwo',10,lHostName,lUserName,
lPassword) Returns lPoolRef
216
Session Pools
called for each session added to the pool. The Object Reference Parameter will contain a
reference to the newly created session which can be used to initialize the session object.
If $new() is successful the session instance assigned from the pool belongs to SessObj and
is normally returned to the pool when SessObj is destroyed (for example, if SessObj is a
local variable the session is returned to the pool when the method containing SessObj
terminates). Alternatively the session can be manually returned to the pool by assigning
some other object or zero to SessObj. The $new method returns NULL if all instances
contained in the pool have already been assigned out.
Now you can use the $newstatement() method with the session object to create a statement
to execute SQL in the normal way.
217
Diagnosing Problems
As of Omnis Studio 5.0, the session object provides the $debugfile and $debuglevel
properties. These are useful in the event of program faults, if you are looking to optimise
network traffic or if you are simply curious about how the DAM is executing commands. It
should be noted that when debugging is enabled, there is a noticeable impact on
performance. Hence, debugging should be reserved for application development and
technical support issues- in which case use of $debuglevel 4 is recommended.
When $debugfile is set to a valid filename, the DAM starts writing debug information to
this file- which is cleared before use. The file is created if it does not already exist.
Debugging continues either until the session object is destructed or until $debugfile is set to
an empty string. For Mac and Linux, a POSIX style path is expected and the user must have
permission to write to the file at the specified location.
It is also possible to assign the value stderr to $debugfile. This is useful for Mac and
Linux platforms where Omnis is run from the command prompt. Debug information will be
written to the terminal window.
The $debuglevel property determines the level of debugging information that is written to
the debug file and supports the following values:
218
Base level debugging. At this level, the DAM base class writes high level
descriptions about the operation of the DAM; statement prepares, executes,
describing of result sets, fetching, etc. This is the default level of debugging.
Session Methods
Method
Description
$begin()
$clear()
$coltext
$commit()
$createnames()
$createnames(vTableDef,[bNullInfo,bPrimaryKeyInfo]) returns
a DBMS specific text string consisting of the SQL column names
and types based on the column types of the supplied list or row
variable. The optional parameters bNullInfo and
bPrimaryKeyInfo can be used to request additional information
about columns where the list has been defined from a schema or
file class.
$insertnames()
$logoff()
$logon()
$logon(cHostname,cUsername,cPassword[,cSessionName])
connects the session to the DBMS using the supplied parameters,
The optional cSessionName parameter registers the session with
$root.$sessions and the SQL Browser utility.
$makeschema()
$newstatement()
$newstatementref()
$nextnativeerror()
219
Description
error message, placing them in $nativeerrorcode and
$nativeerrortext.
220
$rollback()
$rpcdefine()
$selectnames()
$updatenames()
$wherenames()
$wherenames(wRowRef[,cTableName,cComparison,cOperator])
returns the text string for a SQL WHERE clause based on the
supplied list or row variable. The optional cTableName is prepended to the column names if supplied. The cComparison and
cOperator parameters can be used to modify the corresponding
parts of the WHERE clause.
Session Properties
Property
Description
$allowstransactions
$apiversion
Version of the database client API that the DAM was built with.
(Read-only)
$autobegintran
$blobsize
$charmap
$commitmode
$damname
$debugfile
$debuglevel
$defaultdate
$emptydateisnull
$encoding
$codepage
221
Description
property determines the ANSI code page used to interpret nonUnicode data. $codepage should match the character set of the
database so that non-Unicode extended characters are read and
written correctly.
222
$errorcode
$errortext
$fetch64bitints
$hostname
$lobchunksize
The size (in bytes) of a single chunk when inserting large binary
data. Default value is 32KB
$lobthreshold
$maptable
$nativeerrorcode
$nativeerrorpending
kTrue indicates that a further native error code and error text are
available. See session.$nextnativeerror().(Read-only)
$nativeerrortext
$password
$quotedidentifier
$rollbackmode
Indicates how SQL cursors behave when a session is rolledback. Either kSessionRollbackClose, kSessionRollbackDelete or
kSessionRollbackPreserve. (Read-only)
$sqldecimalseperator
Description
separator when storing numeric values, usually .
$sqlstripspaces
$sqlthousandsseperator
$state
$transactionmode
$unicode
$username
$validateutf8
$version
223
Statement Methods
224
Method
Description
$clear()
$columns()
$execdirect()
$execute()
$fetch()
$fetchinto()
$fetchtofile()
$fetchtofile(cFileName[,iRowCount,bAppend,bColumnNames])
fetches the specified number of rows from the result set and stores
them in the specified file. iRowCount, bAppend and
bColumnNames parameters are optional.
$indexes()
$nextnativeerror()
$prepare()
$results()
$rpc()
$rpcparameters()
Description
$rpcprocedures()
$tables()
Statement Properties
Property
Description
$batchsize
$effectivebatchsize
$columncount
$columndelimiter
$errorcode
$errortext
$maxbuffersize
$nativeerrorcode
$nativeerrorpending
225
226
Property
Description
$nativeerrortext
$resultspending
$rowcount
$rowdelimiter
$rowsaffected
$rowsfetched
$rpcreturnvalue
$state
$statementname
$sqlstripspaces
$sqltext
$usecursor
Overview
The SQL Worker Objects support three primary methods:
$init()
Initializes or resets a worker object ready to perform its task
$start()
Starts the worker task on a background thread (non-blocking)
$cancel()
Aborts a worker task running on a background thread
There are additional properties to allow a running task to be discarded in place of a new
task and to cancel such tasks as they become orphaned. There is also a property to report
the state of a worker object's running background thread.
Worker objects are created by sub-classing an Omnis Object class with the appropriate SQL
Worker Object type. You initialize the object by supplying a SQL statement along with any
bind variables that the SQL statement may need. Logon details or optionally the name of a
session pool are also passed during initialization.
A SQL Worker thread is dispatched by calling $start(). Upon completion, the worker thread
calls back into the worker object's $completed() method, or $cancelled(), with the result set
or error information.
227
Description
$init()
$start()
$run()
Starts the worker task running on the caller thread (blocks until
complete). Intended for testing purposes.*
$cancel()
$sessionref()
$completed()
$cancelled()
228
Property
Description
$cancelifrunning
$waitforcomplete
$state
$errorcode
$errortext
$threadcount
To access worker functionality from your code, you then create one or more object instance
variables of subtype <your-object >.
229
Attribute value
session
poolname
The name of an existing session pool. The worker will take a session
object from this pool, returning it upon completion.
hostname
database
username
password
query
bindvars
If the session attribute is supplied, the other logon attributes, i.e. hostname, database,
username & password are ignored, since it is assumed that the session object is already in a
useable state. Please Note: In this mode, the session should be considered reserved for use
exclusively by the worker. If the main application attempts to share a session object being
used by a worker running on another thread, the results are undefined.
The logon parameters are also ignored if the poolname attribute is supplied. In this mode,
the worker attempts to obtain a session from the named session pool, releasing it when the
worker task completes. (If both session and poolname are supplied, poolname is ignored.)
Where neither, session or poolname are supplied, an internal session object is created
dynamically. Valid logon credentials should be supplied via hostname, username and
password. Although read during the call to $init(), the worker will not attempt to logon until
the $run() or $start() method is called. In this mode, the session is automatically logged-off
when the worker task completes (or is cancelled). Should you need to modify one or more
session attributes before calling $run() or $start(), it is possible to obtain a reference to the
session object by calling the worker objects $sessionref() method, for example:
Do iWorkerObj.$sessionref(lObjRef) Returns #F
Do lObjRef.$port.$assign(5435)
The SQL text supplied via the query attribute may contain any SQL statement but ideally,
should be a statement that normally takes an appreciable amount of time to execute, for
example; a SELECT, UPDATE or DELETE statement. The query text may also contain one
or more bind variables, specified using standard @[] notation.
Bind variable values are supplied via a separate bindvars parameter. The supplied list is
stored during $init() and read when the worker task starts. Where the list contains multiple
rows, the worker re-executes the supplied SQL statement for each row of bind variables.
230
The $run() method is analogous to $start() but provided for debugging and testing purposes
only. In this mode, the benefit of the worker object is negated owing to the fact that the
worker will run on the same thread as the caller, thus blocking the caller thread until the
worker task is complete.
Once initialized, a worker object may be run repeatedly if desired provided that the supplied
session object remains useable, the session pool has one or more free sessions or that the
logon credentials remain valid. Any bind variables supplied will be re-used each time the
worker is run.
If an error occurs during $init(), $start() or $run(), an error message is returned via the
objects $errorcode and $errortext properties.
231
Worker State
The current state of a SQL Worker object may be interrogated by inspecting the objects
$state property. This will return either:
kWorkerStateCancelled The worker has been cancelled.
kWorkerStateClear The worker has been initialized.
kWorkerStateComplete The worker has completed.
kWorkerStateError An error occurred (see $errortext).
kWorkerStateRunning The worker is currently running.
For example:
If iWorkerObj.$state=kWorkerStateRunning & iWorkerObj
.$waitforcomplete=kTrue
Calculate iMesg as 'Still running (waiting for completion)'
Quit method
End If
Behind each Worker Object, there are hidden Worker Delegate and Thread Timer objects.
A detached Worker Delegate. The Interface Object may have gone out-of-scope or may now point to a
new delegate.
Upon destruction of an Interface Object, the object transfers ownership of the worker
delegate to the Thread Timer object. One Thread Timer object monitors all Worker objects
of a given type and deletes any orphaned worker processes it owns upon completion.
233
A single Thread Timer object monitors all Worker Delegates of a given type. An Interface Object can
initiate and receive results from a single Worker Delegate but there can be multiple Interface Objects.
234
235
Schema Classes
A schema class maps the structure or data dictionary of a server table or view within your
library. A schema class contains the name of the server table or view, a list of column names
and data types, and some additional information about each column. The data types are the
equivalent Omnis data types, and the names must conform to the conventions used by the
particular server. Schema classes do not contain methods, and you cannot create instances
of a schema class. You can define a list based on a schema class using the Define list from
SQL class command or the $definefromsqlclass() method. You can create a schema class
using the New Class>>Schema option in the Studio Browser.
Schema Classes
$servertablename
the name of the server table or view to which the schema corresponds
The $objs group containing the columns in the schema class supports the group methods
including $first(), $add(), $addafter(), $addbefore(), and $remove(). The $add... methods
require the following parameters
Name
the name of the column
Type
constant representing the Omnis data type of the column
Subtype
constant representing the data subtype of the column
Description (optional)
a text string describing the column
Primary-key (optional)
a boolean set to kTrue if this column is a primary key. If omitted it defaults to kFalse
Maximum-Length (optional)
for character and national columns, the maximum length; for other types, Omnis
ignores the value of this parameter. If omitted for character and national columns, it
defaults to 10000000.
No-nulls (optional)
a boolean set to kTrue if this column cannot have NULL values. If omitted it defaults to
kFalse
You can identify a particular column in the $objs group using its column name, order, or
ident, a unique number within the scope of the schema class assigned to the column when
you add it. A schema column has the following properties (all are assignable except $ident)
$name
the name of the column
$coltype
the Omnis data type of the column
$colsubtype
the Omnis subtype for the data type of the column
$colsublen
the maximum length for Character and National columns
$desc
a text string describing the column
$primarykey
if kTrue the column is a primary key
237
List/Row subtypes
A schema class (or a query or table class) can be used as the subtype of a list or row
variable, that is, a class, instance, local, task or parameter variable, or a column in a list or
row defined from a SQL class.
Schema classes have a property $createinstancewhensubtype that controls whether or not
there is a table instance associated with a List or Row variable with a schema class as its
subtype. You can set this property in the Property Manager when editing the schema class:
it defaults to kTrue for existing and newly created schema classes.
will create the schema MySchema, referencing server table ServerTable, using the current
Omnis session.
Query Classes
Query classes let you combine one or more schema classes or individual columns from one
or more schemas, to give you an application view of your server database. A query class
contains references to schema classes or individual schema columns. Like schema classes,
query classes do not contain methods, and you cannot create instances of a query class. You
can define a list based on a query class using the Define list from SQL class command or the
$definefromsqlclass() method.
You can create a query class using the New Class>>Query option in the Studio Browser.
The Catalog pops up when you open the query class editor, which lets you double-click on
schema class or column names to enter them into the query editor. Alternatively, you can
drag schema class or column names into the query editor. Furthermore, you can reorder
columns by dragging and dropping in the fixed left column of the query editor, and you can
drag columns from one query class onto another. You can also drag a column from the
schema editor to the query editor.
238
Query Classes
You can drag from the query list, the schema editor, and the Catalog, and drop onto the
extra query text field labeled Text appended to queries. Dragging a query column from the
right-hand list of the catalog query tab inserts a bind variable reference in the form
@[$cinst.name].
The column entries have a context menu, which allows you to delete a column, and to open
the schema editor for the schema containing the column.
The additional query text edit field has a context menu which allows you to insert text
commonly used in SQL queries.
The query class editor does not validate schema class or column names, nor does Omnis
automatically update query classes when you edit a schema class. You need to update your
SQL classes manually using the Find and Replace tool.
The alias allows you to eliminate duplicate column names when defining a list from the
query class. By default, each list column name is the same as the schema column name. You
can override this with the alias. If the column name is empty, meaning use all columns in the
schema, Omnis inserts the alias at the start of each column name in the schema, to create the
list column name; otherwise, Omnis uses a non-empty alias as the list column name.
Calculated Columns
Query classes can also contain calculated columns. A calculated column is an entry in a
query class which has:
A schema name, which determines the table to be used in the SQL statement.
A column name. This is the calculation. Omnis treats a column name as a calculation if
it contains at least one open parenthesis and one close parenthesis. This rule helps to
distinguish a calculated column from a badly named schema column. Omnis performs
no validation on the calculation, and it simply inserts it into queries generated by
$select or $selectdistinct, and into the result of $selectnames.
An alias, used as the list column name.
A calculated column is represented, in the list or row variable defined from a SQL class, as
a character column of maximum length. If you include strings in the form <schema
name>. or <library>.<schema name>. in the calculation, then Omnis replaces them with
<server table name>. when it adds the calculation to a query. The <server table name>
comes from the schema class.
240
Use the SQL Browser to open the SQL session for your database
Drag the schema or query class from your library and drop it on to your Session
If you drag a schema class onto an open session, Omnis creates a SQL table with the table
name defined in your schema class. If you drag a query class, Omnis creates a SQL view
with the name of the query class.
241
Table Classes
An instance of a table class provides the interface to the data modeled by a schema or query
class. You only need to create a table class if you wish to override some of the default
processing provided by the built-in table instance methods.
You can create a table class using the New Class>>Table option in the Studio Browser. You
can edit the methods for a table class or add your own custom methods in the method editor.
Table Instances
You create a table instance in Omnis when you define a list or row variable from a schema,
query, or table class, using the Define list from SQL class command, or the
$definefromsqlclass() method. Table instances created from schema or query classes have
all the default methods of a table instance. Table instances created from a table class have
all the default methods of the table class in addition to any custom methods you have added,
perhaps to override the default methods.
When you use Define list from SQL class or $definefromsqlclass(), Omnis defines your list
to have either one column for each column in the schema class, or one column for each
column referenced by the query class (which can contain a subset of columns from a schema
class). In the case where you use a table class, Omnis uses the $sqlclassname property of the
table class to determine the schema or query from which to define the list. You can pass the
query/schema/table class as either an item reference to the class, or as the name of the class,
in the form [library.]class, where the library defaults to the current library if omitted.
A list variable defined in this way has all of the methods and properties of a normal list
variable, together with all of the methods and properties of the table instance. You never
access the table instance directly; you can think of it as being contained in the list variable.
242
Table Instances
For example, if you want to display a grid containing your data in a SQL form you can use
the following code in the $construct() method of the form to create a list based on a schema
class
; Declare instance variable iv_SQLData of type List
Set current session {session-name}
Do iv_SQLData.$definefromsqlclass('SCHEMACLASSNAME')
Do iv_SQLData.$select()
Do iv_SQLData.$fetch(1000) ;; Fetch up to 1000 rows
Once you have defined and built your list you can use the table instance methods to
manipulate the data. Equally you could declare a row variable, define it from a table,
schema or query class, and manipulate your data on a row-by-row basis using many of the
same methods.
The Define list from SQL class command and $definefromsqlclass() method both reset the
$linemax property of the list to its largest possible value.
If you pass a schema class, or a table class that references a schema class, then the list is
defined to have all columns in the schema, unless you pass an explicit list of columns to use
from the schema, such as:
Do iv_SQLData.$definefromsqlclass(query / schema / table class
[,cCol1,cCol2,...])
Note that there is an empty parameter to separate the explicit column list from the consparams that are passed to $construct for the table instance. Note also that this empty
parameter is still required when using a query class or table class that references a query
class.
243
244
Table Instances
When you call $doinserts(), $dodeletes(), $doupdates() or $dowork(), the table instance
calls the appropriate method(s) from the following list, to invoke each individual insert,
delete or update. This allows you to use table class methods to override the default
processing. As a consequence these methods only apply to smart lists.
$doinsert()
inserts a single row with row status kRowInserted
$dodelete()
deletes a single row with row status kRowDeleted
$doupdate()
updates a single row with row status kRowUpdated
The following methods apply to smart lists only, reverting the state of the list, that is, they
do not affect the server database.
$undoinserts()
removes any inserted rows from the list
$undodeletes()
restores any deleted rows to the list, and resets their status to kRowUnchanged
$undoupdates()
restores any updated rows to their original value, and resets their status to
kRowUnchanged
$undowork()
executes the three $undo... methods above, one after the other, in the order insert,
update, delete
You can use the following methods to create text strings suitable for using in SQL
statements. You are most likely to use these if you override default table instance methods
using a table class.
$selectnames()
returns a comma-separated list of column names in the list or row variable, suitable for
inclusion in a SELECT statement
$createname()
returns a comma-separated list of column names, data types, and the NULL or NOT
NULL status, for each column in the list or row variable, suitable for inclusion in a
CREATE TABLE statement
$updatenames()
returns a text string containing a SET clause, suitable for inclusion in an UPDATE
statement
$insertnames()
returns a text string containing a list of columns and values for a row variable, suitable
for inclusion in an INSERT statement
245
246
Table Instances
$rowsfetched
the number of rows fetched so far, using the $fetch() method, in the current result set
for the session used by the table instance
$allrowsfetched
set to kTrue when all rows in the current result set for the current table instance have
been fetched, otherwise kFalse at other times
List columns in a list containing a table instance have three table instance related properties:
$excludefromupdate, $excludefrominsert and $excludefromwhere.
When $excludefromupdate is true, the column is omitted from the result of $updatenames,
and from the list of columns in the SQL statements generated by $update.
When $excludefrominsert is true, the column is omitted from the result of $insertnames, and
from the list of columns in the SQL statements generated by $insert.
Note that $excludefromupdate does not cause the column to be omitted from the where
clause generated by $update and $updatenames, therefore allowing you to have a column
which is purely a key and not updated. If you do want to exclude a column from the where
clause, set $excludefromwhere to true. $excludefromwhere affects the where clause
generated by $update, $updatenames, $delete and $wherenames.
For example:
Do MyList.$cols.MyKey.$excludefromupdate.$assign(kTrue)
The default setting of these properties is kFalse, except for calculated columns, in which
case the default is kTrue. However, note that calculated columns are omitted from the where
clause, irrespective of the setting of $excludefromwhere.
If you define a list from a SQL class and use $add to add additional columns, you cannot set
these properties for the additional columns.
$select()
Do MyList.$select([parameter-list]) Returns STATUS
$select() generates a Select statement and issues it to the server. You can optionally pass
any number of parameters which Omnis concatenates into one text string. For example,
parameter-list could be a Where or Order By clause. The method returns kTrue if the table
instance successfully issued the Select.
The $select() method executes the SQL statement equivalent to
Select [$cinst.$selectnames()] from [$cinst.$servertablenames]
[$extraquerytext] [parameter-list]
247
$selectdistinct()
Do MyList.$selectdistinct([parameter-list]) Returns STATUS
$fetch()
Do MyList.$fetch(n[,append]) Returns STATUS
$fetch() fetches up to n rows of data from the server into the list, or for row variables
fetches the next row. If there are more rows available, a subsequent call to fetch will bring
them back, and so on. The $fetch() method returns a constant as follows
kFetchOk
kFetchFinished
kFetchError
When fetching into a list, if the Boolean append parameter is kTrue, Omnis appends the
fetched rows to those already in the list; otherwise, if append is kFalse, Omnis clears the list
before fetching the rows. If you omit the append parameter, it defaults to kFalse.
The following method implements a Next button on a SQL form using the $fetch() method
to fetch the next row of data. The form contains the instance variables iv_SQLData and
iv_OldRow both with type Row.
; declare local variable lv_Status of Long integer type
On evClick
Do iv_SQLData.$fetch() Returns lv_Status
If lv_Status=kFetchFinished|lv_Status=kFetchError
Do iv_SQLData.$select()
Do iv_SQLData.$fetch() Returns lv_Status
End If
Calculate iv_OldRow as iv_SQLData
Do $cwind.$redraw()
248
Table Instances
$insert()
Do MyRow.$insert() Returns STATUS
$insert() inserts the current data held in a row variable into the server database. It returns
kTrue if the table instance successfully issued the Insert. The $insert() method executes the
SQL statement equivalent to
Insert into [$cinst.$servertablenames] [$cinst.$insertnames()]
The following method implements an Insert button on a SQL form using the $insert()
method to insert the current value of the row variable. The form contains the instance
variable iv_SQLData with type Row.
On evClick
Do iv_SQLData.$insert()
$update()
Do MyRow.$update(old_row[,disable_where]) Returns STATUS
$update() updates a row in a server table from the current data held in a row variable. It
returns kTrue if the table instance successfully issued the Update. Note that if the SQL
statement identifies more than one row, each row is updated.
The old_row parameter is a row variable containing the previous value of the row, prior to
the update.
The optional disable_where parameter is a boolean which defaults to kFalse when omitted.
If you pass kTrue, then Omnis excludes the where clause from the automatically generated
SQL. This may be useful if you want to pass your own where clause using $extraquerytext.
The $update() method executes the SQL statement equivalent to
Update [$cinst.$servertablenames][$cinst.$updatenames(old_row)]
[$extraquerytext]
The following method implements an Update button on a SQL form using the $update()
method. The form contains the instance variables iv_SQLData and iv_OldRow both with
type Row.
On evClick
Do iv_SQLData.$update(iv_OldRow)
$delete()
Do MyRow.$delete([disable_where]) Returns STATUS
$delete() deletes a row from a server table, matching that held in the row variable. It returns
kTrue if the table instance successfully issued the Delete. Note that if the SQL statement
identifies more than one row, each row is deleted. The optional disable_where parameter is
a boolean which defaults to kFalse when omitted. If you pass kTrue, then Omnis excludes
the where clause from the automatically generated SQL. This may be useful if you want to
pass your own where clause using $extraquerytext.
249
$doinserts()
Do MyList.$doinserts()Returns MyFlag
This method only works for smart lists. $doinserts() inserts rows with status kRowInserted
in the history list, into the server table, and returns kTrue if the table instance successfully
issued the Inserts. $doinserts() calls $doinsert() once for each row to be inserted.
$doinserts() then accepts the changes to the smart list, unless an error occurred when doing
one of the Inserts.
$dodeletes()
Do MyList.$dodeletes([disable_where])Returns MyFlag
This method only works for smart lists. $dodeletes() deletes rows with status kRowDeleted
in the history list, from the server table, and returns kTrue if the table instance successfully
issued the Deletes. $dodeletes() calls $dodelete() once for each row to be deleted.
$dodeletes() then accepts the changes to the smart list, unless an error occurred when doing
one of the Deletes. The optional disable_where parameter is a boolean which defaults to
kFalse when omitted. If you pass kTrue, then Omnis excludes the where clause from the
automatically generated SQL. This may be useful if you want to pass your own where
clause using $extraquerytext.
$doupdates()
Do MyList.$doupdates([disable_where]) Returns MyFlag
This method only works for smart lists. $doupdates() updates rows with status
kRowUpdated in the history list, in the server table, and returns kTrue if the table instance
successfully issued the Updates. $doupdates() calls $doupdate() once for each row to be
updated. $doupdates() then accepts the changes to the smart list, unless an error occurred
when doing one of the Updates. The optional disable_where parameter is a boolean which
defaults to kFalse when omitted. If you pass kTrue, then Omnis excludes the where clause
from the automatically generated SQL. This may be useful if you want to pass your own
where clause using $extraquerytext.
250
Table Instances
$dowork()
Do MyList.$dowork([disable_where]) Returns MyFlag
This method only works for smart lists. $dowork() is a shorthand way to execute
$doupdates(), $dodeletes() and $doinserts(), and returns kTrue if the table instance
successfully completed the three operations. The optional disable_where parameter is a
boolean which defaults to kFalse when omitted. If you pass kTrue, then Omnis excludes the
where clause from the automatically generated SQL for $dodeletes() and $doupdates(). This
may be useful if you want to pass your own where clause using $extraquerytext.
$doinsert()
$doinsert(row)
$doinsert inserts the row into the server database. The default processing is equivalent to
row.$insert()
$dodelete()
$dodelete(row)
$dodelete deletes the row from the server database. The default processing is equivalent to
row.$delete()
$doupdate()
$doupdate(row,old_row)
$doupdate updates the row in the server database, using the old_row to locate the row. The
default processing is equivalent to
row.$update(old_row)
$undoinserts()
Do MyList.$undoinserts() Returns MyFlag
This method only works for smart lists. $undoinserts() undoes the Inserts to the list and
returns kTrue if successful. It is equivalent to the smart list method $revertlistinserts().
$undodeletes()
Do MyList.$undodeletes() Returns MyFlag
This method only works for smart lists. $ undodeletes() undoes the Deletes from the list and
returns kTrue if successful. It is equivalent to the smart list method $revertlistdeletes().
$undoupdates()
Do MyList.$undoupdates() Returns MyFlag
This method only works for smart lists. $undoupdates() undoes the Updates to the list and
returns kTrue if successful. It is equivalent to the smart list method $revertlistupdates().
251
$undowork()
Do MyList.$undowork() Returns MyFlag
This method only works for smart lists. $undowork() undoes the changes to the list and
returns kTrue if successful. It is equivalent to the smart list method $revertlistwork().
$sqlerror()
Do MyList.$sqlerror(ERROR_TYPE, ERROR_CODE, ERROR_TEXT)
Omnis calls $sqlerror() when an error occurs while a default table instance method is
executing SQL. The default $sqlerror() method performs no processing, but you can
override it to provide your own SQL error handling. It passes the parameters:
ERROR_TYPE
ERROR_CODE
ERROR_TEXT
$selectnames()
Do MyList.$selectnames() Returns SELECTTEXT
Returns a text string containing a comma-separated list of column names in the list variable
in the format:
TABLE.col1,TABLE.col2,TABLE.col3,...,TABLE.colN
The returned column names are the server column names of the list columns in the order
that they appear in the list, suitable for inclusion in a SELECT statement; also works for
row variables. Each column name is qualified with the name of the server table.
$createnames()
Do MyList.$createnames() Returns CREATETEXT
Returns a text string containing a comma-separated list of server column names and data
types for each column in the list variable, suitable for inclusion in a CREATE TABLE
statement; also works for row variables. The returned string is in the format:
col1 COLTYPE NULL/NOT NULL,col2 COLTYPE NULL/NOT NULL,
col3 COLTYPE NULL/NOT NULL,...,colN COLTYPE NULL/NOT NULL
The NULL or NOT NULL status of each column is derived from the $nonull property in the
underlying schema class defining the column.
252
Table Instances
$updatenames()
Do MyRow.$updatenames() Returns UPDATETEXT
where col1coln are the server column names of the columns in the row variable. Each
column name is qualified with the name of the server table.
Do MyRow.$updatenames([old_name]) Returns UPDATETEXT
The optional parameter old_name is the name of a row variable to be used to generate a
where clause. If you include old_name, a where clause is concatenated to the returned
string in the following format:
WHERE col1=@[old_name.col1] AND ... AND colN=@[old_name.colN]
where row_name is the name of row variable which Omnis uses in the bind variables. This
may be useful if you override $doupdate() for a smart list.
$insertnames()
Do MyRow.$insertnames() Returns INSERTTEXT
where col1...colN are the server column names of the columns in the row variable. The
initial column names in parentheses are qualified with the server table name. You can
replace $cinst in the returned string using:
Do MyRow.$insertnames([row_name]) Returns INSERTTEXT
where row_name is the name of row variable which Omnis uses in the bind variables. This
may be useful if you override $doinsert() for a smart list.
253
$wherenames()
Do MyRow.$wherenames() Returns WHERETEXT
where col1...colN are the server column names of the columns in the row variable. Each
column name is qualified with the server table name.
The columns in the where clause depend on the setting of $useprimarykeys. If True, then
the columns in the where clause are those columns marked as primary keys in their schema
class. Otherwise, the columns in the where clause are all non-calculated columns except
those with data type picture, list, row, binary or object.
The = operator in the returned string is the default, but you can replace it with other
comparisons, such as < or >=, by passing them in the operator parameter.
Do MyRow.$wherenames([operator]) Returns WHERETEXT
where row_name is the name of row variable which Omnis uses in the bind variables. This
may be useful if you override $dodelete() for a smart list.
If you want to see the SQL generated by the table instance SQL methods, you can use the
command Get SQL script to return the SQL to a character variable after you have executed
the SQL method. Note that the returned SQL will contain bind variable references which do
not contain $cinst. This is because Get SQL script does not execute in the same context as
the table instance. However, you will be able to see the SQL generated, which should help
you to debug problems.
254
In this final case the object instance in SessObj is duplicated so that the $sessionobject is a
separate instance. However, both instances continue to refer to the same session. This is a
general rule for session instances, when an object instance is duplicated both instances refer
to the same underlying session. For example:
Calculate SessObj as $sessionpools.poolone.$new()
Calculate SessObj2 as SessObj
At this point both variables contain separate instances that refer to the same session and if
we now
Calculate SessObj as $clib.$classes.odbcobj.$new()
SessObj2 continues to refer to the original session whereas SessObj is now a separate object
Calculate SessObj2 as 0
Now no variables refer to the original session that is automatically returned to the pool.
A list defined from an SQL class also has the $statementobject property. This is a read-only
property which is the statement object that is being used by $sessionobject. The
$statementobject property is intended to be used in methods that are being overridden by a
table class ($select for example). Unlike $sessionobject it is not safe to assume
$statementobject will remain the same throughout the life of the list.
A list variable is then defined in the $construct method of a window class using
Do iResultsList.$definefromsqlclass('T_authors')
255
Where lRef is an item reference variable. In this situation $cinst is a reference to the list
variable iResultsList. Note that the statement object iResultsList.$statementobject is
created automatically and there is no need to use the $newstatement method to create it.
The table class enables the developer to override the default SQL methods, for example a
$select method to select all columns in the list variable
Begin statement
Sta: SELECT [$cinst.$sessionobject.$selectnames($cinst)] FROM
[$cinst.$servertablenames]
If len(pExtraQueryText)
Sta: [pExtraQueryText]
End If
End statement
Do $cinst.$statementobject.$prepare() Returns #F
If flag true
Do $cinst.$statementobject.$execute() Returns #F
End If
Quit method #F
256
Oracle
This section contains additional information you need to access an Oracle database,
including server-specific programming, PL/SQL, data type mapping to and from Oracle, as
well as troubleshooting. For general information about logging on and managing your
database using the Omnis SQL Browser, refer to the earlier parts of this manual.
Session Methods
Method
Description
$proxyas()
$endproxy()
Session Properties
258
Property
Description
$nullasempty
$emptyasnull
$trailingspaces
$maxvarchar2
Oracle
Property
Description
7 & 8. The max value is 4000 for DAMORA8 and 2000 for
DAMORA7. Setting $maxvarchar2 to zero forces all character data
to be mapped to the LONG/CLOB data type.
$nationaltonclob
$nationaltonvarchar
$internalcharmapping
$nativewarncode
$nativewarntext
$booltonum
$authmode
259
260
Property
Description
$credentials
$longchartoclob
$binarytoblob
$newpassword
Studio 5.0 and later. Contain the text that will be inserted for
Boolean bind variables. Where these values where previously
taken from the Omnis localization datafile, these properties now
permit localization-independent values to be inserted, e.g. YES
& NO. For backwards compatibility, default values are taken
from Omnisloc.df1. Affects the text returned by $createnames()
and the size of buffers used to insert data.
$querytimeout
Studio 4.3.2/5.0.1 and later. This is the timeout in seconds for any
statement executed via $execute() or $execdirect(). Designed to
detect Unix network hangs, this property has no effect for Win32
and OS X. When a timeout occurs, the connection is marked bad
and a re-connect is necessary. Default value is 10 seconds.
Oracle
Statement Methods
Methods
Description
$plsql()
$prepareforupdate()
StatementObj.$prepareforupdate(vTableDef[,cTablename,cWhere])
creates and prepares a 'select for update' statement for specific use
with positioned updates and deletes.
$posdelete()
$posupdate()
Statement Properties
Property
Description
$nativewarncode
$nativewarntext
$plsqlarraysize
When retrieving data into an Omnis list via PlSql, the number of rows
that will be fetched is not known until the plsql executes. Historically,
the DAM reserved a pre-determined buffer size of 32512 bytes per list
column to be fetched. If the actual number of rows fetched * column
size (in bytes) exceeds this limit for a given column, ORA-06513 is
returned.
The column buffer size is now set according to $plsqlarraysize (default
value 32512), thus the buffer size can be raised (or lowered) as
required in order to accommodate the entire result set.
261
NCHAR
VARCHAR2
NVARCHAR2
CLOB
NCLOB
LONG
By default, the Unicode Oracle DAM maps all Omnis character data to the NVARCHAR2
and NCLOB data types, dependent on the field length of the Omnis bind variable. However,
the Oracle DAM provides session properties which affect the Omnis to Oracle data type
mappings:
$nationaltonvarchar
If set to kTrue, Character and National data types are treated differently when being
inserted to VARCHAR2 / NVARCHAR2 columns.
$nationaltonclob
If set to kTrue, large Character and National data types are treated differently when
being inserted to CLOB / NCLOB columns.
$maxvarchar2
Sets the byte limit above which Omnis character fields will be mapped to
CLOB/NCLOB data types as opposed to VARCHAR2 / NVARCHAR2 columns. The
maximum value is 4000 bytes.
$longchartoclob
If set to kTrue (the default), Omnis large character fields > $maxvarchar2 in byte length
will be mapped to the CLOB/NCLOB data type. If set to kFalse, the LONG data type is
used.
Oracle
PL/SQL
Oracle does not support the remote procedure call methods such as $rpc() which are
described in the SQL Programming chapter. Server procedures can be executed via
PL/SQL. The Oracle DAM fully supports Oracle PL/SQL; a procedural language that the
server executes.
You create a PL/SQL script and send it to Oracle in a similar way as any SQL statement and
the server executes it. The statement object method $plsql() should be used instead of
$prepare() when you want to call server procedures that contain bound OUT or IN/OUT
parameters. Any PL/SQL bind variables being passed to Oracle should be passed as Omnis
bind variables i.e. @[Xvar]. When $plsql() is called with bind variables, the DAM will
check to see whether any return values are present after execution and will return them back
into the Omnis variable. This does not happen after a $prepare(). If you are creating stored
procedures or executing a server procedure for which you do not expect a return value,
$prepare() will be sufficient.
263
After the PL/SQL executes, the Omnis variable lEmpId has the value associated with the
column id from the row with the name Jones.
The Oracle DAM supports select tables returned through PL/SQL procedures. However
Oracle can only return single column tables (arrays). The statement object method, $plsql(),
has optional parameters that follow the cPLSQLtext parameter. These are necessary when
calling server procedures that return single column tables. To bind a column of an Omnis
list to the select table being returned requires a list variable to be bound in the SQL
statement and the list column number to be passed as an additional parameter. If more than
one select table is being returned, multiple lists will need to be bound and a column number
parameter passed for each list, in the same order as the lists are bound. The bound lists do
not have to be different lists, the same list can be bound more than once in the PL/SQL
statement, but you must take care to specify a different column number for each occurrence
of the bound list. If no column number parameter is passed for a bound list, the first column
of the list is used by default.
Consider the following example table and PL/SQL package:
Table: accounts
id
NUMBER(3,0)
1
2
3
4
5
6
7
8
9
264
name
NVARCHAR2(256)
Bill
Sally
Bob
John
Graham
Helen
Betty
Walter
Sarah
balance
NUMBER(16,2)
2000
120
1000
1700
3000
2000
9000
25000
9100
limit
NUMBER(16,2)
2200
100
190
1500
21087
1860
1490
17200
10000
Oracle
create or replace package test as
type account_name is table of accounts.name%TYPE index by
binary_integer;
type account_balance is table of accounts.balance%TYPE index by
binary_integer;
end test;
create or replace procedure credit(accnum IN number, amount IN
number,pname out test.account_name, pbalance out
test.account_balance)
is
cursor c1 is select name,balance from accounts where balance >
limit;
row_count BINARY_INTEGER;
begin
row_count := 1;
update accounts set balance = balance + amount where id = accnum;
open c1;
LOOP
FETCH c1 INTO pname(row_count),pbalance(row_count);
row_count := row_count + 1;
exit when c1%NOTFOUND;
end LOOP;
close c1;
end;
; Local variables:
; lName=Character 256, lBalance=Number2dp, lCreaditList=List
Do SessObj.$blobsize.$assign(32767)
; Prevents ORA-06505
Do lCreditlist.$define(lName,lBalance)
Do StatObj.$plsql('begin credit(2,490,@[lCreditlist],
@[lCreditlist]); end;',1,2) Returns #F
Do StatObj.$execute() Returns #F
If Creditlist.$linecount<>6
; Incorrect data returned from stored procedure
End If
In the above example, the same list has been bound twice, the first bind variable binds the
first column of the list and the second bind variable binds the second column as defined by
the second and third parameters of the $plsql() method.
265
balance
Sally
610.00
Bob
1000.00
John
1700.00
Helen
2000.00
Betty
9000.00
Walter
25000.00
The balance of account id 2 (Sally) has been increased by 490. The procedure returns
details of those accounts where the balance column is greater than the limit column.
266
Oracle
;lEmpSt,lEmpUpSt,lEmpDelSt are Statement Object instances derived
from the same session
;lTableName is a Character(32) variable
;iTableList and lTempList are list variables defined from schema
class scPos1
;lDataRow is a row defined from schema class scPos1
; Fetch the row
Calculate lTableName as $classes.scPos1.$servertablename()
Do lEmpSt.$prepareforupdate(iTableList,lTableName)
Do lEmpSt.$execute()
Do lEmpSt.$fetch(lDataRow,1)
; Update this row
Calculate lDataRow.vala as 5 ;; change the value of one of the
columns
Do lEmpUpSt.$posupdate(lEmpSt,lDataRow)
Do lEmpUpSt.$execute()
; Fetch the next row
Do lEmpSt.$fetch(lTempList,2)
; delete this row
Do lEmpDelSt.$posdelete(lEmpSt)
Do lEmpDelSt.$execute()
267
268
Oracle
This data type can be used in other Oracle objects, such as procedures and functions in
order to process result sets. An example of a Stored function follows:
create or replace function OmnisFunction return
OmnisPackage.cursorType
as
l_cursor OmnisPackage.cursorType;
begin
open l_cursor for select * from scott.dept;
return l_cursor;
end;
An example of a stored procedure that uses the defined REF CURSOR type follows:
create or replace procedure OmnisProcedure
( p_cursor in out OmnisPackage.cursorType )
as
begin
open p_cursor for select ename, empno from scott.emp order by ename;
end;
Cursor variables are like pointers, which hold the memory location (address) of some item
instead of the item itself. So, declaring a cursor variable creates a pointer, not an item.
REF CURSOR data types can be returned in three different ways; via a PL/SQL block, an
Oracle Stored Function or an Oracle Stored Procedure. The REF CURSOR type is a pointer
to a result set. The SQL statement that returns the REF CURSOR must be prepared using
the $plsql() method. The Oracle 8 DAM maps the REF CURSOR type to an Omnis Oracle8
Statement Object*. The statement object will be created by the DAM and will belong to the
same session object as the Statement object that prepared the initial SQL. It will have a
$state of kStatementStateExecuted and, assuming that there is data in the result set, will
have $resultspending set to kTrue. Therefore, the statement object will be in a Ready-For
Fetch state. Below are examples of the three ways to return and use a REF CURSOR in
Omnis. The connection code and the creation of initial Statement Object (myStatement)
have been removed for clarity.
269
PL/SQL Block
The PL/SQL method does not require any SQL objects created on the server. All the
PL/SQL code can be encapsulated in an Omnis Statement block.
; declare vars: cursor1 (Object), myList1 (List)
Begin statement
Sta: begin
Sta: OPEN @[cursor1] FOR SELECT * FROM scott.emp;
Sta: end;
End statement
If myStatement.$plsql()
If myStatement.$execute()
Do cursor1.$fetch(myList1,kFetchAll)
; myList1 will contain the rows of the result set.
Else
OK message Error {[ myStatement.$nativeerrortext]}
End If
Else
OK message Error {[ myStatement.$nativeerrortext]}
End If
Stored Functions
Returning a REF CURSOR from a Stored Function requires an Oracle Stored Function on
the database. The Function must have a return type that has been defined as a REF
CURSOR. For this example we will assume that the example Oracle Stored Function
described above has been created on the server.
; declare vars: cursor2 (Object), myList2 (List)
If myStatement.$plsql('begin @[cursor2] := OmnisFunction; end;')
If myStatement.$execute()
Do cursor2.$fetch(myList2,kFetchAll)
; myList2 will contain the rows of the result set.
Else
OK message Error {[ myStatement.$nativeerrortext]}
End If
Else
OK message Error {[ myStatement.$nativeerrortext]}
End If
270
Oracle
Stored Procedures
Returning a REF CURSOR from an OUT or IN OUT parameter of a Stored Procedure
requires an Oracle Stored Procedure on the database. The Procedure must have an OUT or
IN OUT parameter type that has been defined as a REF CURSOR. For this example we will
assume that the example Oracle Stored Procedure described above has been created on the
server.
; declare vars: cursor3 (Object), MyList3 (List)
If myStatement.$plsql('begin getemps(@[cursor3]); end;')
If myStatement.$execute()
Do cursor3.$fetch(myList3,kFetchAll)
; myList3 will contain the rows of the result set.
Else
OK message Error {[ myStatement.$nativeerrortext]}
End If
Else
OK message Error {[ myStatement.$nativeerrortext]}
End If
XMLType
The XMLType is a system defined data type with predefined member functions to access
XML data. You can perform the following tasks with XMLType:
Create columns of XMLType and use XMLType member functions on instances of the
type.
Create PL/SQL functions and procedures, with XMLType as argument and return
parameters.
271
URIType
The URIType is an abstract object type that can store instances of HttpUriType or
DBUriType. Universal Resource Indicator references can point to XML, HTML and
custom internet content which can be located either locally within the database, externally to
the database but local to the server or remotely across an internet or network connection.
DBUriType
The DBUriType can obtain data pointed to by a DataBaseUri-reference. A DBUri-Ref is a
database relative URI that is a special case of the Uri-ref mechanism, where ref is
guaranteed to work inside the context of a database and session. This ref is not a global ref
like the HTTP URL, instead it is local ref (URL) within the database.
HttpUriType
The HttpUriType implements the HTTP protocol for accessing remote pages.
UriFactoryType
It is not possible to generate table columns using the UriFactoryType. Rather, this is a
PL/SQL package containing factory methods that can be used to generate the appropriate
instance of the Uri types without having to hard code the implementation in the program.
Custom URI types can be defined and registered using this package.
For further information on the application of these data types, refer to the Oracle9i
Application Developer's Guide XML.
If required, the XPath expression parameter to the extract() function can be supplied using a
character bind variable. For further information on the extract() function and the supported
Xpath syntax, refer to the Oracle9i Application Developer's Guide XML.
URITYPE and its derivatives provide the getClob(), getUrl() and getExternalUrl() functions
for data retrieval. When getClob() is executed, the URL stored in the database column is
read. The document pointed to by the URL is then accessed and returned as CLOB data
which can be read into Omnis:
272
Oracle
SELECT a.myuri.getclob() AS mycol FROM mytable a
The getUrl() and getExternalUrl() functions return the URL contained in the database
column. (getExternalUrl() differs from getUrl in that it escapes the URL so that it better
conforms to the URL specification):
SELECT a.myuri.geturl() AS myurl FROM uritest a
The getClob(), getUrl() and getExternalUrl() functions can be overridden when creating
custom URI types as defined using the UriFactoryType. For information on the
UriFactoryType, refer to the Oracle9i Application Developer's Guide XML.
If required, the XML text can be supplied using a character bind variable.
XML data can also be supplied as CLOB data by inlining a SELECT statement (or some
other expression which returns a CLOB):
INSERT INTO xmltable SELECT id, sys.XMLType.createXML(myclob) FROM
clobtable;
Inlining ensures that createXML() receives a CLOB field, which is not possible from Omnis
since CLOBs are converted into Omnis character strings when fetched.
To insert a URL into a URIType column or one of its derivatives, use the createUri()
function. For example:
INSERT INTO uritest VALUES
(,sys.httpUriType.createUri(http://www.omnis.net),)
If required, the URL can be supplied using an Omnis character bind variable.
273
Omnis to Oracle
Omnis Data Type
CHARACTER
[1]
Character/National <= the value of
$maxvarchar2 (default is 2000)
[1]
Character/National > the value of
$maxvarchar2 (default is 2000)
DATE/TIME
Short date (all subtypes)
Short time
Date time (#FDT)
NUMBER
Short integer (0 to 255)
Integer 64 bit
Integer 32 bit
Short number 0dp
Short number 2dp
Number floating dp
Number 0..14dp
OTHER
Boolean
Sequence
Picture
Binary
List
Row
Object
Item reference
[1]
DATE
DATE
DATE
NUMBER(3, 0)
NUMBER(19,0)
NUMBER(11, 0)
NUMBER(10, 0)
NUMBER(10, 2)
FLOAT
NUMBER(16, 0..14)
[2]
VARCHAR2(3)
NUMBER(11, 0)
[3]
BLOB
[3]
BLOB
[3]
BLOB
[3]
BLOB
[3]
BLOB
[3]
BLOB
274
Oracle
Oracle to Omnis
Server Data Type
CHARACTER
CHAR / NCHAR
Character
VARCHAR2 / NVARCHAR2
Character
CLOB / NCLOB
Character
BLOB
Binary
BFILE
Binary
LONG
Character
RAW
Binary
LONG RAW
Picture
DATE/TIME
DATE
NUMBER
NUMBER(p,0)
p>10
Integer 64 bit
NUMBER(p,s)
p<=10 or s>0
Number floating dp
NUMBER ( NUMBER(0,0) )
Number floating dp
FLOAT
Number floating dp
Oracle Troubleshooting
The following points may help in resolving issues in programming Omnis applications that
use an Oracle database.
When performing transactions that use the new LOB data types the transaction mode must
be set to either kSessionTranAutomatic or kSessionTranManual. This is because LOB and
file locators can not be used across transactions. The DAM performs functionality on these
locators and when the transaction mode is either automatic or manual, the DAM can control
when to commit the command, which would be after all the LOB functionality has been
performed. When the transaction mode is server, Oracle commits (or rollbacks) after every
statement and any LOB functionality performed by the DAM would result in an error.
Oracle has a client character set and a server character set. If the two are not the same
character set, Oracle will convert between the two. If a character in the client character set
also exists in the server character set, Oracle will store that character on the server. If the
character doesnt exist in the server character set, Oracle will do one of two things. Firstly,
Oracle will see if there is a close-fit character. For example, if you are trying to insert the
character , but that particular character is not in the server character set, Oracle will store
that character as an a as it is a close-fit. If there is not a close-fit character, Oracle will
275
276
Sybase
Sybase
This section contains the additional information you need to access a Sybase database,
including server-specific programming, data type mapping to and from Sybase, as well as
troubleshooting. For general information about logging on and managing your database
using the Omnis SQL Browser, refer to the earlier parts of this manual.
Session Properties
Property
Description
$programname
$logontimeout
The timeout in seconds for a logon. The default is 60 seconds. Set this
to 0 for no timeout. Note that a timeout is ignored if $failtimeout is
kFalse.
$querytimeout
$failtimeout
$encryptpassword
Set to kTrue to use password encryption when logging on. The default
is kFalse.
$cterrorlayer
Layer at which the current session client error occurred. Read only.
$cterrororigin
$cterrorseverity
$cterrornumber
$moneydps
277
Description
$locale
The locale name that will be used by the connection. This is initially
set to the default locale contained in the Sybase locales.dat file.
$locale may be set to a different value provided that the DAM is not
logged on.
Valid locale strings include locale names or language-character set
pairs contained in the locales.dat file for which the corresponding
language modules are installed. Assignment fails if the locale
information specified cannot be found or is not installed.
$nationaltounichar
Session Methods
278
Method
Description
$setremotepassword()
$clearremotepasswords()
Sybase
Statement Properties
Property
Description
$cterrorlayer
$cterrororigin
$cterrorseverity
$cterrornumber
$rpcparamspending
$bindshort0dpassmallint
$emptystringisblank
Statement Methods
Method
Description
$cancelresultset()
$writelob()
279
The Sybase DAM reports the select tables exactly as Open Client reports them. If a select
result set has no rows, $fetch() will return kFetchFinished the first time it is invoked for that
set.
Program Name
The Sybase sysprocesses table (in the master database) has a program_name column that
stores a separate name for each connection to the server. The session $programname
property lets you put a name into this column for the current session so that you can use it to
distinguish multiple sessions.
The default name is the name of the current library, i.e. $clib().$name If you wish to change
this you must set this property before logging on to the server, because the value gets set at
logon. If the value is set after logon it does not take affect until the session is logged on
again. The value persists across logons and logoffs, and $clear() does not reset it.
If the string assigned to the property is too long, the DAM truncates it without reporting an
error. The DAM can store a maximum of 255 characters but the program_name field in the
sysprocesses table currently only allows 16.
280
Sybase
Error Handling
If an error is raised on either a Sybase session or statement object, the $errorcode and
$errortext properties associated with the object will provide the generic error code and error
text. If there is an associated native Sybase server or client error this will be returned in the
$nativeerrorcode and $nativeerrortext properties associated with the object.
It is possible for an Omnis command to generate multiple Sybase server and client error
messages. If this is the case, the objects $nativeerrorpending property will be set to kTrue.
To retrieve the next set of error information the application can use the $nextnativeerror()
method. The DAM will return server errors and then client errors in the order in which they
were generated. Any informational messages returned from Sybase are ignored.
If a new Sybase DAM command is issued or a Sybase property is set, the current error
information for that object is cleared. The error set for the session is shared between the
session and all statements in that session. If a session or statement clears the current error
set, any other statement with multiple errors pending will only be able to retrieve the last
cached error since the error set will have been cleared.
You should be aware that the Sybase server and client errors reported may have codes and
messages that sometimes differ between the OS X and Windows Sybase clients.
The Sybase DAM defines several of its own internal error codes. These are returned in the
$nativeerrorcode and $nativeerrortext properties of the session and statement.
Error Code
Description
20000
20005
20010
20011
20030
20050
20051
The table name must be a character string which is not null or empty
20052
The column name must be a character string which is not null or empty
20053
20054
20055
If a Sybase session or statement object generates an Open Client error, the error code is
decoded into the $cterrorlayer, $cterrorseverity, $cterrororigin and $cterrornumber. Sybase
281
This setting is for fetching values only. When fetching LOBs under MacOS Classic using
the standard commands, you should not set this parameter to its largest value. Increasing
this also causes Open Client to allocate more memory to deal with the larger LOBs.
Therefore, setting it too small will truncate your fetched data while setting it too large may
cause Open Client to kill your connection. If you are retrieving a variety of LOBs, you
should try to set it as closely as you can to the size of the largest LOB; you can set this for
each SQL statement sent. You can also use the Sybase datalength() function to find out how
long the value is that you want to retrieve, and use this to set the textsize parameter.
The Sybase DAM provides a faster and more memory efficient way to update a text or
image column through the use of the statement method $writelob(). To use the $writelob()
method you must already have the row in the database and the column value that is being
282
Sybase
updated must have non-NULL data in it.. You would usually create the row with a blank (' ')
in the column, for instance, use the $writelob() method to update the value with the LOB
data.
Do tStatement.$execdirect ("insert into mytable (x, mycol) values
(2, ' ')")
Do tStatement.$writelob(LOB_DATA,'mytable','mycol','where
x=2',kTrue)
This command places the value of the Omnis field LOB_DATA into the column mycol of
the table mytable in the row where x has the value of 2. Thus, the method places a single
LOB value into a location that you specify.
The method is defined as:
StatementObj.$writelob(vVariable, cTablename, cColumnname [,cWHEREclause, bUselog = kTrue])
The vVariable parameter is the Omnis variable containing the data to be sent to the server,
in the example this is LOB_DATA. This variable cannot be NULL or empty.
The cTablename and cColumnname parameters identify the table and column to update.
These can not be NULL or empty.
The cWHERE-clause parameter supplies an optional WHERE clause for a SQL SELECT
statement, including the word WHERE. If your WHERE clause is ambiguous Omnis
updates the first LOB value it finds, so the value updated may not be the one you intended.
Make sure your clause specifies a unique row.
The bUseLog parameter denotes whether to log this action in the transaction log. If you do
not log the action, you cannot roll it back. The default is kTrue to log the update. Setting
this parameter to kFalse requires that the select into/bulkcopy option be set to true with the
system procedure sp_dboption for the database on the DBMS. If you do not wish to log
updates, you must consult your documentation and system administrator as this may have
significant ramifications on being able to backup and recover your database.
The $writelob() method sets the flag false and sets error information in the same way as a
standard statement method.
Sybase recommend that data should be updated using the $writelob() method if the data size
exceeds 100K.
283
#L1.$define(#1,#2,#3,#4) Returns #F
#L1.$add(kInteger,kLongint,0,kParameterReturnValue)
#L1.$add(kCharacter,kSimplechar,30,kParameterInput)
#L1.$add(kCharacter,kSimplechar,30,kParameterInput)
#L1.$add(kCharacter,kSimplechar,30,kParameterOutput)
tSession.$rpcdefine('Test_SYBRPC',#L1) Returns #F
Since the stored procedure generates two result sets these must be processed first.
This will fetch the results from the sysusers and sp_who queries.
284
Sybase
If tStatement.$resultspending=kTrue
Do #L1.$define()
Do tStatement.$fetch(#L1,kFetchAll) Returns #1
End If
If tStatement.$resultspending=kTrue
Do #L1.$define()
Do tStatement.$fetch(#L1,kFetchAll) Returns #1
End If
The stored procedure return status is placed in the statements $rpcreturnvalue property and
the parameter result set is then available.
Calculate #1 as tStatement.$rpcreturnvalue ;; will set #1 to 12345
If tStatement.$rpcparamspending=kTrue
Do #L1.$define()
Do tStatement.$fetch(#L1) Returns #1
End If
Calculate Parm3 as #L1.1.1
;; will set Parm3 to 'Hello There'
An RPC or stored procedure can invoke procedures on another server. To do this, the server
that the first procedure is running on must log onto the other server and for this you can set
up a password to use when logging onto that server. The Sybase session object provides the
$setremotepassword() method to allow you to set up remote passwords. This associates the
specified password with the specified server for this connection to the DBMS. You can call
this multiple times to establish passwords for different servers.
If the server name is NULL, the password is a 'universal' password that you can use with
any server for which you haven't already established a password.
To clear all remote passwords use the $clearremotepasswords() session method.
Multiple Cursors
If a statement is issued without using a cursor, i.e. $usecursor is set to kFalse, any results
generated will block the connection and no other operation on any other statement can be
performed until the blocking result set is completely fetched or cancelled. To avoid
blocking the connection with pending results, use a statement which has the $usecursor set
to kTrue. Note that a statement using a Sybase cursor must have a unique statement name
and only allows SQL SELECT and EXECUTE procedure commands to be issued.
Meta-Data Queries
As of Studio 5.1.1, the $indexes() meta data method returns additional information via the
DamInfoRow column. The DamInfoRow will be defined with the following columns (as
returned by the sp_statistics stored procedure):
TableName
Character column indicating the index owner. For Sybase, this is usually
the same as TableName.
IndexType
Collation
Cardinality
Pages
Integer column containing the number of pages used to store the index.
Sybase Troubleshooting
The following points may help in resolving issues in programming Omnis applications that
use a Sybase database.
Sybase is a case-sensitive RDBMS. Check the case of the table or column names if you
can see a table but cannot select anything out of it
Sybase defaults to NOT NULL columns; you must initialize columns to a specific value
while inserting data, or insertion will fail
Any number with no digits after the decimal point, that is > +/- 231 will generate an
error and not be inserted. This is because Sybase tries to parse numbers without
decimal points as integers
286
Sybase
Sybase does not support binding a NULL Boolean field in Omnis to a Sybase bit field
Sybase does some character mapping where required, but you may need to do character
conversion explicitly using the Omnis character mapping tables.
Sybase interprets empty strings as single spaces.
Fetching pictures from Sybase stored there by other applications, even in standard
formats, is likely to cause problems, since Omnis stores all pictures in a special format.
This occurs even in platform-specific graphics formats such as PICT or BMP.
The $tables() session method can only report information about tables in the current
database and does not return system tables.
The $columns() session method can only report information about tables owned by the
current user in the current database.
The $indexes() session method can only report information about indexes on tables in
the current database.
Sybase does not allow DDL statements to be issued within a user defined transaction,
i.e. do not use statements such as CREATE, DROP and ALTER when the sessions
transaction mode is kSessionTranManual. Do not use the $indexes() method using
kSessionTranManual since this method creates a table.
Sybase automatically strips spaces from character data returned to Omnis.
Data buffers could not be allocated error following a logon attempt:
This error normally occurs if the Sybase environment variables; SYBASE,
SYBASE_OCS and/or LANG/LC_ALL are not correct.
Check the sybinit.err file (in the Omnis folder) for more details about the error.
Further troubleshooting notes, how-tos and tips can be found on the Omnis website at:
www.omnis.net/technotes
287
Omnis to Sybase
Omnis Data Type
CHARACTER
Character/National 0
Character/National 1 <= n <= 255
Character/National > 255
DATE/TIME
Short date (all subtypes)
Short time
Date time (#FDT)
NUMBER
Short integer (0 to 255)
Integer 32 bit
Integer 64 bit
Short number 0dp
Short number 2dp
Number floating dp
Number 0..14dp
OTHER
Boolean
Sequence
Binary/Picture/List/Row/Object/Item
reference where $blobsize <= 255
Binary/Picture/List/Row/Object/Item
reference where $blobsize > 255
288
Sybase
Sybase to Omnis
Sybase Data Type
CHARACTER
char(n)
varchar(n)
nchar(n)
nvarchar(n)
text
DATE/TIME
datetime
smalldatetime
NUMBER
tinyint
smallint
int
bigint
numeric(p,n)
decimal(p,n)
real
float
double precision
money
smallmoney
OTHER
bit
binary(n)
varbinary(n)
image
289
DB2
This section contains the additional information you need to access a DB2 Universal Server
database, including server-specific programming, data type mapping to and from DB2, as
well as troubleshooting. For general information about logging on and managing your
database using the Omnis SQL Browser, refer to the earlier parts of this manual.
Session Properties
Property
Description
$datetimeformat
$drivername
$driverodbcversion
Session Methods
290
Method
Description
$getdatasources()
DB2
Statement Properties
Property
Description
$erroronnodata
In the event of connection failure, the DAM will timeout as dictated by any timeout policy
in use by the server. Logon failures are usually reported immediately.
Transactions
Generally, using manual transaction mode results in increased performance because the
session object does not force a commit after each statement.
If you do not have a results set pending, the DB2 session object will commit each statement
if the transaction mode is automatic. If the transaction mode is server, the server commits
the statement automatically.
Dates
The session property $defaultdate allows default values to be added to date values mapped
to the server where the Omnis date value does not contain complete information, e.g. when
a Short time is mapped to a server DATETIME. The date stored in this property is in a
generic format, i.e. it is compatible with any regional date format that the server may be
using.
291
Boolean Type
DB2 does not include a specific type for storing single bit data. The Omnis Boolean type is
therefore converted to a CHAR(3) value and stored as YES or NO in the server table.
The string representation can then be mapped back to an Omnis Boolean type when the data
is retrieved.
BLOB Type
The session property $blobsize can be used to specify the size argument for columns of type
BLOB generated when the $createnames and $coltext methods are used.
Values range from 1 to 10000000. The default value for $blobsize is 10000000 which is
also the maximum size of an Omnis binary variable.
This property is equivalent to the old-style <SETBLOBSIZE> keyword.
Meta-Data Queries
The meta-data statement methods $columns(), $indexes() and $tables() allow you to receive
information about the objects in your database. The $tables() method takes an optional
owner name as a parameter. The $indexes() and $columns() methods optionally take the
database and/or owner name with the table name parameter. See SQL Programming for
more information on these methods.
When a database, owner or table name is specified, the result set is constrained by those
schemas which meet the filter criterion, i.e. to return column information about the
addressbk table owned by robert in database acc_db the following can be issued.
Do tStatement.$columns('acc_db.robert.addressbk') Returns #F
DB2 Troubleshooting
Reserved Words
This section covers the DB2 specific reserved words.
The following schema names are reserved: SYSCAT, SYSFUN, SYSIBM & SYSSTAT.
In addition, it is strongly recommended that schema names never begin with the SYS prefix,
as SYS is by convention used to indicate an area reserved by the system.
There are no words that are specifically reserved words in DB2. Keywords can be used as
ordinary identifiers, except in a context where they could also be interpreted as SQL
keywords. In such cases, the word must be specified as a delimited identifier. For example,
COUNT cannot be used as a column name in a SELECT statement unless it is delimited.
IBM SQL and ISO/ANSI SQL92 include reserved words, these reserved words are not
enforced by DB2 Universal Database, however it is recommended that they not be used as
292
DB2
ordinary identifiers, since this reduces portability. Please see the final chapter in this manual
which lists the SQL reserved words.
Further troubleshooting notes, how-tos and tips can be found on the Omnis website at:
www.omnis.net/technotes
293
NUMBER
SMALLINT
Integer 32 bit
INTEGER
Integer 32 bit
BIGINT
Integer 64 bit
DECIMAL(p,s)
Number (s)dp
NUMERIC(p,s)
Number (s)dp
FLOAT
Number floating dp
REAL
Number floating dp
DOUBLE
Number floating dp
CHARACTER
CHAR(n)
Character (n)
VARCHAR(n)
Character (n)
LONG VARCHAR(n)
Character (n)
CLOB(n)
Character (n)
DATE/TIME
DATE
Short date
TIME
Short time
TIMESTAMP
BINARY
BINARY
Binary
VARBINARY
Binary
LONGVARBINARY
Binary
BLOB
Binary
EXTENDERS
294
IMAGE
Binary
AUDIO
Binary
VIDEO
Binary
TEXT
Binary
MySQL
MySQL
This section contains the additional information you need to access a MySQL database,
including server-specific programming, data type mapping to and from MySQL, as well as
troubleshooting. For general information about logging on and managing your database
using the Omnis SQL Browser, refer to the earlier parts of this manual.
Session Properties
Property
Description
$clientflags
$database
$hostinfo
$logontimeout
$port
$protoversion
$socket
SessObj.$socket is the socket or named pipe that should be used for the
connection, applicable to non-TCP/IP connections only.
$sslcipher
SessObj.$sslcipher returns the name of the SSL cipher being used for the
current SSL connection or empty for a non-SSL connection. (Read-only)
$threadid
$threadsafe
295
Session Methods
296
Method
Description
$changeuser()
$characterset()
$connectoption()
$getdatatypemapping()
$insertid()
$ping()
$query()
MySQL
Method
Description
$queryinfo()
$queryresult()
$serverdebuginfo()
$servershutdown()
$serverstatus()
$setdatatypemapping()
SessObj.$setdatatypemapping({lMappings}) sets the Omnis-toMySQL data type mappings for the session. The supplied list
contains a prioritised list of mappings for Omnis data types and
subtypes to their intended MySQL server data types. See the section
below on the format of the mapping list. $setdata typemapping() can
be used to map certain data type/subtypes to custom MySQL data
types, e.g. SET and ENUM types. This is also explained in the
section below. On successful execution of $setdatatypemapping()
kTrue is returned, otherwise kFalse is returned. SessObj.$setdata
typemapping() can be called either before or after the session has
logged on.
$sslset
297
Statement Methods
Method
Description
$columns()
$rpcprocedures()
Logging on to MySQL
The MySQL DAM interfaces directly with the MySQL client library, therefore the way the
DAM logs on to the server is slightly different to the other Object DAMs.
298
MySQL
Specifically, the $logon() hostname parameter is taken as the server hostname or IP address.
The username and password parameters are supplied as normal.
As well as the parameters supplied to $logon(), there are some additional parameters which
you can set using the following session properties:
$port - The port number of the MySQL server
$database - The database name
$clientflags - Sets additional behavior for the logon
$socket - Specified if you do not want to use a TCP/IP connection
When logging on using the SQL Browser, default values are used when the Port and
Database fields are left blank.
Transactions
If you require transaction support with MySQL, your server needs to support BDB or
InnoDB table types. Manual transactions may only be made on tables of these types.
When creating tables, you need to specify the table type required if you do not want the
default type (MyISAM).
The following properties and methods apply to transactions. Use of these properties or
methods is equivalent to executing the SQL statements shown:
$begin()
SessObj.$begin() = Begin
$commit()
SessObj.$commit() = Commit
$rollback()
SessObj.$rollback() = Rollback
$transactionmode
SessObj.$transactionmode.$assign(SessionMode)
kSessionTranAutomatic: Autocommit = 1 (the default)
kSessionTranServer: Autocommit = 1
kSessionTranManual: Autocommit = 0
If you are not using InnoDB or BDB table types, you can achieve table locking using the
MySQL lock tables or unlock tables SQL commands. Refer to the MySQL
language reference for further details.
299
CHARACTER
Character n (n<=255)
VARCHAR(n)
National n (n<=255)
NATIONAL VARCHAR(n)
Character/National n (n<=65534)
TEXT
Character/National n
(65534<n<=10000000)
MEDIUMTEXT
NUMBER
Integer 64 bit
BIGINT
Integer 32 bit
INT
Short integer
TINYINT UNSIGNED
Number 0..14dp
DECIMAL(15,0..14)
Number floating dp
DOUBLE
DECIMAL(9,0/2)
DATE/TIME
Short date (all subtypes)
DATE
Short time
TIME
Datetime (#FDT)
DATETIME
OTHER
300
Boolean
BOOL
Picture
MEDIUMBLOB
List
MEDIUMBLOB
Row
MEDIUMBLOB
Object
MEDIUMBLOB
Binary
MEDIUMBLOB
Item reference
TINYBLOB
Sequence
MySQL
Note that this is equivalent to the list returned by a call to $getdatatypemapping() on a
newly created session object:
OmnisType
OmnisSubtype
Parameter
MySqlType
char
simple
255
VARCHAR($)
char
national
255
NATIONAL VARCHAR($)
char
national
65534
TEXT
char
national
10000000
MEDIUMTEXT
integer
64 bit
BIGINT
integer
32 bit
INT
integer
shortint
TINYINT UNSIGNED
number
14dp
DECIMAL(15,$)
number
float
DOUBLE
number
2dpShortnum
DECIMAL(9,$)
boolean
BOOL
date
date2000
DATE
date
time
TIME
date
datetime
DATETIME
picture
MEDIUMBLOB
list
MEDIUMBLOB
row
MEDIUMBLOB
object
MEDIUMBLOB
binary
MEDIUMBLOB
itemref
TINYBLOB
Numeric value
(precedence)
Character equivalent
(OmnisSubtype)
0
1
simple
national
0
32
64
32 bit integer
shortint
64 bit integer
0
1
2
3
4
5
6
8
10
12
14
24
32
34
0dp
1dp
2dp
3dp
4dp
5dp
6dp
8dp
10dp
12dp
14dp
float
0dpShortnum
2dpShortnum
0
1
2
6
1000
date1900
date1980
date2000
time
Datetime
Note that where an Omnis type does not have a subtype (e.g. Binary), it is acceptable to
leave the subtype column blank.
302
MySQL
Parameter column
The Parameter value in the data type mapping list specifies the maximum length or size of
data to which the mapping will apply, e.g. a value of 255 specified for a character data type
signifies that that mapping will apply to Omnis character data with a length of <= 255
characters. You should therefore ensure that where there are multiple occurrences of the
same Omnis data type and subtype, these are entered in ascending order of parameter value.
The maximum size of an Omnis character/binary field is 10,000,000 bytes.
MySqlType column
The MySqlType value specifies the string which will be returned by session.$createnames()
when that row matches the supplied Omnis data type & subtype. This can be (but is not
restricted to) any string which constitutes a valid MySQL column type, e.g.
SET(One,Two,Three,Four).
Where a $ character is used as part of the MySQL type, the appropriate length or scale
attribute will be substituted when $createnames() is called.
For valid MySQL data type assignments, the DAM also uses the data type mapping table to
map outgoing bind variables to their corresponding MySQL column types.
Example applications of $setdatatypemapping()
The intended use of $setdatatypemapping() is to allow schema columns to conditionally
map to custom MySQL data types, not implemented by default, e.g. the SET, ENUM,
GEOMETRY and YEAR types and also to allow extra type qualifiers to be added, such as
UNSIGNED, PRIMARY KEY, AUTO_INCREMENT, etc.
To get $createnames() to return one of these types, you might for example isolate a specific
character string length and add a data type mapping for your new type.
Then whenever $createnames() encounters a string of that specific length, the mapping to
your new type will occur. If you want to implement the SET data type, you could insert a
new mapping entry between the first and second default entries, adjusting the length
parameters as shown below:
char
simple
254
VARCHAR($)
char
simple
255
SET(One,Two,Three,Four)
char
national
255
NATIONAL VARCHAR($)
Alternatively, you could dedicate the national character subtype for your custom data
types, leaving the simple character subtype for standard character mappings.
303
MySQL to Omnis
The following mappings are hard-coded and cannot be altered.
MySQL Column Type
Range
OmnisType/
Subtype
NUMBER
Boolean
BIT/BOOL/TINYINT(1)
TINYINT UNSIGNED
TINYINT
SMALLINT
MEDIUMINT
INT/INTEGER
BIGINT
FLOAT
DOUBLE/REAL
DEC/DECIMAL/NUMERIC
DATE/TIME
DATE
DATETIME
TIMESTAMP
TIME
YEAR
CHARACTER
CHAR
VARCHAR
TINYTEXT
TEXT
MEDIUMTEXT
LONGTEXT
ENUM
SET
BINARY
TINYBLOB
BLOB
MEDIUMBLOB
LONGBLOB
304
(0..+255)
(-128..+127)
2^16 (-32768..+32767)
2^24 (-8388608..+8388607)
2^32 (-2147483648..+2147483647)
2^64 (-2^63..+2^63-1)
Short integer
Short number 0dp
Integer 32 bit
Integer 32 bit
Integer 32 bit
Integer 64 bit
Num floating dp
Num floating dp
Num 0..14dp
Datetime (#FDT)
Datetime (#FDT)
Datetime (#FDT)
Datetime (#FDT)
Integer 32 bit
Character
Character
Character
Character
Character
Character
Character
Character
Binary
Binary
Binary
Binary
PostgreSQL
MySQL Troubleshooting
The following points may help in resolving programming issues encountered using MySQL
session and statement objects. For additional updated trouble shooting issues, refer to the
readme file which accompanies your installation media.
$sqlstripspaces has no effect for MySQL sessions. MySQL automatically strips trailing
spaces from data inserted into CHAR and VARCHAR columns. Character data
returned from the server will already be stripped of trailing spaces.
MySQL 4.1 does not support chunking of fetched (output) LOB data (TEXT and
BLOB types). Chunking of input LOB data is supported.
$rowcount will be 1 following execution of a SELECT, SHOW or EXPLAIN
statement. This is because MySQL cannot determine this value until the final row has
been fetched.
The MySQL DAM is compatible with MySQL Server version 4.1 and later. Prior to
Omnis Studio version 4.1, connection is only possible to a commercial version of
MySQL Server (i.e. MySQL pro or classic). Later versions of Studio do not have
this restriction.
Further troubleshooting notes, how-tos and tips can be found on the Omnis website at:
www.omnis.net/technotes
PostgreSQL
This section contains the additional information you need to access a PostgreSQL database,
including server-specific programming, data type mapping to and from PostgreSQL, as well
as troubleshooting. For general information about logging on and managing your database
using the Omnis SQL Browser, refer to the earlier parts of this manual.
For additional information on changes to the PostgreSQL DAM, refer to the readme file
which accompanies your installation media.
Win32 platforms
For Win32 platforms, the library search path includes the Windows\System32 folder or any
location in the PATH environment variable, including the folder containing omnis.exe. The
Win32 client library is named libpq.dll.
305
2007-01-15
10:20
2007-01-15
10:20
libpq.so.5.0
Under Linux and OS X therefore, it is essential that the target library and symbolic link to it
both exist either in the library search path or in the same folder as the Omnis executable.
OS X only
The client library supplied with Omnis Studio is built as a Universal Binary- meaning that it
is compatible with both Mac-Intel and Mac-PPC architectures. If you substitute this library
for one obtained e.g. from the PostgreSQL website, please note that the replacement library
may support a single architecture, restricting use of the DAM to that architecture only.
You can determine the architecture(s) supported by a Mach-O dynamic library using the
file terminal command. For example:
>
file libpq.5.0.dylib
306
PostgreSQL
Session Properties
Property
Description
$maxvarchar
Defines the maximum size above which- Omnis Character fields will
be mapped to TEXT type instead of VARCHAR. The default value
for this property is 2000.
$database
$service
$protocolversion
$backendpid
$port
Used to set the additional port logon parameter. This property has a
default value of 5432.
$socket
$options
$logontimeout
$timezone
307
Description
The default time zone is +00 but $timezone will accept any
character string (80 characters max).
308
$usetimezone
$serializable
$readonly
$schema
$numericprecision
$sequencetoint
$char38touuid
$char39tooid
PostgreSQL
Session Methods
Method
Description
$connectstatus()
$escapebinary()
$getssl()
$transactionstatus()
Returns the current in-transaction status of the server. The status can
be kPgSqlTranIdle (currently idle), kPgSqlTranActive (a
command is in progress), kPgSqlTranInTrans (idle, in a valid
transaction block), or kPgSqlTranINError (idle, in a failed
transaction block). kPgSqlTranUnknown is reported if the
connection is bad. kPgSqlTranActive is reported only when a query
has been sent to the server and not yet completed.
$parameterstatus()
$reset()
$cancel()
$addcustomtype()
Description
8.3 enum and xml columns.
310
$clearcustomtypes()
$lobimport()
$lobexport()
$lobcreate()
$lobunlink()
$lobopen()
$lobwrite()
$lobread()
$lobseek()
$lobtell()
PostgreSQL
Method
Description
$lobtruncate()
$lobclose()
Statement Properties
Property
Description
$sqlstate
Logging on to PostgreSQL
In addition to the hostname, username and password parameters provided by the $logon()
method, the PostgreSQL DAM provides several session properties which enable additional
logon parameters to be set. These should be set before calling $logon().
$database is used to specify the dbname connection parameter.
$port is used to specify the port connection parameter.
$logontimeout is used to specify the connect_timeout parameter.
$options is used to specify further optional connection parameters.
$service is used to specify a service (filename) to use for additional parameters.
Metadata Functions
$indexes()
The DamInfoRow for $indexes() is defined with a single column containing the SQL text
used to define the index.
$tables()
The PostgreSQL DAM implements $tables() slightly differently. In particular- only the
kStatementServerTable and kStatementServerView parameters are supported. This is
because the processes for querying tables are incompatible with those for querying views.
(kStatementServerAll defaults to kStatementServerTable).
311
Transactions
PostgreSQL supports two transaction isolation levels: Read Committed (the default) and
Serializable. Using Read Committed mode, a statement can only see rows that were
committed before the current transaction began. Using Serializable mode, all statements in
the current transaction can only see rows that were committed before the first query or datamodification statement was executed in this transaction.
Transactions can also be instantiated as read-only if required. This enables significant
performance improvements for read operations. When a transaction is read-only, the
following SQL commands are disallowed: INSERT,UPDATE,DELETE and COPY FROM
if the table they would write to is not a temporary table; all CREATE,ALTER and DROP
commands; COMMENT,GRANT,REVOKE,TRUNCATE,EXPLAIN ANALYZE and
EXECUTE if the command they would execute is among those listed. Please refer to the
PostgreSQL documentation on transactions for further details.
When using manual transaction mode (kSessionTranManual), the transaction isolation level
can be switched between Read Committed and Serializable using the $serializable session
property.
The access mode can be changed using the $readonly session property.
The PostgreSQL DAM treats the kSessionTranAutomatic and kSessionTranServer
transaction modes identically. In either of these modes the server automatically begins and
commits read/write transactions.
312
Language
IsAgg
SecDef
IsStrict
RetSet
kTrue if the function returns a result set (i.e. multiple values of the
specified data type).
PostgreSQL
Volatile
Indicates whether the function result depends only on its input arguments,
or is affected by outside factors. It is i for "immutable" functions, which
always deliver the same result for the same inputs. It is s for "stable"
functions, whose results (for fixed inputs) do not change within a scan. It
is v for "volatile" functions, whose results may change at any time, that
have side-effects for other functions or tables or functions which cannot
otherwise be optimised.
Source
$rpc(). Calling $rpc() is similar to executing a SQL SELECT statement of the form:
SELECT * from proc_name (param1,
param2, )
with the exception that $rpc() will also set any InputOutput or Output parameters.
Any return value generated by the function will be available via $rpcreturnvalue although in
the case where the function generates a result set, it may be preferable to retrieve the entire
set by calling $fetch(). The value returned by $rpcreturnvalue is also returned as the first
row of this result set.
313
CHARACTER
Character/National n (n<=$maxvarchar)
VARCHAR(n)
Character/National n (n>$maxvarchar)
Character(38)
NUMBER
TEXT
UUID [3]
Integer 64 bit
BIGINT
Integer 32 bit
INTEGER
Short integer
SMALLINT
Number 0..14dp
NUMERIC(15[1] ,0..14)
NUMERIC(15[1],0/2)
Number floating dp
DOUBLE PRECISION
DATE/TIME
Short date (all subtypes)
DATE
Short time
TIME /TIMETZ*
TIMESTAMP /TIMESTAMPTZ*
OTHER
Boolean
BOOLEAN
Sequence
SERIAL/INTEGER [2]
Picture
BYTEA
List
BYTEA
Row
BYTEA
Object
BYTEA
Binary
BYTEA
Item reference
BYTEA
[1] Numeric precision for Number (dp) columns uses the value of $numericprecision.
[2] The mapping used for the Omnis Sequence type depends on the value of $sequencetoint.
[3] This mapping occurs only if $char38touuid is set to kTrue
*Time zone data types are used when session.$usetimezone is set to kTrue
314
PostgreSQL
PostgreSQL to Omnis
PostgreSQL Data Type
Description
INT2/SMALLINT
-32768 to +32767
Integer 32 bit
INT/INT4/INTEGER
-2147483648 to +2147483647
Integer 32 bit
INT8/BIGINT
-2^63 to +2^63-1
Integer 64 bit
SERIAL
1 to 4294967296
Integer 32 bit
SERIAL8/BIGSERIAL
1 to 2^64
Integer 64 bit
FLOAT4/FLOAT/REAL
1E-37 to 1E+37
Number floating dp
DOUBLE/FLOAT8
1E-307 to 1E+308
Number floating dp
NUMERIC
MONEY
-21474836.48 to +21474836.47
Number 2dp
DATE
Dates only
Short date
TIMESTAMP/TIME
Datetime (#FDT)
NUMBER
DATE/TIME
Character
INTERVAL
Character
CHAR
Character
VARCHAR
Character
TEXT
BOOLEAN/BOOL
CHARACTER
Boolean
Character
UUID
Character 36
ENUM
Character 64
XML
Character
Binary
DAM will map decimal values to the Omnis Number dp data type where column scale is <=14
315
but the DAM also accepts UUIDs formatted without hyphens and/or encapsulated using
curly braces.
Output from UUID columns is always in the standard form.
To allow input binding of UUIDs and to make $createnames() return UUID types, it is
necessary to set $char38touuid to kTrue. Once set, the Omnis Character 38 data subtype
maps to UUID.
Note: there is no facility either in the PostgreSQL client library or in the DAM to create
UUID values. This must be implemented by the Omnis application.
ENUM
Enumerated types are created by executing CREATE TYPE statements, for example:
Do statObj.$execdirect("CREATE TYPE mood AS ENUM ('sad',
'ok', 'happy')") Returns #F ;;creates the enumerated type
To make Omnis map certain character sub types to ENUMs, the $addcustomtype() method
is provided.
The following example maps the Omnis Character 2001 data subtype to the mood
enumerated type:
Do sessObj.$addcustomtype(2001,'mood') Returns #F
Once set, this mapping affects the text generated by $createnames() as well as input binding.
To clear previously defined enumerated type mappings, the $clearcustomtypes() method is
provided.
XML
The $addcustomtype() method can also be used to force an Omnis Character subtype to map
to the XML data type, for example:
Do sessObj.$addcustomtype(10001,'xml') Returns #F
As above, this mapping affects the text generated by $createnames() as well as input
binding and remains in effect until $clearcustomtypes() is called.
316
PostgreSQL
$lobimport() creates a large object and imports data into it from a local file.
$lobexport() retrieves data from a large object and writes it to a local file.
$lobcreate() creates a new (empty) large object and returns the OID value.
The large objects are identified by their OID values, which can subsequently be stored and
retrieved in database Oid columns in a similar fashion to standard integers.
Once created, the following methods can be used to manipulate data inside large objects:
$lobopen() opens a large object (OID) and returns a large object descriptor.
$lobread() reads zero or more bytes from a descriptor into a Binary variable.
To use these methods, it is important to note that large object operations must be performed
within a single transaction, i.e. in manual transaction mode. Any open large object
descriptors are automatically closed upon $commit(). For example:
Do cSess.$transactionmode.$assign(kSessionTranManual)
Do cSess.$begin()
Do cSess.$lobcreate() Returns lOid
;; create new oid
Do cSess.$commit()
Do cSess.$begin()
Do cSess.$lobopen(lOid) Returns fileDesc
Calculate lBinary as 'Some Unicode character data'
Do cSess.$lobwrite(fileDesc,lBinary) Returns lNumBytes ;;write
data into the large object
Do cSess.$lobseek(fileDesc,8,kPgSqlSeekSet) Returns lFilePos
317
For further information on the behavior of these methods and the parameter values that may
be applied, please refer to the Session Methods section above.
PostgreSQL Troubleshooting
The following points may help in resolving programming issues encountered using
PostgreSQL session and statement objects.
$rpcparameters(). When calling $rpcparameters(), the DAM uses defaults for the
column precision and/or scale since this information is not provided by the pg_proc
system table.
For this reason, the API may report parameter-matching problems when calling certain
functions and the list (passed to $rpcdefine()) may need to be manually coerced.
Error Messages. The following additional error messages may be returned via the
session or statement $errortext property:
"Native error text could not be retrieved". No connection currently exists to the server
or there is no message corresponding to the current error code.
"Unsupported client protocol version". The protocol version reported by the client API
is too low. The DAM cannot use this version and you should upgrade to a newer
version of the client library. Use the PostgreSQL access library supplied with Omnis
Studio.
"Client or interface function not available". The most likely cause of this error is that
the client library (or one of its dependencies) was not found and has not been loaded.
Can also occur if the client library being used does not provide a required interface
function.
"server closed the connection unexpectedly. This probably means the server terminated
abnormally before or while processing the request." This error can occur when logging
on with a username other than postgres. The client library uses the username for the
database name unless the database name is specified. Set $database to the required
database name (e.g. postgres) and try again.
Linux Terminal Messages. On Linux, NOTICE and/or WARNING messages are sent
to stderr, (normally the terminal window behind Omnis). To avoid these, refer to the
server configuration parameter: client_min_messages and set his to a higher level.
Chunking and Batch Fetching. Chunking of large character/binary data is not handled
by DAMPGSQL but is handled automatically by the API. Such data is effectively
returned to the DAM as single chunks. $lobthreshold , $lobchunksize and $blobsize
therefore have no effect.
318
SQLite
Batch fetching of data is also not handled by DAMPGSQL. The API automatically
manages transfer of the data and presents the DAM with the entire result set. Hence
setting $batchsize has no effect.
Further troubleshooting notes, how-tos and tips can be found on the Omnis website at:
www.omnis.net/technotes
SQLite
This section contains the additional information you need to access a SQLite database, a
very popular database which is embedded into a whole range of applications on desktop and
mobile devices. The code for SQLite is in the public domain and is thus free for use for any
purpose, commercial or private.
SQLite implements a self-contained, server-less, zero-configuration, transactional SQL
database engine. Unlike most other SQL databases, SQLite does not have a separate server
process. SQLite reads and writes directly to a disk file which can contain multiple tables,
indices, triggers, and views. For more information about SQLite and to download it, please
go to the website: www.sqlite.org (portions of this text are taken from the SQLite website).
The SQLite DAM uses the SQLite v3.0 API which uses a different file format to the v2.8
API. Existing v2.8 datafiles must be converted for use with v3.0. See
http://www.sqlite.org/version3.html) for more details about SQLite3.
This section contains the additional information you need to access a SQLite database,
including server-specific programming, trouble-shooting and data type mapping to and from
the database. For additional information on changes to the SQLite DAM, refer to the
readme file which accompanies your installation media.
Server-specific Programming
Logging on to SQLite
To connect using the SQLite DAM, create an object variable of subtype SQLITESESS.
You connect to a SQLite data file using the $logon() method. The hostname parameter
should be the full path to the data file.
SQLite does not require a username or password, but you can specify a session name that
will appear in the SQL Browser and in the Notation Inspector under $sessions.
SQLite expects a DOS-style pathname under Windows and an absolute POSIX-style path
under OS X and Linux. For example:
Do mySession.$logon(C:\mydata\mydatafile.db,,,session1)
Returns #F ;; on Windows
Do mySession.$logon(/Users/MyUser/mydatafile.db,,,session1)
Returns #F ;; on OS X / Linux
319
Transaction Support
SQLite supports both automatic and manual SQL transactions.
To invoke manual transaction mode, the $transactionmode session property should be set to
kSessionTranManual.
In this mode you must commence each transaction by calling the $begin() session method
and terminating each transaction either by calling $commit(), $rollback(), by switching back
to kSessionTranAutomatic or by logging off.
The SQL text that is submitted each time $begin() is called may be augmented using the
$transactiontype session property as shown below. The different transaction types affect the
way in which SQLite acquires row locks on tables:
$transactiontype
Resulting SQL
text
Meaning
kSQLiteTranDeferred
BEGIN
kSQLiteTranExclusive
BEGIN
EXCLUSIVE
kSQLiteTranImmediate
BEGIN
IMMEDIATE
The $commit() and $rollback() methods, invoke the COMMIT and ROLLBACK
commands respectively.
320
SQLite
$commitmode and $rollbackmode are set to kSessionCommitClose and
kSessionRollbackClose respectively for the SQLite DAM. Statement objects are closed
upon $commit() / $rollback(). Any pending result set is discarded and the statement is
returned to its prepared state ready for re-execution if desired.
321
Session Properties
322
Property
Description
$blobsize
The default value for $blobsize is set at 32KB for the SQLite DAM
since this property is used routinely when creating empty BLOB
columns for use with incremental input/output methods.
$opencreate
If kTrue, the data file specified at $logon() will be created if it does not
exist. If kFalse (the default), an error will be generated if the data file is
not found.
$readonly
$transactiontype
SQLite
Session Methods
Method
Description
$blobbytes()
$blobclose()
$blobcloseall()
$blobhandles()
$blobopen()
$blobread()
$blobreopen()
$blobwrite()
$lastrowid()
$rowsmodified()
323
CHARACTER
Character n
National n
CHAR(n)
NCHAR(n)
NUMBER
Integer 64 bit
Integer 32 bit
Short integer
Number 0..14dp
Short number 0/2dp
Number floating dp
BIGINT
INTEGER
TINYINT
NUMERIC(15, 0..14)
NUMERIC(9, 0/2)
FLOAT
DATE/TIME
Short date 1900..1999
Short date 1980..2079
Short date 2000..2099
Short time
Datetime (all subtypes)
DATE(1900)
DATE(1980)
DATE(2000)
TIME
TIMESTAMP
OTHER
Boolean
Sequence
Picture
List
Row
Object
Object reference
Binary / other
324
BIT
INTEGER PRIMARY KEY (auto increments when
inserted as NULL)
PICTURE
LIST
ROW
OBJECT
OBJECTREF
BINARY
SQLite
SQLite to Omnis
The SQLite DAM recognizes several additional SQL data types in order to maximize
compatibility with externally generated data files as well as those generated by Omnis.
SQLite Data Type
NUMBER
TINYINT
Short integer
Integer 32 bit
Sequence
BIGINT
Integer 64 bit
Number floating dp
DATE/TIME
DATE(1900)
DATE(1980)
DATE(2000)
CHARACTER
CHAR, VARCHAR, TEXT, CLOB,
Character
National
OTHERS
BOOLEAN, BOOL, BIT
PICTURE
LIST
ROW
OBJECT
OBJECTREF
BINARY / other
Boolean
Picture
List
Row
Object
Object reference
Binary
325
Troubleshooting
The following points may help in resolving programming issues encountered using SQLite
session and statement objects.
For additional updated troubleshooting issues, refer to the readme file which accompanies
the installation media.
For a detailed explanation of the SQL syntax supported by SQLite, please refer the SQLite
website: www.sqlite.org
SQLite does not currently support dynamic creation of SQL stored procedures or
functions. The associated methods; $rpcprocedures(), $rpcparameters() & $rpc()
therefore return kFalse.
The SQLite API handles the transfer of binary data automatically. The $blobsize,
$lobchunksize and $lobthreshold properties are therefore ignored.
For performance reasons, journaling mode is set to PERSIST for the SQLite DAM. For
optimum performance, especially on Linux it may be desirable to turn off journaling,
(PRAGMA journal_mode = OFF). Note: in this mode however it will not be possible
to rollback manual transactions.
You may experience slow performance during certain INSERT operations. Each
INSERT and UPDATE operation is normally committed to the disk drive so as to
preserve integrity of the data in the event of a crash or power failure. Executing
"PRAGMA synchronous=OFF" tells SQLite not to wait for data to reach the disk
surface between writes which results in much faster performance. This risks data loss or
corruption in the event of a crash however. Alternatively, you can use manual
transaction mode (kSessionTranManual) to commit several INSERT operations at
once.
326
ODBC
ODBC
This section contains the additional information you need to access a database using ODBC
middleware, including server-specific programming, data type mapping, as well as
troubleshooting. For general information about logging on and managing your database
using the Omnis SQL Browser, refer to the earlier parts of this manual.
Session Properties
Property
Meaning
$dbmsname
$dbmsversion
$defaultdatabase
$drivername
Once a session has been established this is the name of the ODBC
driver that the object is using. This defaults after a $logoff. (Read
only)
$driverversion
$driverodbcversion
$infoaserror
327
328
Property
Meaning
$logontimeout
$programname
$querytimeout
$trustedconnection
$usefiledsn
$uselogonprompt
$useprogramname
ODBC
Property
Meaning
$usequalifiers
$nationaltowchar
Available only with the Unicode DAM. By default, Omnis Character and
National fields are mapped to the SQL_WCHAR, SQL_WVARCHAR
and SQL_WLONGVARCHAR data types. By setting $nationaltowchar
to kTrue only National fields will be mapped to these types (to the
equivalent server data types) and Character fields will be mapped to
SQL_CHAR, SQL_VARCHAR and SQL_LONGVARCHAR as
determined by the Omnis field length. Character fields mapped in this
way are subject to data loss/truncation where such fields contain Unicode
characters. When setting this property, please note that Unicode data
types usually have precision limits half that of their corresponding ANSI
data types. For example, this is 8000 for the SQL Server VARCHAR()
data type but 4000 for NVARCHAR().
$nationaltowchar affects both the text returned by the $createnames()
method and the binding of input parameters.
$datesecdp
$defaultschema
For use with Microsoft SQL Server 2005 and later. $defaultschema
returns the schema name which owns tables created by the current user.
This should be used in place of username in methods such as $tables().
Assigning to this property invokes an ALTER USER statement which
changes the default schema for the user.
A number of additional session properties have been added to the ODBC DAM in Studio
4.3.1 to facilitate better understanding and control of cursors and transactions. Use of these
properties assumes that the session is logged-on and has been placed in manual transaction
mode (kSessionTranManual):
329
330
Property
Description
$autobegintran
$cursorsensitivity
$txncapability
$multipletransactions
(Read Only). Returns kTrue if the driver supports more than one
active transaction at the same time, kFalse if only one
transaction can be active at any time.
$multipleresultsets
$isolationoptions
$isolationlevel
ODBC
Session Methods
Method
Description
$getdrivers()
CompanyName is only obtainable for Win32 and will return as empty for
other platforms. DriverName is obtainable directly from the driver only for
Win32. Other platforms require each driver to be loaded and called in order
to obtain the version string. Hence, there will be a commensurate delay
when calling this method.
Example:
$getdatasources()
Do sessObj.$getdrivers(iDriverList) Returns #F
$getinfo()
331
Description
$setinfo()
$configdsn()
Value
dsnname
but can also include other keywords that are allowed by the driver.
When $uselogonprompt is set to kODBCPromptNever, this prevents
$configdsn() from opening setup dialogues. The DSN is created/modified
silently using values read from the attribute list instead.
Example: Do sessObj.$configdsn(kODBCUserDSN,kODBCAddDSN,
SQL Server,lAttribList) Returns #F
332
ODBC
Method
Description
$getoption()
$setoption()
When the session property $usefiledsn is set to kTrue, this specifies that the hostname
parameter is to be treated as a file data source name by the driver manager.
When the session property $uselogonprompt is set to kODBCPromptComplete, this
specifies that the driver will prompt for missing logon information. Note that not all drivers
support prompting and this may result in the logon failing.
For specific details on connection strings, please refer to the documentation supplied with
the RDBMS or with the ODBC driver.
Transactions
Generally, using manual transaction mode results in increased performance because the
session object does not force a commit after each statement.
If you do not have a result set pending, ODBC session objects will commit each statement if
the transaction mode is automatic. If the transaction mode is server, the session may be
committed depending on the behavior of the ODBC driver.
Dates
The session property $defaultdate allows default values to be added to date values mapped
to the server where the Omnis date value does not contain complete information, e.g. a
Short time mapped to a server date time.
Multiple cursors
To allow multiple select cursors when connecting to Microsoft SQLServer the statement
issuing the SELECT must have the $usecursor property set to kTrue before the statement is
executed. If a statement is issued when $usecursor is kFalse and this statement returns a
result set, this will prevent all other statements in the same session from returning data. The
blocking results must be completely processed or cleared before another result set can be
generated. If a commit or rollback is performed on the session, all the sessions statement
cursors will be closed and all pending results will be lost. Note that a SQLServer cursor
only allows SQL SELECT and EXECUTE procedure commands to be issued.
334
ODBC
When fetching the data into Omnis, the CAST() function can then be used inside the
SELECT statement to ensure that the incoming data gets converted to the proper Omnis
types.
Do myStatement.$execdirect(select CAST(col3 as smalldatetime) from
mytable) returns #F
For this reason, tables containing SQL_VARIANTs are probably best used in tandem with
an index column, which is used to associate a cast type with each row. Since there is no
variant type in Omnis, there is no systematic way of reading a whole column of variants.
Note: text, ntext, image & timestamp types are not supported by SQL_VARIANT.
Custom Data Types
When custom data types are fetched from SQL Server their base type is abstracted from the
custom type and returned to Omnis. For example, if a custom data type is created using;
Do myStatement.$execdirect(EXEC sp_addtype birthday, datetime, 'NOT
NULL') returns #F
Do myStatement.$execdirect(create table test(col1 integer,col2
birthday)) returns #F
335
Omnis can then call the function to obtain the table results, e.g.:
Do mylist.$define(col1,col2)
Do myStatement.$execdirect(select * from Function1(50)) returns #F
Do myStatement.$fetch(myList,kFetchAll)
ODBC Administration
The $getdrivers(), $getdatasources(), $getinfo(), $setinfo(), $configdsn(), $getoption() and
$setoption() session methods (documented above) allow the ODBC DAM to be used to add,
modify and remove ODBC Data Source Names (DSNs) as well as to retrieve and modify
information about ODBC drivers and general ODBC administration attributes.
The $uselogonprompt property has been modified to allow driver prompting to be forced if
required.
All of these methods return a boolean value to indicate successful operation. Errors
generated by these methods are returned as normal via the session objects
$nativeerrorcode and $nativeerrortext properties.
336
ODBC
Execute $logon() with the name of the File DSN as the hostname.
Under Win32, this prompts the ODBC Administrator library to display the driver specific
logon dialogue which prompts for information necessary to make the connection. If the
DAM is successful in logging on, the Administrator library writes the additional information
back to the File DSN, hence modifying the datasource.
To remove a File DSN, you should use the FileOps component to manually delete the
specified filename.
337
ODBC Troubleshooting
The following points may help in resolving issues in programming applications that use
ODBC session objects.
ODBC does not support any extended ORACLE cursor operations such as positioned
update and delete.
You must specify literals in SQL statements with single quotes ('), not double quotes
(").
Some data sources may strip trailing spaces prior to sending it to the session object.
SQL Server behaves in this way.
Further troubleshooting notes, how-tos and tips can be found on the Omnis website at:
www.omnis.net/technotes
338
ODBC
Omnis to ODBC
Omnis Data Type
CHARACTER
Character(n)
National(n)
DATE/TIME
Short date (all subtypes)
Short time
OTHER
Boolean
[1]
SQL_VARCHAR(n)
SQL_CHAR(n)
[1]
SQL_LONGVARCHAR(n)
SQL_CLOB(n) (DB2 only)
[1]
SQL_DATE
SQL_TYPE_DATE
SQL_TIMESTAMP
SQL_TYPE_TIMESTAMP
SQL_TIME
SQL_TYPE_TIME
SQL_TIMESTAMP
SQL_TYPE_TIMESTAMP
SQL_TIMESTAMP
SQL_TYPE_TIMESTAMP
SQL_TINYINT (unsigned)
SQL_SMALLINT
SQL_BIGINT
SQL_CHAR(20)
SQL_INTEGER
SQL_NUMERIC(10,0)
SQL_DECIMAL(10,0)
SQL_FLOAT
SQL_DOUBLE
SQL_NUMERIC(p,s)
SQL_DECIMAL(p,s)
SQL_FLOAT
SQL_DOUBLE
SQL_BIT
SQL_TINYINT
SQL_SMALLINT
SQL_NUMERIC(1,0)
SQL_DECIMAL(1,0)
SQL_CHAR(1)
SQL_VARCHAR(1)
SQL_FLOAT
SQL_VARBINARY(blobsize)
SQL_BINARY(blobsize)
SQL_LONGVARBINARY(blobsize)
SQL_BLOB(blobsize) (DB2 only)
Where blobsize is SessObj.$blobsize
Refer to the $nationaltowchar property for use with the Unicode version of Omnis Studio
339
ODBC to Omnis
ODBC Data Type
CHARACTER
SQL_CHAR(n)
SQL_VARCHAR(n)
SQL_LONGVARCHAR(n)
SQL_WCHAR(n)
SQL_WVARCHAR(n)
SQL_WLONGVARCHAR(n)
SQL_CLOB(n)
DATE/TIME
SQL_DATE
SQL_TYPE_DATE
SQL_TIME
SQL_TYPE_TIME
SQL_TIMESTAMP
SQL_TYPE_TIMESTAMP
NUMBER
SQL_DECIMAL(p,s)
SQL_NUMERIC(p,s)
SQL_SMALLINT
SQL_TINYINT (unsigned)
SQL_TINYINT (signed)
SQL_INTEGER
SQL_BIGINT
SQL_REAL
SQL_FLOAT
SQL_DOUBLE
SQL_BIGINT
OTHER
SQL_BIT
SQL_BINARY
SQL_VARBINARY
SQL_LONGVARBINARY
SQL_BLOB
SQL_GUID
SQL_VARIANT
Custom Data Types
Table Type
340
Number (s)dp
Integer 32 bit
Short integer
Integer 32 bit
Integer 32 bit
Integer 64 bit
Number floating dp
Character 20
Boolean
Binary
Binary
N/A
N/A
JDBC
JDBC
This section contains the information you need to access a database using the JDBC object
DAM and JDBC drivers (plus their associated middleware where applicable), including
server-specific programming, data type mapping and troubleshooting. For general
information about logging on and managing your database using the SQL Browser, refer to
the earlier parts of this manual.
Minimum Requirements
To use the JDBCSESS object the client machine must have the Java Runtime Environment
v1.4 or higher installed. In addition, the JDBCSESS object will only support JDBC 2.x
certified drivers. The JDBC DAM utilises the Omnis Java Engine (OJE), so it is important
that the requirements for the OJE are also met. In particular a JVM_PATH environment
variable must be set to the path of the JVM library in order for the OJE to start the Java
Virtual Machine.
Session Properties
Property
$dbmsname
$dbmsversion
$drivername
$driverversion
$logontimeout
$querytimeout
Meaning
Once a session has been established this is the type of database that
the object is connected to. This defaults after a $logoff. (Read only)
Once a session has been established this is the version of the
database software that the object is connected to. This defaults after
a $logoff. (Read only)
Prior to a session being established this should be set to the name of
the JDBC driver that the object wishes to use in order to establish a
connection. This can also be set using the $setdriver() method.
Once a session has been established this is the version of the JDBC
driver that the object is connected to. This defaults after a $logoff.
(Read only)
The timeout in seconds for a $logon call. The default is 15 seconds.
A value of 0 represents no timeout.
The timeout in seconds for a query. A value of 0 represents no
timeout, which is the default.
341
Session Methods
Property
$setdriver()
Meaning
$setdriver(drivername) sets the JDBC driver that the session
object should use to establish a connection. This is the same as
assigning a name to $drivername.
Failure to perform this step will cause the $logon() to fail. In order for the specified JDBC
driver to be successfully loaded, it must exist in the system CLASSPATH environment
variable.
To log on to the database using the SessObj.$logon() method, the hostname must contain
the database URL required by the specified driver. The user name and password should
contain the values required by the database.
Transactions
Generally, using manual transaction mode results in increased performance because the
session object does not force a commit after each statement.
If you do not have a result set pending, JDBC session objects will commit each statement if
the transaction mode is automatic. If the transaction mode is server, the session may be
committed depending on the behavior of the JDBC driver.
Dates
The session property $defaultdate allows default values to be added to date values mapped
to the server where the Omnis date value does not contain complete information, e.g. a
Short time mapped to a server date time.
Multiple cursors
To allow multiple select cursors when connecting to Microsoft SQLServer, the statement
issuing the SELECT must have the $usecursor property set to kTrue before the statement is
executed. If a statement is issued when $usecursor is kFalse and this statement returns a
result set, this will prevent all other statements in the same session from returning data. The
blocking results must be completely processed or cleared before another result set can be
342
JDBC
generated. If a commit or rollback is performed on the session, all the sessions statement
cursors will be closed and all pending results will be lost.
343
Omnis to JDBC
Omnis Data Type
CHARACTER
Character(n)
National(n)
DATE/TIME
Short date (all subtypes)
Short time
Date time (#FDT)
NUMBER
Short integer (0 to 255)
Sequence
Integer 32 bit
Integer 64 bit
Short number 0-2dp
Number floating dp, 0..14 dp
OTHER
Boolean
344
JDBC
JDBC to Omnis
JDBC Data Type
CHARACTER
CHAR(n)
VARCHAR(n)
LONGVARCHAR(n)
CLOB(n)
DATE/TIME
DATE
TIME
TIMESTAMP
NUMBER
SMALLINT
INTEGER
BIGINT
DECIMAL(p,s)
NUMERIC(p,s)
REAL
FLOAT
DOUBLE
OTHER
BIT
BINARY
VARBINARY
LONGVARBINARY
BLOB
Boolean
Binary
345
Dependencies
The Amazon DAM has runtime dependencies on several other dynamic libraries which
must be present on your systems library search path before the DAM can be used. When a
DAMAZON session object is created, the DAM attempts to locate and resolve the symbols
it needs from each of the external libraries.
If one or more symbol references cannot be resolved, these are reported to the Omnis trace
log as warnings, $logon() is disabled and you should not attempt to call session or statement
methods, otherwise a crash may occur.
The additional files required by the Amazon DAM for each platform are as follows:
Windows
libcurl.dll (requires msvcr90.dll)
libeay32.dll (requires msvcrt.dll)
libxml2.dll (requires iconv.dll & zlib1.dll)
OS X
libcurl.dylib (where libcurl.dylib -> /usr/lib/libcurl.4.dylib, for example)
libcrypto.dylib (where libcrypto.dylib -> /usr/lib/libcrypto.0.9.7.dylib, for example)
libxml2.dylib (where libxml2.dylib -> /usr/lib/libxml2.2.dylib, for example)
346
Logging on to SimpleDB
To connect to SimpleDB, the endpoint required is supplied via the $logon() hostname
parameter. In the case of Amazon SimpleDB, the endpoint is sdb.amazonaws.com or
sdb.eu-west-1.amazonaws.com in Europe.
Your access key id and secret are supplied via the username and password parameters, for
example:
Do SessObj.$logon(sdb.amazonaws.com, AGIBJ5LOYFITD3BR7,
H/z6t3ARzuJL26uIE07 GTS1AkK+p5) Returns #F
For other databases, the endpoint may be specified using http syntax, for example:
Do SessObj.$logon(
http://www.remoteserver.com/?,user_1,password) Returns #F
If the hostname parameter is omitted, i.e. substituted with a comma, the DAM uses
sdb.amazonaws.com by default.
347
Meta Data
SimpleDB does not provide information about tables, columns and indexes in the same way
as traditional relational databases. Instead, domains can be likened to tables, items can be
likened to rows and attributes can be likened to columns. This has an impact on the
behavior of the following meta-data methods:
$tables()
$columns()
$indexes()
ItemCount
AttributeNameCount
AttributeValueCount
ItemNamesSizeBytes
AttributesValuesSizeBytes
AttributeNamesSizeBytes
Item
Attribute
Value
Suits
Colour
Navy
Suits
Colour
Black
Suits
Colour
Grey
In addition, SimpleDB effectively supports only a single data type: Character. All data
inserted into and retrieved from SimpleDB will be character data optionally encoded as
UTF-8 bytes. Once fetched into Omnis, data can be assigned to typed variables as required.
Such data will be automatically converted to the appropriate data type where possible.
348
Creating a Domain
To manually create a domain (analogous to a table), use the StatObj.$createdomain()
method. For example:
Do StatObj.$createdomain(Project810) Returns #F
Inserting Data
To insert items and attributes into SimpleDB, use the StatObj.$putattrib() method.
Each call to $putattrib() inserts a new attribute-value pair into the specified domain item.
(There is no need to create the item before inserting an attribute, the item is created
implicitly). Since SimpleDB supports multiple attribute values, you can assign several
different values to the same attribute if required. Duplicate values are ignored. For example:
Do StatObj.$putattrib(Project810,Materials,Tools,13mm
Wrench) Returns #F
Do StatObj.$putattrib(Project810,Materials,Tools,Quick
release clamps) Returns #F
If many attributes are to be inserted, it may be preferable to assign the domain name to the
StatObj.$domain property and the item name to the StatObj.$item property. These
parameters can subsequently be omitted in calls to $putattrib()- and any of the other
statement methods discussed below. The above example becomes:
Do
Do
Do
Do
StatObj.$domain.$assign(Project810)
StatObj.$item.$assign(Materials)
StatObj.$putattrib(, ,Tools,13mm Wrench) Returns #F
StatObj.$putattrib(, ,Tools,Quick release clamps) Returns #F
349
Deleting Data
To delete items, attributes and values from SimpleDB, use the StatObj.$delete() method.
Deleting Values
To delete a specific attribute value, the domain, item, attribute name and value should be
specified. For Example:
Do StatObj.$delete(Project810,Materials,Timber,50x50x2.4m
pse) Returns #F
Deleting Attributes
To delete an attribute including all of its values, the domain, item and attribute name only
should be specified. For example:
Do StatObj.$delete(Project810,Materials,Timber) Returns #F
Deleting Items
To delete an entire item including all its attributes and values, the domain and item name
only should be specified. For example:
Do StatObj.$delete(Project810,Materials) Returns #F
Deleting a Domain
StatObj.$delete() cannot be used to delete a domain. To do this- use
StatObj.$deletedomain(). This method should be used with caution as it will permanently
delete all items, attributes and values contained in the domain before removing the domain
itself. For example:
Do StatObj.$deletedomain(Project810) Returns #F
Replacing Data
Whereas $putattrib() is used to append new attributes and values, StatObj.$replaceattrib() is
used to replace all values for a specified attribute with the supplied single value. For
example:
Do StatObj.$replaceattrib(Suits,Gents Formal Suit,Colour,Navy
only) Returns #F
Fetching Data
The Amazon DAM uses Amazon SELECT statements to fetch multiple items. These are
issued using the statement objects $prepare(), $execute() and $execdirect() methods in a
similar way to traditional SQL SELECT statements. The general form of a SimpleDB
SELECT statement is as follows:
select output_list from domain_name [where expression]
[sort_instructions][limit limit]
350
Retrieving an Item
You can retrieve all attributes for a specific item using the StatObj.$getall() method. The
result set (a single row) generated by this call is returned using $fetch(). For example:
Do StatObj.$getall(Suits,Gents Suits) Returns #F
Do StatObj.$fetch(lvRow)
Retrieving an Attribute
You can retrieve the contents of a specific attribute using the StatObj.$getattrib() method.
The result set (a single row containing a single column) generated by this call is also
returned using $fetch(). For example:
Do StatObj.$getattrib(Project810,Materials,Tools) Returns #F
Do StatObj.$fetch(lvRow)
351
myList.$define(lvChar1, lvChar2)
myList.$add(Tools,Posidrive screwdriver)
myList.$add(Tools,Metal hammer)
myList.$add(Charges,1 hours labour)
StatObj.$putmany( , , myList) Returns #F
You can retrieve the values of multiple attributes using the StatObj.$getmany() method. The
attribute names to be retrieved are supplied via a single-column list, for example:
Do
Do
Do
Do
Do
myList.$define(lvChar1)
myList.$add(Tools)
myList.$add(Materials)
myList.$add(Charges)
StatObj.$getmany( , , myList) Returns #F
Each subsequent call to $fetch() returns a row containing separate attribute- either as a
comma-separated-value or as a single column list, as dictated by $attribcsv.
352
cSess.$begin()
cStat.$putattrib(,,'Materials','White Paint') Returns #F
cStat.$putattrib(,,'Materials',Cement 25Kg) Returns #F
cStat.$replacemany(,,lvAttribList) Returns #F
cStat.$execdirect(select * from Project810') Returns #F
cSess.$commit() Returns #F
353
Machine Utilization
Amazon SimpleDB measures usage of remote resources (and hence the charge it imposes
on the end-user) in terms of box usage. Each action sent to the database incurs a box
usage- quoted as a decimal fraction of one hour. StatObj.$boxusage returns the box usage
for each action which generates a response.
The session object also has a $boxusage property which accumulates a total box usage for
the open connection. When retrieving multiple responses, the box usage for each response is
received (and added) in turn.
$boxusage may not be supported by all Simple databases in which case, the value remains
set to zero.
Read Consistency
Amazon SimpleDB supports two types of read consistency, defined as follows:
Eventually Consistent Reads
the eventual consistency option maximizes your read performance (in terms of low
latency and high throughput). However, an eventually consistent read (using Select or
GetAttributes) might not reflect the results of a recently completed write (using
PutAttributes, BatchPutAttributes, DeleteAttributes). Consistency across all copies of
data is usually reached within a second; repeating a read after a short time should return
the updated data.
Consistent Reads
in addition to eventual consistency, Amazon SimpleDB also gives you the flexibility
and control to request a consistent read if your application, or an element of your
application, requires it. A consistent read (using Select or GetAttributes with
ConsistentRead=true) returns a result that reflects all writes that received a successful
response prior to the read.
The Amazon DAM implements this functionality using the $consistentread session
property. When set to kFalse (the default setting), the eventual consistency option is used.
When set to kTrue, all $getattrib() and SELECT statement results are fetched using
consistent reads.
354
Once bound, variable values should be assigned before each call to $putattrib(), $delete(),
etc:
Do cStat.$whereclause.$assign(where Name = @[lvChar])
Calculate lvChar as Brookes
Do cStat.$putattrib(StockDB,Supplier1,Frequency,Daily)
Returns #F
Calculate lvChar as Robinson
Do cStat.$delete(StockDB,Supplier2,Frequency) Returns #F
Currently, the exists condition may only be specified if both <name> and <value> attributes
are also specified. To use does not exist, only the <name> attribute should be specified.
Subsequent calls to put, replace or delete attributes return kFalse if the condition is not met.
$whereclause is not affected by $clear(). To remove the where condition for a statement
object; assign $whereclause to an empty string.
355
Session Properties
Property
Meaning
$boxusage
$consistentread
If set to kTrue, all read operations (e.g. $getattrib() & $fetch()) are
executed guaranteeing that the results of recent updates are seen
immediately. If set to kFalse, the default (faster) eventual consistency
option is used.
$responses
$transactionmode
Session Methods
356
Method
Description
$begin()
$commit()
Statement Properties
Property
Meaning
$attribcsv
If set to kTrue (the default), attributes with multiple values are returned
as comma-separated values, i.e. the fetched row will be defined with
character columns. If set to kFalse, attributes will be returned as single
column lists, i.e. the fetched row will contain a single column list in
each column.
$boxusage
$domain
The current domain name. $domain will be used with various statement
methods if set. Statement methods which require a domain parameter
will assume this value if the method parameter is omitted.
$endofresponse
Returns kTrue if the last item/attribute of the current response has been
fetched in which case, $boxcount, $itemcount and $columncount are set
to reflect the next response. Read-only.
$item
The current item name. As with $domain, $item will be used with
various statement methods if set. Statement methods which require an
item name will assume this value if the method parameter is omitted.
When retrieving an item list from the database, $item is also set to the
name of the last item to be fetched.
$itemcount
Returns the number of items in the current response. Returns zero if the
response contains only attribute information. Read-only.
$resultspending
$whereclause
Affects all put, replace and delete attribute methods. This property
accepts a SQL-style where clause of the form:
where <name> [= <value>] [exists|does not exist]
<name> and <value> can be literal values; in which case they must be
double-quoted, or bind variables. Double quotes inside literal values
should be escaped using \
357
Statement Methods
358
Method
Description
$createdomain()
$delete()
$deletedomain()
$deletemany()
$getall()
$getattrib()
$getitems()
$getmany()
Description
attribute names are supplied via lAttribs, which should be defined with
a single character column. The result of the query is retrieved by calling
StatObj.$fetch(). Returns kTrue on success, kFalse otherwise.
$putattrib()
$putmany()
$replaceattrib()
$replacemany()
Implementation Notes
Bind Variables
Queries issued using $execute() and $execdirect() may contain bind variables- for example
in the where clause of the SELECT statement. The DAM inlines variable values into the
SQL text each time $execute() is called, placing single quotes around each value. Values
containing single quotes are escaped by adding a second single quote for each occurrence.
For example:
Calculate lVar as Katharine OHara
Do StatObj.$execdirect(select * from Customers where Name
@[lVar]) Returns #F
becomes
select * from Customers where Name = Katharine OHara
Remote Procedures
SimpleDB does not support remote procedures, views or triggers. These are features of
traditional relational databases.
Binary Data
SimpleDB attributes support only character data of maximum length 1024 bytes and are not
suitable for storing binary data directly. A better approach (the intended approach) is that
attribute values be used to store URLs or unique identifiers for pictures, files and other
media which exist externally to the database.
360
Chapter 10Report
Programming
You can create many different types of report using a template or wizard, each with very
different layouts and data handling capabilities. With reports you can print out all or a
subset of your data, and collect up data from different sources and print it on a single report.
Each type of report in your application is defined as a report class. This chapter describes
report classes and report sections and their properties.
Reports can contain data fields, pictures, text, and graphics. You can also place graphs on
your reports, or base a report on an Omnis list. On the Omnis fat client, you can print
reports to a number of destinations, including the current printer, the screen, a file, a port,
the clipboard, or for the JavaScript Client you can print to a PDF file and display it in the
end users web or mobile browser.
361
Report Wizard
The SQL report wizard lets you create a report that contains fields that map directly to a
SQL class in your library, which lets you print data on your SQL server database. Before
you can use report wizards you must create the schema, table, or file classes necessary for
SQL.
To create a new report using a wizard
Click on the Class Wizard option, then click on the Report option
Select the report SQL Report wizard and click on the Create button
For SQL reports you need to select the Session to be associated with the new report. The
SQL report wizard creates a report based on a schema or query class; each separate field on
the new report maps to a schema column, which in turn maps to your server database
Note: there is an Omnis Report Wizard which creates a report based on an Omnis file
class which is only suitable for storage in an Omnis datafile.
When you finish in the Report Wizard the new report class is opened ready for you to
modify or print. To modify your report you need to edit its properties. You can also add
new report objects from the Component Store, and you can add methods to the report class
or the objects on the report.
Report Tools
The toolbar at the top of the report editor lets you set the page size, preview the report on
screen, and show or hide connections between the different sections of the report as shown
down the left-hand side of the report editor. In addition, you set the sort levels in your report
from this toolbar. Position your mouse over each tool to see what it does.
Some of the options in the report editor toolbar are available using the report context menu
by Right-clicking on the report background.
The Narrow Sections option displays the section markers as narrow lines which shows you
how the report will look when you print it. The Show $ident displays the ident numbers for
the fields and section markers in the report. The Field List option displays a list of fields
and section markers in the report class. You can expand the tree in the Field list to show the
fields within each report section.
362
Report Sections
The Class Methods option lets you add methods to the report class, and the Properties
option shows the properties for the class. The Page Setup option or toolbar button opens the
Page Setup dialog in which you can select the printer, and set the page size and orientation.
This dialog will vary greatly across the different operating systems.
Report Sections
Sections are horizontal markers or dividers across the report class that structure and position
the data when your report is printed. To create a complex report with headers, footers,
subtotals, and totals, such as an invoice or catalog listing, you have to place the appropriate
sections in your report class in the right order. When you enable the various sections in your
report using the Property Manager, their position and order is handled for you
automatically.
There are two sections that you must have in a report: the Record section indicates the start
of the display of records or rows of data, and the End of report section indicates the end of
the report. These sections appear automatically in every new report class.
The following section types are available.
Report heading
Page header
Subtotal heading
Subtotal heading 1 to 9
Record
Positioning
Subtotals level 1 to 9
Totals
Page footer
End of report
364
Report Sections
Watermarks
You can add a watermark effect to your reports by assigning a picture to the $backpicture
property of the report. The alignment can be one of the following:
TopLeft
TopCenter
TopRight
CenterLeft
Center
CenterRight
BottomLeft
BottomCenter
BottomRight
Stretch
Tiles
The horizontal and vertical DPI (dots per inch) specify the resolution at which the image is
to be printed.
When using notation, $backpicture refers to the binary representation of the image and the
formatting properties. To change the image or formatting properties you can use
$backpicture.$picture or $backpicture.$align. The full set of notation is as follows:
$backpicture.$picture
$backpicture.$picturealign
$backpicture.$horzdpi
$backpicture.$vertdpi
$backpicture.$horzoffset
$backpicture.$vertoffset
365
Section Positioning
When you print a report, each section follows the previous section by default, and is
positioned down the page according to the height of the previous section set in the report
class. However for some types of section, you can control where a section prints and
whether or not a new page is forced using the pagemode and startmode properties of the
section. You can use a special type of section marker called a position section to print part
of your report literally anywhere on the page. To do all these things you have to modify the
properties of the appropriate section marker.
To view the properties of a section, open your report class in design mode and click on the
appropriate section to view its properties in the Property Manager.
Page Mode
You can control whether or not Record, Subtotals, Totals, and Subtotal heading sections
start a new page when they are encountered by setting their pagemode property. You can
select one of the following options for this property.
Nopage
does not force a new page; uses the pagination in the report class (the default)
Newpage
always starts a new page before this section
Testspace
starts a new page before starting this section if there is not the specified amount of
space available on the current page
If you select the Testspace option, the pagespacing property is enabled in the Property
Manager in which you can enter the amount of space required for the section. If this amount
of space is not available on the page, a new page is started. The figure you enter in
pagespacing is shown on the section marker.
Omnis works with units that are 1/72 of an inch; therefore it may round exact numbers in
centimeters or inches to the next real unit. For example, 1cm becomes 0.99cm.
Start Mode
All sections except for Page footer and End of report let you specify the startmode, which
tells Omnis where to start the section. You can choose one of the following options.
Follow previous section
starts the section on the line following the end of the previous section (the default)
Fromtop of previous section
starts the section n inches/cms from the top of the previous section
366
Section Positioning
Fromend of previous section
starts the section n inches/cms from the end of the previous section
Fromtopmarg
starts the section n inches/cms from the top margin of the report
Frombottommarg
starts the section n inches/cms from the bottom margin of the report
When you choose one of the start modes the startspacing property is enabled in the
Property Manager, which lets you enter a measurement for the startmode. The startmode
and spacing is shown on the section marker.
Omnis ignores previous section settings if the previous section was a Page header section
or a Positioning section within a Page header section. The spacing comes before the page
start test that examines the amount of space left on a page. Omnis ignores top and bottom
margin settings for reports that are not paged.
Note that when you set up a report to print labels, you can use the Fromtop or Frombottom
options to set the spacing between your labels.
You can enter a negative value for the start spacing of a positioning section, for example
Start 1.000cms from end of previous section. This allows you to align fields with the
bottom of an extending field.
Record Spacing
The default spacing between records or rows of data on your printed report is determined by
the height of the Record section in your report class. However you can override this spacing
by setting the userecspacing property for the Record section. This property forces the
report to use the vertical spacing set in the recordspacing property of the report class.
Position Sections
A Position section is a special type of report section that you can print literally anywhere in
the report. For example, using a positioning section, you could print a footnote or a logo at
the bottom of a letter, regardless of the content or amount of data in the main report letter.
A positioning section placed over the second line of a two-line extending field with the
Follow previous section property prevents the second line from printing as a blank. You can
also follow extending fields by a positioning section with Follow previous section to
prevent them from writing over any fields below. A positioning section within a subtotal
section lets you trigger a print position change by changing a sort field value.
Section Calculations
Sections have the $printif property which can trigger the section to print based on a
calculation. If a section has a calculation, it is skipped if the calculation evaluates to zero,
otherwise the section is printed as normal. If a section has been given a calculation, the text
Print if calculation will appear in the section bar.
If a main section is skipped, all positioning sections belonging to the main section are also
skipped, regardless of their $printif property. Calling $printsection from a method will
ignore the $printif calculation and always print the section.
Custom Sections
A custom section is effectively a positioning section with $printif calculation of 0. This
means the section will not print unless, $printsection() is called with a reference to the
section. You can add a custom section from the Component Store.
Custom sections can be placed inside any of the main sections, but can be printed before or
after any of the other report sections, but not during. Changing the $printif calculation to
anything other than 0, will change the section into a normal positioning section, and vice
versa.
368
Subtotal Sections
You can specify a Subtotal heading section in your report. It prints before the first Record
section and successive Record sections following each Subtotals section. The subtotal
heading can print column names and anything else you want to apply to each subtotaled
Record section.
The Subtotals section prints whenever the Record section breaks on the corresponding sort
field, with the subtotal printing before the record with the changed value. Since there are up
to nine sort fields, you can have up to nine Subtotal heading and Subtotal levels numbered 1
through 9 corresponding to the sort fields specified in the report. The higher numbered sort
fields are nested within the lower ones and hence change more often. That is, sort field 5
changes within sort field 4 which changes within sort field 3, and so on. Correspondingly,
the Subtotal heading and Subtotals sections with higher numbers print more often as the sort
fields change.
When you have multiple subtotals which print consecutively, the corresponding heading
sections print one after another, starting with the one for the last subtotal. Subtotals and
totals can be aggregations of several kinds, including sums, averages, counts, minimums, or
maximums, depending on the fields totalmode property. Omnis maintains the total for
each subtotal printing, then resets the subtotal to zero for the next section.
The Totals section prints at the end of the report. As for subtotals, you place the fields to
aggregate in this section, and Omnis accumulates the aggregate values across the entire
report. You can set the totalmode property for a field in the totals section.
370
Printing Reports
Printing Reports
Omnis provides a wide range of choices for printing your reports, including sending your
report to the printer, the screen, to a page preview, to a text or HTML file. End users can set
the report destination using the File>>Print Destination menu option. In your finished
library, you can provide a menu, popup menu, or toolbar button to print your report to the
required destination. There are a number of commands that let you set the print destination,
including Send to screen, Send to file, and Send to clipboard.
While you are creating your report class you may need to print it to try it out. You can use
one of the buttons on the report editor toolbar to print the current report class. From these
tools you can print to the current printer, a page preview window, or to the screen.
371
Printer
The Printer option sends the report to the current printer. Under Windows, selecting the
printer as destination opens a list of installed printers, and changing to a new printer does
not affect the default printer setup as defined in the Windows Control Panel. Note that you
can change the page setup with the File>>Page Setup menu item.
Preview
The Preview option displays a full page on the screen. Text is Greeked if the screen size
is too small, dots representing the characters so that the whole page fits the available screen
area.
Screen
The Screen option is the default report destination at startup. It displays the report on the
screen without the normal page margins. You can have more than one screen/page preview
report open at a time. When you display reports on the screen, you can use the horizontal
and vertical scroll bars to view the report, and the Page up, Page down, and arrow keys as
well.
Omnis displays a screen report window as soon as it has prepared the first page of data, that
is, normally it does not wait for the report to finish. Therefore as you scroll a long report it
may take a few seconds to print each page.
Screen and Preview toolbars
Screen and Preview reports have a toolbar at the top of the window to allow end users to
print the report to the current Printer or Save the report to a file.
The Omnis root preferences $reporttoolbarscreen and $reporttoolbarpagepreview (in the
$root.$prefs devices group) allow you to select the buttons on the Screen report and
Preview toolbar for user reports.
372
Printing Reports
Copying from Screen and Preview reports
You can copy graphics in Windows metafile, bitmap or Macintosh PICT format from the
screen and page preview report window by selecting an area with the mouse and using the
Edit>>Copy menu item. You can copy text in the same way, and you can select and copy
more of the report than is displayed on screen. When you drag-and-select data in your
report, the window will scroll. The Select All option in the edit menu selects the whole
report.
The Omnis root preference $disablereportcopy (in the $root.$prefs devices group) allows
you to disable the copy via selection feature of screen reports and page previews for user
reports.
Disk
The Disk file report device sends the report output to a file on disk in a cross-platform
binary format. If you double-click on the Disk icon in the Report Destination dialog Omnis
prompts you for a disk file name.
You can print to the Disk device on one platform, reload the file in Omnis and print it on
another platform. Alternatively, you can print the output from the Disk device using the
File>>Print Report From Disk menu option, or using the Print report from disk command.
Clipboard
The Clipboard option sends the current report to the clipboard as an unpaged, text-only
report suitable for pasting as text into other applications.
Port
The Port option sends the current report to a Unix or Windows serial or parallel port, or a
Mac OS Modem or Printer port specified in the Parameters pane (Note: Serial ports are not
supported on Mac OS X). This device also uses the settings in the Page sizes pane: see the
File device.
Only one program can have a particular port open; if a port is open in Omnis and it is also,
for example, the port used by the Spooler, then the Spooler will not be able to function.
Under Mac OS, there is an option on the Parameters pane to Convert for Imagewriter. When
selected, the characters beyond ASCII 127 convert to a combination of a character,
backspace, and accent character so that the report can print accented characters and
umlauts.
If you are using a G3 or G4 Macintosh, you will not see any serial ports displayed in the
Parameters panel. This is because the latest Macintoshes do not have serial ports. However,
it is possible to connect a serial adapter to the USB port of either a G3 or G4. Once the
drivers for your serial adapter are installed correctly, Omnis Studio will automatically
recognise any new serial ports when you plug the adapter into your machine. Any new serial
ports that are discovered will be displayed in the parameters panel for you to select.
373
File
The File print destination sends the current report to a file. If you double-click on the File
icon in the Report Destination dialog Omnis prompts you for a file name. Omnis does not
close the file at the end of the report so you can append multiple reports into a single file.
This option enables the Page sizes pane in the Report Destination dialog.
In the Page sizes pane you can specify the number of lines per page to use in reports printed
to a file or a port. Omnis stores the setting in the Omnis configuration file.
If you check the Generate paged reports check box, you can also check the Send form feed
check box, which tells Omnis to terminate pages with a form feed, or fill in the Line per
page field with a number of lines to which to pad out each page. Checking the Restrict page
width option lets you enter the number of Characters per line.
RTF
The RTF print device sends the current report to an RTF file. If you double-click on the
RTF icon in the Report Destination dialog Omnis prompts you for a file name. You can also
set the file name under the Parameters pane in the Report Destination dialog, as well as
control the how images are embedded or linked. The default behavior is to embed images in
the RTF file, but you can link the images in which case any images are stored as separate
files and linked to the RTF file; you can also ignore the images altogether.
HTML
The HTML report device is a custom device that prints a report to an HTML file on disk.
When installed and loaded it appears in the print destination dialog and behaves like any
other standard printing device. You can send any Omnis report to the HTML device and
access and change the device using the notation. If you double-click on the HTML icon in
the Report Destination dialog Omnis prompts you for a file name.
The HTML printing device uses HTML tables and standard HTML tags to position and
structure the output of the Omnis report. The default background color of the HTML file is
white. The color of the text in the original report class is retained in the HTML output file.
Where possible, the device converts any image or picture data into JPEG images, which are
written to disk and linked to the output HTML file.
Memory device
The Memory device lets you send a report to a binary variable or field, which you can hold
in memory or save in a database. At a later date you can reload the contents of the binary
variable or field and print the report to the printer or any other destination.
374
You can print the output from the Memory device using the Print report from memory
command.
DDE/Publisher Device
The DDE/Publisher lets you send a report via DDE under Windows, or to an edition under
Mac OS.
You can access the DDE/Publisher device using the notation only via the $root.$devices
notation group. By default this device is not shown in the Print Destination dialog, but you
can show it using the following method:
Do $root.$devices.Memory.$visible.$assign(kTrue)
Printing Errors
The print manager reports the following error codes and text. You can setup error handlers
to manage these errors.
1001650
1001670
1001680
Print manager system error; the code is shown in the error text
1001681
Right-click in the method list in the method editor and add your method
Right-click in the method list in the method editor and add your method
The next section in this chapter describes the type of methods you can add to report classes
and objects.
376
$cdevice
the current printing device or report destination. You can change $cdevice by assigning
a device from the $devices group, for example, to specify the screen as the current
device use one of:
Calculate $cdevice as kDevScreen
Calculate $cdevice as $devices.Screen
Calculate $cdevice as $devices.$findident(kDevScreen)
Print Devices
The $root.$devices group contains the currently installed printing devices plus any custom
devices you may have installed. A device has the following properties; $canassign for these
properties is true unless specified.
$name
the name of the device; $canassign is false
$title
the string used to identify the device in the Print destination dialog
$iconid
the id of the icon for the device as displayed in the Print destination dialog, zero by
default which means the device uses the default icon
$ident
a unique numeric identifier for the device in the $devices group; $canassign is false
$visible
if true, the device is shown in the Print destination dialog
$isopen
returns true if the device is open and in use; $canassign is false
$istextbased
returns true if the device is text-based, otherwise, the device is image-based, such as
Printer, Screen, or Preview; $canassign is false
377
$cangeneratepages
this is a read only property. If it returns true, the device can generate pages and all
normal page headers and footers will be printed. If it returns false, only the report
header and first page header are printed. No footer section is printed.
$cankeepopen
returns true if the device can be kept open for long periods of time, such as the File
device; otherwise, the device should be opened prior to printing and closed
immediately after printing has finished, for example you must do this for the Printer;
$canassign is false
You can use the following methods for a device; $cando() returns true if a device supports
the method.
$open()
opens the device ready for printing or transmitting text or data. Some devices such as
the Screen or Preview can only be opened from a print job when printing a report
$close()
closes the device, if the device is open
The following example prints two reports in the same print job, and uses the $open() and
$close() methods to initialize the Printer.
Set reference theDevice to $devices.Printer
If theDevice.$isopen
;; check if printer is in use
If theDevice.$canclose()
Do theDevice.$close()
Else
Quit method kFalse
;; if device cant be closed
End if
End If
Do theDevice.$open() Returns ok
;; open the printer
If ok
;; print the reports
Set report name reportOne
Print report
Set report name reportTwo
Print report
Do theDevice.$close() Returns ok
;; close the printer
End If
$canclose()
returns true if the device can be closed. If you opened the device using $open(), this
method returns true; if you opened the device via a print job and the job is still in
progress, it returns false
378
$senddata( cData[,cData1] )
sends the specified data in a binary format to the device; no character conversion takes
place unless the data is of type kCharacter. If more than one parameter is specified the
data is sent in individual packets
When using the $senddata() method you must consider type conversion. The method
expects binary data, and therefore any data which is not in a binary format is converted to
binary. For example, if you pass an integer variable, the data is converted to a 4 byte
binary. In some cases, due to cross platform incompatibilities, if you want to be certain of
the order in which the data is sent, and of the values which are sent, you should use
variables of type Short integer (0 to 255), for example
Calculate myShortInt1 as 13
Calculate myShortInt2 as 10
Do myDevice.$senddata( myShortInt1, myShortInt2 )
You can send raw data to the Port or File device. The following example prints a report to a
binary variable and sends the binary data to the Port device.
379
$flush()
flushes the device. For the File device $flush() will ensure all data is written to disk;
you can safely call $flush() for devices which do not support this method; $cando()
returns true for all devices that support $senddata() or $sendtext()
380
$cdevice.$assign(kDevScreen)
$prefs.$windowprefs.$assign(MyTitle/20/20/420/520/CEN)
$prefs.$waitforuser.$assign(kFalse)
$prefs.$hideuntilcomplete.$assign(kTrue)
$charsperinch
the number of characters per inch when printing to a text-based device
$linesperinch
the number of lines per inch when printing to a text-based device
$generatepages
if true, reports generate paged output when printing to text-based devices, that is, page
headers and footers are generated as normal; otherwise if false, only one report header
and page header is printed at the beginning of the report
$linesperpage
the number of lines per page when $generatepages is true
$restrictpagewidth
if true, the width of a page is restricted when printing to text-based devices
$charsperline
the number of characters per line when $restrictpagewidth is true
$sendformfeed
if true, form feeds are sent to text-based devices after each page
$appendfile
if true, data is appended to the current print file specified in $printfile, otherwise if
false, the file is overwritten when printing to the File device; note if the device is
already open prior to printing a report, the file is appended to regardless
381
There is also a group of Page setup properties under $root.$prefs giving access to the global
page settings. These are
$orientation
the page orientation; this can be kOrientDefault, kOrientPortrait, or kOrientLandscape
$paper
the paper type, a constant; one of 50 or so paper sizes or types including US Letter,
European A sizes, envelope sizes, custom sizes, and so on
$paperlength
the length of the paper in cms or inches depending on the $usecms preference
382
Report Instances
$paperwidth
the width of the paper in cms or inches depending on the $usecms preference
$scale
the scaling factor in percent
$copies
the number of copies
The Omnis root method $getprinterlist() allows you to get a list of printers available to the
current user. For example, the following method will return a list of printers:
; define local vars printer (Char), mylist (List)
Do mylist.$define(printer)
Do $root.$getprinterlist(mylist)
Report Instances
Report instances have the following methods.
$printrecord()
prints the Record section; same as the Print record command
$printtotals(section)
triggers a subtotal or totals section; section is the highest level subtotal to be printed, a
constant, such as kSubtotal5 or kTotals
$printsection(section)
prints a report section; section is a constant, kRecord, kTotals, and so on, or a reference
to a field on the report instance
$accumulate(section)
accumulates the subtotals and totals section, and is sent during the printing of a record
section
$checkbreak()
checks if a subtotal break is required, returns a constant: kSubtotal1 to kSubtotal9 or
kNone if subtotal break is not required
$skipsection()
skips the current section; if you call this during $print() for a field, no further fields will
be printed for that section
$startpage(pagenumber)
starts a new page; adds the page header section to the page, and for the first page also
adds the report header section
383
The device preferences are listed under the global printing preferences. Report instances
have their own printing preferences which are local to the instance. They take their initial
values from the global printing preferences. You can only assign values to these properties
in $construct(), and before you start printing the first record.
The $firstpage property always returns 1, and $canassign() is false. The $lastpage property
returns the last page. You cannot set $lastpage in the report instance to reduce the number
of pages generated, that is, once pages have been generated they cannot be removed from a
print job.
Note that the $pageheight property of a report instance returns the height of the printable
area excluding the margins, headers, and footer areas of the report.
384
Report Instances
The following method generates subtotal breaks every fifth record. The $reccount property
is incremented and the subtotals accumulated manually.
Do $reports.Report2.$open('*') Returns Myreport
For lineno from 1 to Mylist.$linecount step 1
Do Mylist.[lineno].$loadcols()
Calculate Myreport.$reccount as Myreport.$reccount+1
Do Myreport.$printsection(kRecord)
Do Myreport.$accumulate()
If mod(lineno,5)=0
Do Myreport.$printtotals(kSubtotal1)
End If
End For
Do myreport.$endprint()
385
Note that you should not use hash variables to define the columns in list if it is going to be
used as the basis of a report.
386
kPosHeader
kPosFooter
kPosSection
the position is global to the print job, relative to the top-left of the local
area of the first page
the position is relative to the top-left of the paper edge of the page
specified by $posvertpage and $poshorzpage
the position is relative to the top-left of the printable area of the page
specified by $posvertpage and $poshorzpage
the position is relative to the top-left of the local area (excluding the
header and footer sections, and the margins) of the page specified by
$posvertpage and $poshorzpage
the position is relative to the top-left of the header area (union of report
and page header sections) of the page specified by $posvertpage and
$poshorzpage
the position is relative to the top-left of the footer area of the page
specified by $posvertpage and $poshorzpage
the position is relative to the top-left of the section specified by
$possectident
387
kBndsLocal
kBndsHeader
kBndsFooter
returns kPosGlobal coordinates. The top, left, width, and height are
calculated to global coordinates of the local area of the page
returns kPosPaper coordinates. The top and left are zero, and the height
and width are calculated to the height and width of the paper of the page
returns kPosPrintable coordinates. The top and left are zero, and the
height and width are calculated to the height and width of the printable
area of the page
returns kPosLocal coordinates. The top and left are zero, and the height
and width are calculated to the height and width of the local area of the
page
returns kPosHeader coordinates. The top and left are zero, and the
height and width are calculated to the height and width of the header
area of the page
returns kPosFooter coordinates. The top and left are zero, and the height
and width are calculated to the height and width of the footer area of the
page
$possectident
the $ident of the section when $posmode is kPosSection
$posvertpage
the vertical page number when $posmode is not kPosGlobal or kPosSection
$poshorzpage
the horizontal page number when $posmode is not kPosGlobal or kPosSection. This
will usually be set to 1. Horizontal page numbers apply when horizontal pages are
enabled
$top
the top of the position in cms or inches local to its $posmode
$left
the left of the position in cms or inches local to its $posmode
$height
the height of the position in cms or inches
$width
the width of the position in cms or inches
Measurements are in either cms or inches depending on the setting of the usecms Omnis
preference which you can change in the Property Manager using the
Tools>>Options/Preferences menu option.
388
Page layout
To understand the positioning notation it helps to look at the layout of the report on paper or
screen. The area available for printing is limited to the printable area on the paper as
determined by the printer or device. Within this space Omnis reports print to the header,
footer, and local or global areas, that is, the space remaining after subtracting the header,
footer, and margins specified in the class. Note that Omnis subtracts the margins specified
in the class from the paper edge, rather than the boundary of the printable area.
Header
Local or
Global area
Margins
Footer
The position of a report object, either a section or report field, is relative to the local area on
the current page, or the global area for the entire report.
389
Object
Object
The following example method produces a report with multiple columns by configuring
itself according to the current paper size and orientation. The report class contains various
390
You can use the $offset(x,y) method to move the object horizontally by x units (unless
$horzpages is enabled) and vertically by y units. The units are defined by $prefs.$UseCMS
and maybe either positive or negative.
391
Report Inheritance
When a report is based on a report superclass several items are inherited including report
header and footer sections (e.g. page header, subtototals, footer, etc), the objects within
these sections, as well as the sort fields in the report superclass. The objects within the
record section of the report superclass are not inherited. You can, therefore, create a report
template containing your company identity and base all other reports on the template to
ensure a uniform design and layout is maintained across all your reports.
Inherited sections cannot be manipulated in any way. You cannot resize an inherited section
by moving the section object immediately below the inherited section, or change the
properties of the section or its objects. When a section is inherited, the height of the section
is determined from the superclass, and all other sections below are moved up or down
accordingly.
For inherited sections, the text of the section bar and the text of the section connection lines
are shown in blue. The background is shown in gray to indicate that this section cannot be
manipulated.
Inheriting Sections
Modifying a Superclass
When modifying the section of a superclass, e.g. adding, removing or changing objects
within a section, these changes will be reflected in any report class which inherits the
section.
Removing an entire section from a superclass will also affect all subclasses. However,
adding a new section to a superclass will not affect any of its subclasses. To inherit the new
section, subclasses need to be modified to inherit this new section.
Any changes made to sort fields will be reflected in all subclasses.
Inheriting/Overload a section
To inherit or overload a section, right click on the section in the Property Manager. A
context menu opens allowing you to inherit or overload the property. You cannot
manipulate inherited sections, or inherited section objects, or to add more objects to an
inherited section.
392
Report Fonts
When overloading a sort field, the properties of the sort field originally inherited are
maintained. If a sort field is inherited which has not been specified by its super class, the
name will be displayed as #???.
Positioning Sections
If an inherited section contains positioning sections, these are also inherited. It is not
possible to add additional positioning sections to an inherited section. It is not possible to
inherit position sections without inheriting their main section.
Notation
You can inherit or overload sections using notation. To do this you assign $isinherited of
the section notation. For example:
Do $clib.$reports.myreport.$pageheader.$isinherited.$assign(kTrue)
The objects of inherited sections are not part of the subclass and as such will not appear in
the list of objects of the report class, but will appear in the list of objects of a report
instance.
The following section properties can be inherited: $reportheader, $pageheader,
$subtotalhead, $subtotalhead1 to 9, $subtotal9 to 1, $pagefooter, $totals.
Report Fonts
If you are developing an application for a cross platform environment, you may want to set
up the system font tables to allow the fonts used in your application to map correctly across
the different platforms. There is a system font table for report classes and window classes
for each platform supported in Omnis.
The fonts in the report font table will appear in the $font property for report objects. So
even if you are developing an application for a single platform, you may still want to edit
the report font table to add fonts to those already available for report objects.
#WIRFONTS
#MARFONTS
#UXRFONTS
#MXRFONTS
393
Use the Browser Options dialog (press F7/Cmnd-7 while the Browser is on top) to
make sure the system tables are visible in the Studio Browser
The #WIRFONTS system table contains a list of fonts that are available in Omnis by
default. Each row in the font list displays the corresponding font for each platform
supported in Omnis. To change the font mapping, replace the name of a font either by
typing its name or selecting it from the list of fonts. To add a font, click in the next available
line in the font list and add the name of the font. Add a font name for each platform.
The font table editor loads or creates a font table for each platform (corresponding to each
column in the editor) and allows you to edit them all simultaneously. Therefore when you
edit the report font table for the first time, and click OK to finish editing it, a new system
table is added to your library for each platform supported in Omnis, other than your current
platform.
394
Port Profiles
Port Profiles
A port profile is a named collection of information sufficient to completely describe the
operating system configuration of a port. Under Windows, the port profile information
corresponds to the information required to set the fields in a DCB for a serial port (under
Win16 the DCB is different to Win32). There is no port profile for a parallel port, since it
requires no operating system configuration information.
Under Mac OS, the port profile information corresponds to the information required to
make the SerReset and SerHShake API calls. (Note: Port profiles are not currently
supported on OS X)
The information required to completely configure a port therefore comprises:
1. The port profile (not required for parallel ports)
2. Characters per inch.
3. Lines per inch.
When this command executes, it first checks the entire parameter string against the list of
profiles. If it matches an entry in the list, the command uses the profile to configure the port;
otherwise, the command treats the parameter string as a parameter list.
Notation
The relevant $port notation such as $portparity is unassignable when a port profile is
selected. The $portprofile property is the port profile for the current port on the Mac, or just
the single port profile under Windows.
Printer Escapes
When sending to printer, escape characters are not interpreted correctly, because the printer
driver attempts to draw them as data. You must send reports containing printer escapes to
port to ensure escape sequences are interpreted correctly.
The Omnis root preference $exportencoding ($root.$prefs) determines how the data is
converted before Omnis sends it to the port. Set this to kUniTypeAnsiLatin1 for printer
escapes to be interpreted correctly.
The escapes generated by the style() function cannot be mixed (in a report field's data) with
escapes specific to a printer.
396
Labels
Labels
To print labels in Omnis you need to create a report class and set up its properties for label
printing. You can create the report class using the standard SQL or Omnis report wizards, or
you can create an entirely New Report and add the fields yourself. This section uses the
Omnis Report wizard as the basis for a Customer address label, but the process is the same
for any label report.
To create the basis of your label report
Create a new report class using the Omnis Report wizard and include the fields you
want in your label
Open the report class to modify it
Delete the header section and any labels the report wizard places on the report class,
but leave the data fields; your report class should look something like the following
To change this report class into a label report you need to change some of its properties, set
the properties of the Record section to position your labels on the printed page, and as a
further enhancement you can set the properties of some of the fields on the report to exclude
empty lines. Note that all measurements use the current units set in the usecms Omnis
preference.
To set the label properties of a report class
Set the labelcount property to the number of labels across the page; for example, for
standard 3 x 8 laser labels you set labelcount to 3
Specify the width of a single label in the labelwidth property; if there are spaces
between your labels, include the space in the label width, that is, the labelwidth is the
distance between one record and next across the sheet of labels
If you want to print more than one label for each row or record of data set the
repeatfactor property, otherwise leave it set to 1 for a single copy of each label
397
Leave the dataname property empty, and set the calculated property to kTrue
Enter the calculation in the text property, something like the following
con(CU_FNAME, ,CU_LNAME)
The con() function concatenates the current values in the CU_FNAME and CU_LNAME
fields and separates them with a single space character.
Using all the features described in this section, your label report should look something like
the following when printed to the screen.
The constant kDevHtml is supplied by the HTML component at registration together with
some other constants.
Description
kDevHtmlFileName
kDevHtmlFont1
kDevHtmlFont2
kDevHtmlFont3
kDevHtmlFont4
kDevHtmlFont5
kDevHtmlFont6
kDevHtmlFont7
kDevHtmlImageBorder
kDevHtmlUseRects
kDevHtmlBackcolor
kDevHtmlTextcolor
default text color; any black text received from the print manager
will be changed to this color
kDevHtmlLinkcolor
kDevHtmlVLinkColor
399
Description
kDevHtmlALinkColor
kDevHtmlTemplate
full path and file name of a template HTML file; it must already
contain the basic framework for an HTML file, that is
<HTML>
<BODY bgcolor= etc>
</BODY>
</HTML>
kDevHtmlTemplateChars
the place holder contained within the template file which marks
the point at which the report output will be inserted into the
template, that is, $$$$ the template file must contain this text,
that is
<HTML>
<BODY bgcolor= etc>
<p>$$$$</p>
</BODY>
</HTML>
kDevHtmlScaleFont
You can get and set the value of the device parameters using the following methods.
$getparam(param constant)
returns the value of the specified parameter
$setparam(param constant, value [,param constant, value, ] )
sets the value(s) of the specified parameter(s)
For example
Do $devices.Html.$setparam(KDevHtmlFont1,6,KDevHtmlFont2,8)
Do $devices.Html.$getparam(kDevHtmlFileName) Returns MyPath
The value of all device parameters is stored in the Omnis configuration file.
401
Chapter 11Unicode
Chapter 11Unicode
Omnis Studio fully supports Unicode, which means you can expand the market for your
Omnis applications by supporting the majority of world languages and the display of special
characters, including scientific and mathematical symbols.
In previous versions of Omnis Studio, we provided a Unicode and non-Unicode version of
the development kit, but Omnis Studio 5 is Unicode compatible by default. The Unicode
version of Omnis Studio is available for Windows, Mac OS X, and Linux, and will allow
you to localize your applications and deploy them to virtually any market, anywhere in the
world.
You should also refer to the Localization chapter in this manual for information about
localizing and deploying your applications for non-English speaking markets.
What is Unicode?
Unicode provides a mechanism for representing characters or symbols used in many of the
languages in the world, as well as scientific and technical environments. The Unicode
standard is maintained by the Unicode Consortium (www.unicode.org) who set the
standards for Unicode and promote its worldwide use. They define Unicode as: a
character coding system designed to support the worldwide interchange, processing, and
display of the written texts of the diverse languages and technical disciplines of the modern
world. In the context of client-server and multi-tier computing, Unicode allows the
seamless exchange and processing of character data across different platforms, software
products and programming environments.
The Unicode consortium provides information and resources concerning Unicode, including
the standard definition and maintenance, character code tables, a locale identifier repository,
and lists of Unicode enabled products. The last major version update of Unicode was
version 5.1 which is capable of representing over 100,000 different characters, used in
many different languages throughout the world. Many operating systems and software
products have adopted Unicode, which is now universally accepted as the standard for
character representation. For example, the latest versions of Windows Vista and Mac OS X,
as well as all varieties of Linux, offer Unicode support. All web standards, such as the latest
versions of HTML and XML support Unicode, as well as the latest versions of Internet
Explorer and all Mozilla-based browsers. In addition, SQL databases such as the most
recent versions of Sybase, Oracle, and DB2 provide Unicode support.
Together with the display of multiple languages in Omnis, the use of Unicode encoding
affects the sort order of dynamic data, for example, in list variables, as well as the querying
and retrieval of data from Unicode compatible Server databases.
402
403
Chapter 11Unicode
DAMs
The DAMs provided with Studio 5.0 are able to function in Unicode or 8-bit compatibility
mode. This means that after converting your existing libraries for use with Studio 5.0, it is
possible to continue interacting with non-Unicode databases.
In 8-bit compatibility mode, all DAMs:
Return non-Unicode character data types via the $createnames() and $coltext attributes
Bind outgoing character variables using the database's non-Unicode data types
Convert all data inside outgoing character bind variables to single-byte characters
Define incoming character columns using the database's non-Unicode data types
Convert all data inside incoming character bind variables from bytes into characters
Character Mapping
This section is applicable to session objects operating in 8-bit compatibility mode only.
When reading data from a server database, Omnis expects the character set to be the same
as that used in an Omnis data file. The Omnis character set is based on the Mac OS
extended character set, but is standard ASCII up to character code 127. Beyond this value,
the data could be in any number of different formats depending on the client software that
was used to enter the data.
When assigned, the $maptable session property identifies files containing translation tables
for 8-bit character codes read into and sent out of Omnis. For example, suppose you are
working with a database that stores EBCDIC characters. In order to accommodate this
database, you should create an '.IN' map file that translates EBCDIC characters to ASCII
characters when Omnis in reading server data and a matching '.OUT' file that reverses the
process by converting ASCII to EBCDIC characters when Omnis is sending data to the
server.
Under Windows and Linux, Omnis uses the same character set as under Mac OS, so in the
general case, mixed platform Omnis applications should have no need for character
mapping. However, if the data in a server table was created by another software package,
running under Windows for example, the characters past ASCII code 127 would appear
incorrect when read using Omnis. In this situation the $maptable property should be used to
map the character set.
404
DAMs
There are two kinds of character maps: IN and OUT files. IN files are used to translate
characters coming from a server database into Omnis. OUT files are used to translate
characters that travel from Omnis back to a server database.
In this example, the two map files are called "pubs.in" and "pubs.out".
The session property $charmap controls the mode of character mapping that is to be applied
to the data. Set the character mapping mode using a command of the form:
Do SessObj.$charmap.$assign(pCharMap) Returns #F
The potential values for the character mapping mode parameter pCharMap are:
kSessionCharMapOmnis
Use the internal Omnis character set.
kSessionCharMapNative
This is the default and specifies that the client machine character set is to be used.
kSessionCharMapTable
Use the character mapping table specified in the $maptable property. If the $maptable
property is not set and the application attempts to assign kSessionCharMapTable this
fails.
405
Chapter 11Unicode
If you wish to use the character mapping tables defined using the $maptable property, you
must set $charmap to kSessionCharMapTable.
406
DAMs
407
Chapter 11Unicode
Oracle DAM
This section summarizes recent changes made to the Unicode Oracle Object DAM designed
to enable insertion and retrieval of mixed ANSI and Unicode character types.
In the case of Oracle 8i and later, these data types are:
CHAR
NCHAR
VARCHAR2
NVARCHAR2
CLOB
NCLOB
LONG
By default, the Unicode Oracle DAM maps all Omnis character data to the NVARCHAR2
and NCLOB data types, dependent on the field length of the Omnis bind variable. However,
the Oracle DAM provides session properties which affect the Omnis to Oracle data type
mappings:
$nationaltonvarchar
If set to kTrue, Character and National data types are treated differently when being
inserted to VARCHAR2 / NVARCHAR2 columns. The National character subtype
will be used with Unicode data, whilst the Character subtype will be reserved for nonUnicode data.
$nationaltonclob
If set to kTrue, large Character and National data types are treated differently when
being inserted to CLOB / NCLOB columns. The onus is upon the developer not to put
Unicode characters into Character subtypes when using these properties; otherwise data
insertion/encoding mismatch errors will occur.
$maxvarchar2
Sets the byte limit above which Omnis character fields will be mapped to
408
Character Normalization
CLOB/NCLOB data types as opposed to VARCHAR2 / NVARCHAR2 columns. The
maximum value is 4000 bytes.
$longchartoclob
If set to kTrue (the default), Omnis large character fields > $maxvarchar2 in byte length
will be mapped to the CLOB/NCLOB data type. If set to kFalse, the LONG data type is
used.
Reading Unicode and Non-Unicode Data
The Oracle DAM automatically detects the data type of retrieved character columns and
converts the data accordingly. There is no need to modify any properties in order to retrieve
mixed ANSI and/or Unicode Data.
ODBC DAM
The ODBC DAM provides the $nationaltowchar session property.
By default, Omnis Character and National fields are mapped to the SQL_WCHAR,
SQL_WVARCHAR and SQL_WLONGVARCHAR data types. By setting
$nationaltowchar to kTrue only National fields will be mapped to these types (to the
equivalent server data types) and Character fields will be mapped to SQL_CHAR,
SQL_VARCHAR and SQL_LONGVARCHAR as determined by the Omnis field length.
Character fields mapped in this way are subject to data loss/truncation where such fields
contain Unicode characters. When setting this property, please note that Unicode data types
usually have precision limits half that of their corresponding ANSI data types. For example,
this is 8000 for the SQL Server VARCHAR() data type but 4000 for NVARCHAR().
$nationaltowchar affects both the text returned by the $createnames() method and the
binding of input parameters.
Character Normalization
Originally, Unicode was a 16-bit character set. It has subsequently been extended to include
code point values up to and including U+10FFFF. It is not expected that it will be extended
any further. Windows and Mac OS X still represent Unicode character strings using arrays
of Short (16-bit) integers. This is not a problem, because the UTF-16 standard allows code
points U+10000 and greater to be represented by pairs of 16-bit values (each member of the
pair occupies space in the 16-bit range that is not used for code points). This representation
is referred to as a surrogate pair.
Internally Omnis uses UTF-32 to represent code points, that is, each code point occupies 32
bits, and the value of each code point is between 0 and U+10FFFF inclusive. This allows
for straightforward processing of character strings, since every code point occupies the
same space in memory.
Unicode allows a significant number of characters to be represented by more than one
sequence of code points. For example, consider the letter E with circumflex and dot below,
409
Chapter 11Unicode
a character that occurs in Vietnamese (). This character has five possible representations in
Unicode:
1. U+0045 Latin capital letter E
U+0302 combining circumflex accent
U+0323 combining dot below
2. U+0045 Latin capital letter E
U+0323 combining dot below
U+0302 combining circumflex accent
3. U+00CA Latin capital letter E with circumflex
U+0323 combining dot below
4. U+1EB8 Latin capital letter E with dot below
U+0302 combining circumflex accent
5. U+1EC6 Latin capital letter E with circumflex and dot below
A character represented by more than one code point is referred to as a composite
character. A character represented by a single code point is referred to as a pre-composed
character.
As far as the end-user is concerned each of these representations usually needs to be treated
identically. This leads to some interesting consequences for Omnis. These are discussed in
the following sections. Note the term end-user character means the character that the enduser is working with in the example above, the end-user character is .
Normalization of a Unicode character string converts the string into a standard, defined
format. Once normalized, a Unicode character string has only one possible representation,
thereby making it possible to compare it with other character strings, and produce results
useful to the end-user. The Unicode standard recommends two forms of normalization.
These are:
1. Canonical decomposition, referred to as NFD:
Pre-composed characters are replaced by their equivalent composite characters;
Composite characters are replaced with a single fixed composite representation.
2. Canonical decomposition followed by canonical composition, referred to as NFC:
After carrying out NFD, all composite characters are replaced with their pre-composed
equivalent, where one exists.
Omnis provides two functions to normalize character strings:
nfd(string) carries out canonical decomposition on the string and returns the
normalized string.
nfc(string) carries out canonical decomposition followed by canonical composition on
the string and returns the normalized string.
These functions are not available in client-side web client methods.
410
Character Normalization
Comparing Text
Omnis uses two types of comparison for character strings:
Comparison of the UTF-8 values of the strings. This is called Character comparison.
Comparison according to the rules for the locale specified via the localization data file;
prior to comparison, the input data is normalized. This is called National comparison.
National comparison is more likely to produce results that the end-user would expect.
Note that upper casing used in conjunction with national comparison may not have an
effect, since sometimes the rules for the locale ignore the case of the characters.
The natcmp() function uses national comparison. Note that natcmp() is not available in
client-side web client methods.
Omnis compares text for many different reasons, and in many different places. Key areas
are:
Sorting lists
Searching lists
Manipulating data file indexes
Expressions, for example the test on an if statement
Omnis supports two types of character variable character and national.
Sorting Lists
When using the character type, Omnis uses character comparison.
When using the national type, Omnis uses national comparison.
Searching Lists
When using the character type, Omnis uses character comparison.
Searches that directly use a character column of national type use national comparison.
Other searches, for example searches using a calculation, will behave as if they are
operating on normal character data. However, you can use natcmp() as part of the
calculation, in order to use national comparison.
Expressions
To ensure the correct behavior of expressions that test the value of character variables, you
must either normalize their value first using nfc() or nfd(), or you must use the natcmp()
function.
411
Chapter 11Unicode
Drawing Text
Depending on the font and operating system you use, different representations of the same
end-user character may not always be drawn in the same way. The same applies if you try to
use strings that require surrogate pairs. Generally speaking, you will get the best results if
you normalize the text using nfc(), as the issues generally occur with composite characters.
Entering Text
Wherever possible, you should use the nfc() normalization form for data that is to be edited.
If composite characters are present in the data, multiple left or right arrow key presses are
required to skip a composite character, and also clicking and selecting in the text will
highlight an area which when copied to the clipboard might not exactly contain what
appeared to be highlighted.
Omnis performs NFC normalization on character data pasted from the clipboard when
running in the thick client (runtime); no normalization occurs when pasting characters into a
remote form when using the web client.
Character Translation
The following functions allow you to translate a specified character in a string to its
Unicode value and to allow the reverse.
unicode(string,position[,returnhex])
returns the Unicode value of the character at the specified position in the string. The
first position in string is 1. If Boolean returnhex is true (default false) it returns a hex
string representing the value, of the form 'U+h'.
unichr(num1[,num2]...)
returns a string formed by concatenating the supplied Unicode character codes. Each
code is either a number or a string of the form 'U+h',where h is 1-6 characters
representing a hexadecimal value.
These functions are available in client-side methods as well as the thick client, but will
generate an error if used in the non-Unicode version of Omnis.
Unicode Clients
Locale Identifier
The locale()function returns the Locale Identifier (LCID) for the current client
machine/operating system. As well as the language of the machine, the Locale Identifier
specifies the decimal, thousand and list separators, currency values, units of measurement,
412
The function converts src, and stores the result in dst. It returns zero for success, or a nonzero error code together with error text in errtext. Src and dst are either binary or character
variables, depending on the values of the srctype and dsttype.
srctype and dsttype are one of the kUniType... constants (see below).
Bom is Boolean: if true, dst has a Unicode Byte Order Marker (BOM) if relevant for the
destination type.
The kUniType... constants are as follows:
kUniTypeAuto
The source encoding is automatically detected from the conversion source; possible
encodings are identified by the remaining kUniType... constants (allowed only for the
source type).
kUniTypeUTF8
The data is stored in a binary variable and contains Unicode character data encoded
using UTF-8
kUniTypeUTF16
The data is stored in a binary variable and contains Unicode character data encoded
using UTF-16LE if the machine is little-endian, or UTF-16BE if the machine is bigendian. Useful when writing cross-platform code that interacts with the OS.
kUniTypeUTF16BE or kUniTypeUTF16LE
The data is stored in a binary variable and contains Unicode character data encoded
using UTF-16BE (big-endian) or UTF-16LE (little-endian)
kUniTypeUTF32
The data is stored in a binary variable and contains Unicode character data encoded
using UTF-32LE if the machine is little-endian, or UTF-32BE if the machine is bigendian. Useful when writing cross-platform code that interacts with the OS.
413
Chapter 11Unicode
kUniTypeUTF32BE or kUniTypeUTF32LE
The data is stored in a binary variable and contains Unicode character data encoded
using UTF-32BE (big-endian) or UTF-32LE (little-endian)
kUniTypeNativeCharacters
The data is stored in a binary variable and contains a stream of bytes, where each byte
is a character in the Latin 1 character set for the machine (Ansi on Windows,
MacRoman on the Mac, ISO-8859-1 on Unix
kUniTypeCharacter
The data is stored in a character variable. Note this constant has been moved since
the last Unicode build, so you need to re-enter it in your code.
kUniTypeAnsi
The data is stored in a binary variable, and contains character data where each byte is
encoded using the specified ANSI code page. A range of constants are provided to
cater for most world or regional languages, including Cyrillic, Greek, Hebrew, Arabic,
Thai, and so on
kUniTypeISO8859...
The data is stored in a binary variable, and contains character data where each byte is
encoded using the specified ISO 8859 code page.
There are two sys() functions to assist OEM conversion when using the uniconv() function.
sys(218) modifies OEM conversion to map CR to CR and LF to LF.
sys(219) reverts to the original mapping for the OEM code page.
Formfile
The $filereadencoding and $filewriteencoding properties have been changed. In previous
versions of Omnis Studio, the Formfile component defined kFFEncoding constants.
These constants should not now be used, and you are advised to use the kUniType
constants to identify the file encoding. Formfile has been extended, so that you can use any
of the kUniType... constants except kUniTypeCharacter for the $filereadencoding property,
and any of the kUniType... constants except kUniTypeAuto and kUniTypeCharacter for the
$filewriteencoding property.
In addition, there is also a kUniTypeBinary constant to identify files that are to be treated as
raw binary data.
Code that uses the old kFFEncoding constants should continue to work.
414
Fileops
The Fileops component has two methods, $readcharacter() and $writecharacter() which
allow you to read and write Unicode character data from and to a file.
$readcharacter(encoding,variable)
reads all data from a file containing character data into variable; encoding is one of the
kUniType constants (listed above), identifying the encoding of the file.
$writecharacter(encoding,variable)
replaces the contents of the file with the character data stored in variable; encoding is
one of the kUniType constants, identifying the encoding of the file.
For $readcharacter, specify the encoding as any kUniType... constant except
kUniTypeBinary and kUniTypeCharacter.
For $writecharacter, specify the encoding as any kUniType... constant except
kUniTypeAuto, kUniTypeBinary and kUniTypeCharacter.
Note the $readcharacter() and $writecharacter() methods use the kUniType constants and
not the kFFEncoding constants which should not now be used.
415
Chapter 11Unicode
$exportbom
If true, and the $exportencoding preference identifies a Unicode encoding, a Unicode
BOM is output at the start of the output file.
These properties can be found in the Omnis preferences ($root.$prefs). In a multi-threaded
server, there is a separate value of each of these properties for each thread.
416
Chapter 12Localization
Note: the following section describes a localization method that can only be used for
Window classes and Remote forms that use the Web Client plug-in. For all new libraries
that use the JavaScript Client we urge you to use the localization method described in the
Creating Web & Mobile Apps manual.
If you are developing Omnis applications for an international market, you may want to
translate the text and labels in your libraries into another language or support multiple
languages. Omnis provides tools for localization of your libraries via the String Table tab on
the Catalog window and via the String Table editor in the Add-ins submenu of the Tools
menu.
As well as translating your Omnis libraries, you can translate the majority of the text and
strings that appear in the Omnis Runtime environment (the Omnis.exe) and the Omnis Web
Client. You can localize various language dependent strings in the Omnis executable itself,
such as the days of the week.
Chapter 12Localization
Open your remote form and open the Component Store (press F3)
Click on the Background Components or WEB Background Objects group in the
Component Store toolbar and drag the String Label component onto your window or
remote form
Open the Property Manager (F6/Cmnd-6), click on the Custom tab, and enter a suitable
label in the $rowid property; the row ID can be a number or string
Create the other labels for your window or form using the String Label component, and
assign unique labels in the $rowid property for each one
The string label object can display single or multiple lines of text.
It is also possible to translate the text for pushbuttons, check boxes and the contents of lists
that may appear in your window or form. To identify these objects in the string table and
your Omnis code you should make sure the objects have a suitable text string specified in
the $name property. The text in the $name property of an object should be used as the row
ID in the string table and also used in your code to reference the text.
418
Rename the second column by clicking in the column and selecting the Rename
Column option from the Columns menu; name the column using the two-letter ISO 639
language code for your native or default language, e.g. enter EN if your string labels
and buttons contain English
Next you need to add a row for each string label or button you have used in your
window(s) and/or remote form(s) in your application, entering the row IDs and button
names you have used to identify these objects in the STRINGID column
You can tab to the end of the row to create a new row or click the Add Row button and
enter the Row ID for the next table entry; continue adding rows for each label or object you
wish to translate.
Add a column for each language you wish to support in your application, using the twoletter ISO 639 language code to name each column, e.g. the third column could be
named FR to support French, the fourth column could named DE to support German,
and so on
Next click on the Translate button, select the Translate from column and the
Translate to columns; note the Translate to list allows multiple selections to allow
419
Chapter 12Localization
you to translate to multiple languages, or you can press Ctrl/Cmnd-A to select all lines
(except the column selected in Translate from)
Click the Translate button and Omnis will translate all the strings; note this may take a
few minutes if you have many rows and columns in your string table
The following example shows a String Table for a remote form that has a number of string
labels and pushbuttons. The English strings are in the second column, while the French and
German strings were added automatically using the Translate option.
Under certain circumstances you can use the STRINGID column in your string table as your
default language, for example, if you have used the exact label names in the STRINGID
column rather than some other rowID. In this case, you need to specify the Locale of your
STRINGID column in the Translate dialog, using the two-letter ISO 639 language code, to
identify its language.
420
Chapter 12Localization
$removestringtable()
StringTable.$removestringtable(cPathname) deletes the string table file specified by
cPathname. Returns kStringTableOK or an error code which is less than zero
$rowcnt()
StringTable.$rowcnt([cTableName]) returns the number of rows in string table
cTableName, or an error code which is less than zero
$savestringtable()
StringTable.$savestringtable(cTableName) saves the string table specified by
cTableName. Returns kStringTableOK or an error code which is less than zero
$setcolumn()
StringTable.$setcolumn(cColumnNumberOrName) sets the current column. Returns
kStringTableOK or an error code which is less than zero
$unloadall()
unloads all string tables from memory.
$unloadstringtable()
StringTable.$unloadstringtable(cTableName) unloads the string table cTableName
from memory. Returns kStringTableOK or an error code which is less than zero
The following functions apply to string tables for remote forms and are available for
execution in client methods only:
stgettext()
StringTable.stgettext(id) returns the string with the specified id from a string table, or
empty if the lookup fails. id can be prefixed with 'TABLENAME.', or must be an id for
the string table of the current form.
stgetcol()
StringTable.stgetcol(table) returns the name of the current column for string table table
stsetcol()
StringTable.stsetcol(table,col) sets the current column for lookups from string table
table to the column with name col and returns Boolean true for success.
422
Having loaded the string table and specified the current column, the following method can
be used to load the text or string values into the appropriate field labels, buttons, and lists in
a data entry window. Note that the IDs for each object are stored in custom constants that
are defined in the the Startup_task in the library.
; custom method $loadFields
; Define the button and group box descriptions using $getText
Do StringTable.$getText(kPrintButton) Returns lval
Do $cwind.$objs.PrintButton.$text.$assign(lval)
Do StringTable.$getText(kLanguageButton) Returns lval
Do $cwind.$objs.LanguageButton.$text.$assign(lval)
Do StringTable.$getText(kEmpTitle) Returns lval
Do $cwind.$objs.stEntry_1022.$text.$assign(lval)
423
Chapter 12Localization
The next section of the method defines the dropdown lists for Sex (male/female) and
Marital Status by loading the relevant entries from the current string table.
Set current list iSex
Define list {iField}
Do StringTable.$getText(kMale) Returns iField
Add line to list
Do StringTable.$getText(kFemale) Returns iField
Add line to list
Calculate iSex.$line as 1
Set current list iStatus
Define list {iField}
Do StringTable.$getText(kMarried) Returns iField
Add line to list
Do StringTable.$getText(kSingle) Returns iField
Add line to list
Calculate iStatus.$line as 1
Within your application you need to provide some way for the user to select and change the
language setting. This could be done using a separate window containing a list of available
languages and a button to set the selected language. The following method gets all language
column names from the Lang String Table and puts them into an Omnis list.
; custom method $loadList
Set current list iLang
Define list {iLangField}
; Save the current column number
Do StringTable.$getColumnNumber() Returns lnum
; Build a list of all column names in the String Table.
Do StringTable.$colCnt() Returns maxcol
; Start from column 2 as column 1 is reserved for String Table IDs
For lcount from 2 to maxcol step 1
Do StringTable.$setcolumn(lcount)
Do StringTable.$getcolumnname() Returns iLangField
Add line to list
End For
Do StringTable.$setColumn(lnum)
Calculate iLang.$line as pLine
When the user selects a language from the list, they should click a button with the following
method which changes the language of the text on itself and the data entry window.
424
The following method translates the language list depending on the Language selected. The
code uses the String Table column headings to look up corresponding IDs from within the
table itself.
; custom method $translateList
Set current list iLang
Calculate lnum as iLang.$line
Calculate lrowcnt as iLang.$linecount
For lcount from 1 to lrowcnt step 1
Do StringTable.$getText(iLang.[lcount].iLangField)
Returns iLang.[lcount].iLangField
Calculate iLang.$line as lcount
End For
Calculate iLang.$line as lnum
Finally you need a method to redraw all the fields and text labels on any open windows or
forms.
; custom method $redrawAll
Do $iwindows.$first() Returns ref
While ref
Do StringTable.$redraw(ref.$hwnd)
Do $iwindows.$next(ref) Returns ref
End While
425
Chapter 12Localization
426
Tooltips
You can use the $st. lookup notation to lookup text from a string table to fill out the $tooltip
property for a field.
427
Chapter 12Localization
Localizing Omnis
In order to provide a completely foreign version of your Omnis application, you may need
to translate various resources that appear in Omnis itself (rather than strings that appear in
your libraries, as described in the previous section). This applies equally to applications that
run on the desktop using the Omnis executable (Runtime), and applications that run on the
Internet using the Omnis Web Client: you can translate string resources in the Omnis
runtime and in the web client.
Omnis Studio 5 introduces two new String Tables that allow you to translate:
Various built-in string resources in the Omnis executable, and
String resources in the Web Client.
The new String Tables can be accessed via the String Table tab in the Catalog (F9) window
and are edited using the String Table editor.
In addition, the Localization Library (omnisloc.lbs) is still available in the Local folder for
you to translate further string resources in the Omnis executable.
428
Localizing Omnis
When reading a string resource, Omnis looks up the string value in the string table, and if
present, it replaces the string value with the translation. If no translation is available, the
string remains unchanged. The string value lookup is case-sensitive, allowing the translation
to contain the correct case for the translated text.
Omnis loads the studio.stb string table when it starts up, and when $root.$prefs.$language
changes, and the appropriate language version of the resources is loaded. The column used
for translations is the ISO 639 language component of the locale stored in the current
language record. This is also stored in a small text file (locale.txt) in the Local folder of the
Omnis tree, to cater for the fact that the string table is loaded sooner in the life of Studio
than the localization data.
When a web-based client connects, Omnis sends client.stb to the client; this is handled via
the cache, so it will not always be sent. The client loads client.stb, and uses the column
corresponding to the client locale to obtain translations (the client locale can be specifically
set using $cinst.$stringtablelocale for the remote task instance, or it can be allowed to
default to the locale of the client machine).
Local Language
The locale() function for the fat client now has an optional Boolean parameter, which when
passed as kTrue, causes it to return the locale field value for the current
$root.$prefs.$language.
429
Chapter 12Localization
Days of Week
This comprises 2 strings for each of the 7 days of the week, allowing for a full name such as
Wednesday, and an abbreviated name such as Wed.
If a day of the week item is empty, Omnis will read its value from the operating system.
Months of Year
This comprises 2 strings for each of the 12 months of the year, allowing for a full name such
as August, and an abbreviated name such as Aug.
If a month item is empty, Omnis will read its value from the operating system.
430
Separators
These comprise the following:
The decimal point used for all numeric fields. If this item is the character 0 (zero),
Omnis will read the decimal point character from the operating system.
The thousands separator used for numbers. If this item is the character 0 (zero),
Omnis will read the thousands separator character from the operating system.
The function parameter separator
The decimal point used when importing data
The field separator used when importing
The sequence used for quoting names in the notation
If you leave the field empty, then no suffix is applied, otherwise, the string before the first $
is the default suffix, and the remaining $-separated strings are a day number followed by its
suffix. There must be a trailing $.
To see the suffix used for a particular date you can use the function call dat(date,d).
431
Chapter 12Localization
User Interface
The Omnis preferences accessed from the IDE Tools>>Options menu line let you assign a
new language from the dropdown list in the $newlanguage property. The current language is
shown in the $language property. The language must already be defined in the localization
data file.
The new language does not apply until you quit and restart Omnis. Note that if the
localization database is shared by several users, then the new language setting affects each
of them, as soon as they restart.
An Omnis library, OmnisLOC.LBS is provided that lets you create and edit language
information. To use it:
Take a backup of the OmnisLOC.DF1; you may prefer to work on the backup copy
rather than the live copy, in which case you should make a working copy as well as a
backup copy
Open the OmnisLOC.LBS library, found in the Local folder in the main Omnis folder.
You are prompted for the location of the localization data file and a localization menu
is installed on the IDE menu bar, to the right of the Tools menu
Select Current Language to display the language in use
Select Language Records to create a new set of language information, or to edit an
existing one. This displays a dialog containing a set of tabbed panes and the standard
Omnis Insert, Edit, Find, Next and Previous buttons
You use the Next and Previous buttons to move through the records in the data file, the Find
button to locate a particular language record, and Edit to modify data already present in the
data file.
Two Insert buttons are available. Insert lets you create a brand new record, while Insert CV
lets you make a copy of an existing language record and edit that. This is particularly useful
for cases where there are only minimal differences between two language records. To use
Insert CV:
432
Click on Insert CV
A new record is created. Remember to edit the language name as well as the specific
internal data.
When all the data is input, click on OK to store it and close the library
If you were working on a copy of the data file, move it back to the local folder
Any fields that are left blank will default to a single space. Some of the fields on the
General tab are limited in terms of which characters can be used; for example trying to
define a letter as a decimal separator is not allowed, and will generate an error message.
Notation
There is no requirement to manipulate localization data at runtime, so the localization
notation is minimal.
$root.$prefs.$language
a read-only property which returns the name of the language Omnis is currently using
$root.$prefs.$newlanguage
a property that lets you assign the name of the new language, that is, the language
Omnis will use when it restarts
$hascurrlangnationalsortorder
a property of a data file, for example
$root.$datas.DataFile.$hascurrlangnationalsortorder
if true the sort order matches that for the current language, and false otherwise
Every data file stores its national sort order. When you create a new data file, Omnis stores
the national sort order for the current language in the data file.
433
Chapter 12Localization
$hascurrlangnationalsortorder is assignable, but you cannot set it to kFalse only kTrue.
When set to kTrue Omnis drops all of the indexes from the data file, changes the sort order
to that for the current language, and rebuilds all of the indexes.
434
Chapter 13Version
Control
This chapter describes how you can use the Omnis Version Control System (VCS) to
control Omnis application development in a team environment. In such an environment,
with several people working on the same application at the same time, perhaps in different
locations, you need to ensure that only one person can change a particular component at a
time and that any modifications are not lost or overwritten. The Omnis VCS allows you to
control the development of your Omnis applications, or any other project involving many
different files such as web or Intranet applications, and it allows you to build your
application for deployment to your customers or organization.
The Omnis VCS lets you revise Omnis library files and other application components
systematically. Apart from the Omnis libraries and classes within those libraries, you may
have your own externals, text files, web components, Html files, and so on, that are all
necessary to the running of the application. The Omnis VCS can handle all these types of
files and components.
In this chapter, the term component is used to refer to all types of files and different
components stored on disk. With regards to the Omnis VCS, a non-Omnis component is
any disk file or external component other than an Omnis class.
435
Overview
To place Omnis libraries under version control you check them into the Omnis VCS from
the Libraries tree in the Studio Browser, or for non-Omnis components from the File
Browser in the VCS itself. All the components you check into the VCS are kept in a project.
The VCS stores each project in its own repository database, which can be a remote server
database or an Omnis data file.
The Omnis VCS provides all the functionality to set up, manage, and use version control,
including:
Creating a database session and VCS repository
Checking in Omnis libraries and other non-Omnis components
Creating a project
Managing and supervising users
Building projects and libraries for distribution
Managing projects and granting user privileges
Setting VCS options
The Omnis VCS is permanently available in the Studio Browser. To use the VCS click on
the VCS option in the Studio Browser. The Session Manager and the Open Session options
are shown in the Studio Browser. To use the VCS you must first create a database session to
store your project.
The VCS tree displays all your open projects and works in a very similar way to the
Libraries and SQL Browser tree. The VCS context menu lets you open and close sessions,
and perform user administration functions. When you select a project in the VCS, the
Browser shows the contents of that particular project.
436
Setting up a Project
Setting up a Project
This section is for the lead developer or manager in the development team and details how
you setup a VCS repository and create a new project containing all your application
components.
To use the VCS you need to connect to a database via a session, set up the Supervisor user,
and create a VCS repository. You can open a VCS session using the SQL Browser, but you
should use the VCS session browser for convenience.
You can create a repository on a server database, such as Oracle, Sybase, or MySQL, or in
an Omnis data file, that is, Omnis own built-in database. You can access a repository using
a native DAM for the chosen database, or you can use ODBC or JDBC. Connecting to your
server or Omnis database by creating an Omnis session is covered earlier in this manual.
Once you have connected to your database, the VCS operates in the same way, regardless of
the database and the location the repository is stored in.
To setup a new project, you need to:
Define a new database session, and create a new repository
Sign in as Supervisor, then create and define users
Check in your libraries, classes and other components (the check in process creates a
new project for you) and assign access privileges to components for individual users
You also need to tell the members of your development team their usernames and
passwords, and provide them access to the VCS repository
Sybase Repositories
If you are using Sybase for your VCS repository, you must make sure the transaction log
has enough capacity to handle your transactions. See the Sybase documentation for details
on the transaction log. You can use the command
dbcc checktable (syslogs)
while you are running the VCS against your repository to check the status of the transaction
log. You must also set the option select into/bulkcopy to false with the following remote
procedure call
sp_dboption <db>, select into/bulkcopy, false
where <db> is your Sybase database name. The VCS issues an error message and aborts
logon if the target database has the select into/bulkcopy option set.
437
Creating a session
To create a new VCS session, you can either use the default session, called VCS_Session,
or create a new one.
To create a VCS session
Select VCS in the Studio Browser and click on the Session Manager option
The Modify Session dialog opens which allows you to enter the details of the new session.
To duplicate a VCS session
If you have a session that is a suitable template for a new one
Select the existing session and select Duplicate from the Sessions menu
In either case, a new session appears in the VCS Session Browser. You can now click on
your session and modify it.
To modify a VCS session
Select the session in the Browser and click the Modify Session option
or
The Modify Session dialog lets you modify the details of the selected session; it is identical
to the session definition dialog in the SQL Browser.
Note that to make a session usable with the VCS, you must select VCS from the Session
type dropdown list.
The information you need to supply depends on the database you want to use, but would
normally include hostname, username and password, plus you need to select the correct
DAM for your chosen database. You dont need a username and password for an Omnis
data file.
When you have modified the session, click on OK to close the Modify Session dialog
438
Select the VCS option in the Studio Browser, click on the Open Session option and
select the session from the list of VCS sessions
Enter the Username and Password to open the session
Setting up a Project
Time Settings
The Omnis VCS supports the UTC (Co-Ordinated Universal Time) standard time setting.
The VCS stores times in UTC, but displays times according to the time zone that has been
set. There is a preference to set the local time zone, which you can set on the Display tab
under the VCS Options.
Both the user name and password are case sensitive, so make sure both words are in the
correct case, otherwise you will not be able to logon.
Click on OK
To ensure a secure system, you should change the Supervisor name and password. You can
do this later, but to do it now
Select the VCS option in the Studio Browser and click on the User Admin option
The User Administration window lets you add and remove users, and initially displays only
one defined user, Supervisor. The columns in the list show details about each user, in this
case the Supervisor, including the user's name, password, phone extension, department, and
status.
Change the Supervisor user name to your name and enter a new password
Enter any more information you wish to store, and click on the Finished button
439
440
Click on the User Admin option and click on the Add User button, or you can rightclick on the list of users and select Add User
Add the new user information, including the username and password; you can add the
phone extension number and department name for the user as well
Change the type of user as appropriate; a new user is set to Participant by default
Click on the Finished button and you are prompted to Save the Changes
Checking in Components
To change an existing users definition
Select the user in the list and change the user details,
Click on the Finished button and you are prompted to Save the Changes
Do not change the status of the Supervisor user, particularly if you have only one user with
Supervisor status. If you change the status of the Supervisor user you will no longer be able
to manage the project and its users.
To delete a user
Select the user in the list and click on the Delete button
Click on the Finished button and you are prompted to Save the Changes
Checking in Components
The final step in setting up your project is to check the components in your application into
the VCS. You can check in complete Omnis libraries to include all the classes in those
libraries, you can check in individual classes from any number of different libraries, and you
can check in a whole folder hierarchy containing all the necessary files for your application.
Once you have checked all the components in, other users can build a local working version
of your library or project using the Build Project option.
Open the Studio Browser and your library containing the Omnis classes you want to
check in to the VCS
Display the classes in your library, and drag and drop your library or selected classes
onto the VCS node in the Studio Browser tree (or if you have created a project
manually, you can drop the components on the project name)
or you can
Select your library or individual classes in the Studio Browser, right-click on the
object(s) and select the Check-in option from the context menu
Whichever method you choose, the Check in components dialog appears. This dialog lets
you set the check in options for the selected components. If you check in a library all the
classes in the library are checked in automatically.
Select the Add new component radio button, and type Initial check in or something
similar in the Check In Notes field
Version Numbers
The version string for each component is currently set to 1. You can enter a special
version in the Version field if you want to use a different numbering scheme, although this
is not recommended. All the components in the VCS have both a version and a revision
number, each of which is an integer value. The version indicates the major revision or
release of a component and typically applies to all the classes in the library, so its
effectively the version of the library. The revision number indicates a relatively minor
change to the component. When you first check in a component, you can assign it a version;
the VCS automatically sets this to 1 and the revision number to 0. Each time you check in a
component, the VCS assigns a new revision, but the version doesnt change unless you
change it explicitly in the check in dialog.
A progress bar shows the number of components added. When all the components are
checked in, the project appears in the VCS tree, with the same name as your library.
442
Checking in Components
File Browser
To check in non-Omnis components you use the File Browser available within the VCS
itself.
Important Note: You can check Omnis library files into the VCS using the File Browser,
but this is only appropriate if you want to manage the library as a discreet disk file.
However, if you want to access all the classes in the Omnis library, you should check the
library into the VCS as separate classes, as described in the previous section, and not using
the File Browser.
To check non-Omnis components into the VCS
Select your project under the VCS node in the Studio Browser (not in the right-hand
pane)
Click on the File Browser option
Locate the files or folder you want to check into the VCS using the Select Files/Folder
button
From thereon, the check in process for non-Omnis components is exactly the same as for
Omnis classes, that is, the Check in components dialog appears which lets you set the check
in options for the selected components.
If you check in a folder, all the files and all subfolders and files within that folder are
checked into the VCS. In this case, you could, for example, check in a complete folder
structure containing your own Help system.
Select the project name in the VCS tree, or double-click on the project icon in the VCS
Browser
You may find the Details view most useful when viewing the components in a project, since
that view shows information such as the version, the status, which user has checked each
component in or out, and so on. You can change the view using the View menu on the main
Studio Browser menubar. In addition, you can sort the contents of your project by clicking
on one of the column headers in the VCS Browser.
443
Project Folders
You can create folder classes in an Omnis library to allow you to store and organize the
classes within the library. When you check a library into the Omnis VCS these folder
classes are copied into the VCS project. It is also possible to create a folder class directly
within a VCS project via the hyperlink option New Folder available at the VCS project
level. This will allow you to organize the classes in your VCS project, but will also allow
you to organize non-Omnis objects such as external components.
Depending on how a project folder is created and what it contains, it can have one of three
possible states:
a normal folder is one that is generated withing an Omnis library and contains only
Omnis classes
an external folder is one that is generated from within the VCS
a hybrid folder is one that contains both Omnis classes and non-Omnis Objects
Building a Project
When you build a project, normal folders will be built in the destination library as at
present. External folders will be built into the file system using the folder name as a
directory appended to the build path with any non-Omnis Objects built there. A hybrid
folder will build a folder class in the Omnis library along with any Omnis classes inside it as
well as building to the file system.
444
Checking in Components
Select the set of components for which you want to grant the privileges
Click on the Privileges option or right-click on the component(s) and select the
Privileges option from the context menu
The Assign Component Privileges window lets you assign privileges for specific
components to particular users.
Alternatively, you can check the Assign privileges when checking in for the first time
option under the Check In tab on the VCS Options dialog to ensure that all users are granted
access to all components in your project automatically when you first check in the
components.
For more details about assigning privileges to components see the Managing Components
section.
445
Click on the Open Session option and select the appropriate project in the list
If you dont have a valid user name and password, you can sign in as a temporary user by
checking the Observer check box. An observer can view information about the components
stored in a project, but cannot check components in or out, or perform any other VCS tasks.
Alternatively, you can check the Create User check box to create a new user and password,
which signs you in with Participant status. The Supervisor can change your user status at a
later stage if required.
Display the components in your project by double-clicking on the project in the VCS
Browser, or selecting the project name in the VCS tree
Select the components in the VCS Browser that you want to check out or copy out
Select the Check Out option, or right-click on the component(s) and select the Check
out option in the context menu
Drag the classes from your VCS project and drop them on the appropriate library in the
Libraries node in the Studio Browser
In the Check out dialog, select either Check Out or Copy Out and whether the
component should overwrite an existing one or prompt for a new name (you can change
the default for both these options in the VCS Options)
You can add a description for the checking or copying out process
You can add a separate note for each component by clicking the Expand Notes button.
Click on Continue
If the VCS cannot locate the original library for an Omnis class, it will prompt you to select
a target library. You should select a library, or skip this component. The VCS may prompt
you to locate a library for further classes. For non-Omnis components the VCS prompts you
for a destination folder.
If you check out an Omnis class that has a superclass or belongs to a design task, read-only
copies of the superclass(es) and design task are copied out, assuming the Automatically
copy out related components preference is enabled in the VCS options.
In the Libraries tree, Omnis classes are shown as checked out with a lock icon.
Updating Properties
When checking out a class, you can update the destination library properties with the
properties that are held in the VCS for that project. This is especially useful for situations in
which there are multiple developers working on the same project. You can enable this
feature by checking Update the destination library with preferences from the VCS option
on the Check Out tab of the VCS Options.
447
Drag the selected component(s) on to the appropriate project in the VCS Browser
or
Right-click on the component(s) and select the Check In option from the context menu
Assuming your project is selected in the VCS, click on the File Browser option
Locate the folder containing the files your want to check into the VCS
For all types of component, the Check in window appears which lets you set the check in
choices for the selected components, as already described in the Setting up a Project
section.
448
449
Building Projects
The Omnis VCS lets you build a project on your local workstation, or any other destination,
from the components stored in the VCS repository. You can do this at any time using the
Build options in the VCS. You can also build projects at a specific time and date using the
Scheduled Build option, which is described in the next section in this chapter.
Building any type of project from the VCS guarantees that all the components in your local
copy are up-to-date. In the context of Omnis application design, building a project means
creating a library containing up-to-date classes for you to work on or test. If your Omnis
application contains multiple libraries, doing a build from the VCS guarantees that your
whole application is up-to-date. You can also build a project containing non-Omnis
components and reproduce the original folder hierarchy required in your application. Using
the revision labeling features, you can build previous versions of a library or project for
comparison, troubleshooting, or debugging.
When you build a project that contains classes from more than one library, the VCS copies
all the components to a single library by default. However by setting the Build options you
can build classes to separate libraries, thus maintaining your original library structure.
You can update a local copy of a library in the Studio Browser using the Update from
VCS option. This is appropriate for updating single libraries, but is not appropriate for
building a complete project. The Update from VCS option is described later in this chapter.
To build a project with multiple libraries
Select the VCS in the Studio Browser and click the Options option
Click on the Build tab and check the Maintain Project Structure option; this will
ensure your project builds to multiple libraries where applicable
To build a project
Whether or not you are building to one or more libraries
The Build Manager lets you configure the project build in detail. It contains one line only if
you have chosen to build a project containing Omnis classes into one library, with the
project name as the library name. If you have set the preference to maintain your library
structure, the Build Manager lists each separate library in the project. If your project
contains non-Omnis components you can enter the name and path of the target folder.
450
Select the library or project and specify the Build options as follows
Type the path for your library or project in the Build into field or use the Browse
button to select a folder or create a new one
When you have set the options for your project, click on the Build button
451
Removing Comments
When you create a build from the VCS, you can remove the comments from the code in
your libraries by checking the Strip Comments check box. If the option is set, all
comments within methods are removed, as well as all variable definitions, and descriptions
for file, query, and schema classes. This will make library files smaller, which may be better
for deployment.
You can select classes that you want to retain their comments when you build a project. To
do this, right-click on the list of projects in the Build Window, select the Do Not Strip
Comments option, and select the classes in which you want the keep comments.
Under the Build tab in the VCS Options window, there are four checkboxes that, if checked,
will ensure that comments in variables, file classes, query classes and schema classes are
retained.
System Tables
When you build a library, the VCS includes the system tables by default, assuming you have
copied them to your project. The system tables contain library-specific settings such as
fonts, input masks, field styles, and in the case of #ICONS the icons in your library, so they
are important in maintaining the correct look-and-feel and behavior in your application.
Remember that when you check in a version of the library, the VCS does not automatically
put the system tables into the library; you must specifically show and select them in the
Studio Browser just as you do the other classes in your library.
452
Scheduled Builds
The Omnis VCS allows you to build projects at a specific time and date, which for large
development teams may be useful if you need to build a library out of office hours. You can
set up a Scheduled Build from the Scheduled Build option in the main Omnis VCS
Browser. When you select this link, the Build Manager will open containing a new button
called Schedule, which opens the Schedule Build Process window.
The Schedule Build window allows you to control the frequency of the builds and set the
time that you want the build to run. The following options are available:
Never
no scheduled builds occur, but you can still build a project manually
Daily
the build will occur every day at a specified time
Weekly
you can specify which day(s) of the week the build should occur during the week; you
can also set the time
Monthly
the build will occur once a month, on the specified day of the month; you can also set
the time
The best time to schedule the build is when there is no one else logged on to the VCS. You
must ensure that Omnis Studio is running at the time of the build and that you are logged on
to the correct VCS repository. If you do not have Studio open at the time of the build
schedule, when you next log on during that day, the VCS will prompt you that you have
missed the scheduled build and ask if you want to run it then. For example, if you have the
build set to run at 7am on a Monday, but do not start Omnis until 8am, Omnis will remind
you about the build that you missed.
You should use the Build Manager window to define the projects you want to build and
how you want them to be built using the normal options that are available. When you click
the Finish button these preferences will be saved and the timer started according to the
schedule defined.
Labels
You can choose to label the build either at the time you schedule the build or when the build
runs. Note that if you select Label at Build and there is already a label with that name, the
VCS will redefine the label with the current state of the classes. This may or may not be
what you require, so caution should be exercised, particularly if you are setting the build to
run every day and therefore you may lose the ability to rebuild to a specific point in the
project development at a later point in time. If you select Label Now, the VCS will prompt
you if there is already a label defined and give you the chance to confirm that you want the
label redefined.
453
Locked or unlocked
You can specify whether the VCS builds a locked or unlocked version of your library (or
both) using the Library Status dropdown list in the Build window.
Build notes
If you have selected a path to save them into, the build notes will be saved to a file prefixed
AutomaticBuildNotes_ within that path. By default the path is the BuildFolder within the
main Studio folder.
Project Branching
The Omnis VCS allows you to create branches within the current project, based on the
contents of your original project. You are then able to make changes or additions to the
branches in your project, thereby in effect making different versions of the same
project/application. The ability to create branches may be of real benefit to developers who
have different customers with differing or urgent requirements, outside of your normal
product release cycle. In this case a branch can be created and tailored to an individual
customer, perhaps to provide them with an urgent patch.
Project branching allows you to create and maintain multiple development paths alongside
each other within a single project. Each branch is based on the original project branch, but
is independent of each other.
Note: please note there is no function at present to merge different branches, so you should
think very carefully before creating multiple branches in a project and allowing separate
independent development paths to be created.
Creating a Branch
You can create a branch by clicking the Make Branch hyperlink in the Omnis VCS
browser window. By default the new branch will be called _Branch_1, but you can rename
it either at this point or after creation using the Branch Manager tool. When you create a
new branch, you can set it to be the default branch, although youll probably want to keep
the original branch as the default: see below.
The VCS creates the new branch and places the contents of your original project in another
branch called _Trunk. At this point the new branch will be identical to the contents of
_Trunk. Any assigned user privileges in the original project are carried over to the new
branch. The VCS displays the two new branches or nodes underneath the original project
name.
There is no difference between the _Trunk and any other branch, that is, all branches have
the same properties, so the Trunk simply identifies the contents of your original project.
You can create as many branches as you wish, attached to the main Trunk, but you cannot
create a sub-branch, that is, a branch of a branch.
454
Branch Options
There are two new options that allow you to manage the Checkin/Out process for projects
that contain branches. See the VCS Options section in this chapter.
Managing Branches
The Manage Branches window lists all the branches defined for a project and allows you to
label or delete branches. You can open the window from the Manage Branches hyperlink in
the VCS browser.
Deleting a Branch
You can delete any branch apart from the _Trunk. To delete a branch you can use the
Manage Branches window or Delete Branch hyperlink. If all branches are deleted from a
project, the _Trunk is also removed, and all classes belonging to the _Trunk are reassigned
to the original project.
An Example Scenario
Consider the following scenario: An Omnis developer releases a version of their application
and begins work on the next version, checking changes into the VCS as the project
progresses. Then a bug is identified in the released version which requires an urgent fix,
perhaps for a particular customer who cannot wait until the next release to receive the fix. In
this case, the developer could add a branch to the project, make the fix in the new branch
and release an interim fix to satisfy the customer.
After the interim release is made, further work may be carried out on the main product
branch (probably the Trunk/Default branch), which will then be released at some time in the
future. In this case, the main product will not include the urgent fix, since it was made to the
455
Labels
In long-term projects, the components in your project may undergo many revisions. The
VCS tracks these revisions using labels. You can reproduce a particular version of a library
using the appropriate label. A label is a string of up to fifty characters that you can assign to
a project and each of its components. When a project is complete and you want to release it,
you can assign a release name by labeling the project. You can see the label for a project or
individual component in its Information window.
To label a project
Once a project has been labeled, the last label assigned is shown in the VCS Project
Browser if the browser is in Details view.
When you build a project, you can use labels to select either the latest version of all the
components, or an older version. You can also check out a specific revision of a component
using its label. See the description of the Check Out process in the section on Managing
Components below.
If you delete a component that has a label, it remains in the VCS. If you build a project
using that label, the VCS finds and includes the component in the build even though you
have deleted it from later revisions of the project. The VCS does not include the component
in any builds or labels that occur after you delete the component. For example, if you label
a project and its components on Monday, delete a component from it on Tuesday, and do a
build on Wednesday using Mondays label your library will include the component.
However if you do a build on Wednesday using the most recent project label, your library
will not include the component you deleted on Tuesday.
Finding Classes
The Find Class option in the VCS Browser lets you search for a class within the current
VCS repository. You can search for a class within one or more projects. A list of matching
456
Read-only classes
When you try to modify a class in a library built from the VCS, it is only possible to edit the
class when the class is checked out. If it is not possible to edit the class, the class is
considered to be read-only.
1.
If a library has a non-empty VCS build date, then all class editors behave in a read-only
fashion, when $showascheckedout is kFalse for the class being edited.
2.
You can disable this behavior using the $alloweditifnotcheckedout Omnis preference
($root.$prefs) which is set to kFalse by default. Set it to kTrue, to disable this behavior.
3.
When this behavior is enabled, new classes in a library with a non-empty VCS build
date (created in any way), are automatically marked as checked out.
4.
Replace will not work against a read-only class, an error is written to the find and
replace log.
Note that this does not affect the notation (although the notation inspector will not allow
changes to a read-only class).
457
Managing Components
The VCS has an extensive array of component management functions, including
Granting user privileges for components
Associating a component with more than one project
Managing revisions of components
Deleting and renaming components
Display the components in your project by double-clicking on the project in the VCS
Browser
Select the set of components for which you want to grant the privileges
Click on the Privileges option or right-click on the component(s) and select the
Privileges option from the context menu
The Assign Component Privileges window lets you assign privileges for specific
components to particular users. You can choose one of the following levels of privilege
Read/Write
the user may check in, check out, copy out, get information on and build libraries with
components
Read Only
the user may get information on, build libraries with, and copy out a component into a
local library, but cannot check out the component nor check it back in with changes
Info Only
the user may get information only about a component
Select one of the levels of privilege and click the Set button to grant the privileges
Assigning the Info Only privilege also revokes existing privileges from a user. Info Only is
the default privilege that any user has for a component. The owner of the component must
458
Managing Components
grant the user, including Supervisors, the Read Only or Read/Write privileges necessary for
building libraries or changing the component.
By default, the owner of a component starts with Read/Write privileges for that component,
and you must have Read/Write privileges to grant privileges for it to other users.
If you select components for which you dont have Read/Write privileges, the VCS disables
the radio buttons and Set button. If you select components for some of which you have
Read/Write privileges, you can use the radio buttons. The VCS does not however, grant the
privileges to the user(s) on those components for which you do not have Read/Write
privilege.
Open the project containing the component, and select the component
Click on the Link option, or right-click on the component and select the Link option
from the context menu
The Link option displays a window showing all your open projects (the link window will
not open if there are no other open projects, or if the component is already linked to all
other open projects).
Select the project with which you want to link the component, or you can open a
project in the list and select a particular library
Click OK to link the component
If the Maintain Project Structure build option is not checked, the component is associated
with the single library together with all the other components. Otherwise if the build option
is enabled, the component is associated with a library of the same name as the one
containing it. If such a library does not exist, it is created automatically.
To delete a linked component in a specific project
459
Select the component, and click on the Delete option, or right-click on the component
and select the Delete option from the context menu
If the component has a label, it becomes disassociated and a small trash can icon is shown.
If you build a project using a label, the component is still available for the build, even
though the library or project in question may no longer associate with the component.
Managing Revisions
When you first check in a component, the VCS creates the component in its repository and
sets the version to 1 and the revision to zero. Each time you check in a new revision of the
component, the VCS stores the new component and increments its revision number. The
sequence of changes to a component is stored in its revision history.
To see the revision history for a component
460
Managing Components
Method Inspector
The Method Inspector lets you examine the methods in a class without having to Check Out
or Copy Out a class or build the library. This may be useful if you want to quickly check
what methods are contained in a class or what code is contained in a particular method
within a class.
To open the Method Inspector, you can select the class and choose the Method Inspector
hyperlink option in the VCS Browser, or Right-click on the class and select the option from
the context menu.
On the first tab of the Method Inspector window, there is a list of all the methods within the
class. If the class has a superclass, the superclass methods are also shown. They are
displayed in blue to differentiate them as inherited methods.
If the selected class is a window, report, remote form, menu or toolbar, there is another
checkbox displayed at the bottom of the list to allow you view field methods. By default this
option is not selected except for menu and toolbar classes.
Further properties of the method are shown in this tab: description, execute on client and
web service method. There is also a context menu option to allow you to view the path to
the method within the class this is of most use if you are looking at field methods as you
can see the exact path to the method.
If you double-click a method, the code for the method is displayed on the second tab.
Should the method be inherited, there is a context menu option to allow you to view the
superclass code.
Orphan Components
It is possible for a component that has a parent folder to lose its parent folder; in this case,
the component is regarded as an orphan component. A component can lose its parent
folder either because the parent folder itself no longer exists, or the id of the parent folder
has changed and the component is not aware of the change. The id of the parent folder for a
component is stored in its $parentfolder property.
The Find Orphans option in the VCS will look for components where their $parentfolder
id does not exist and place these components in the Orphans folder. You can move the
component(s) back to their respective folders or recreate the appropriate folder. In most
cases, the option will return no orphan components.
461
Component Services
The Component context menu gives you information about a component, and lets you
rename, delete, or unlock a component. To open the context menu you must right-click on
the component.
To get Info about a component, or rename, delete, or unlock one
Right-click on the component in the VCS and select the appropriate menu option
Click on the Info, Delete, or Unlock option in the list of options in the VCS Browser
Get Information
This window displays the information about the component, including the labels, the
revision state, the check out history, and links.
Deleting Components
To delete a component, you must own the component and it must be checked in. The Delete
option checks whether the component belongs to more than one library and whether any
labels apply to it. If not, the VCS prompts for confirmation that you want to delete the
component. If it does belong to more than one library, the VCS displays a list of associated
libraries, letting you choose the ones from which to remove the component.
Unlocking Components
You can unlock a locked component by clicking on it and selecting the
Component>>Unlock menu option. A warning message advises you that having done this,
you will not be able to check in a previously checked out version of the component.
Renaming Components
To rename a component, you must own the component and it must be checked in. You can
rename any component in the VCS, but renaming Omnis classes requires some additional
care because of the potential dependencies of some classes on the class you want to rename.
That is, before you rename a class in the VCS you must change all references to it in any
other classes that refer to the class. You do this by checking out all the relevant classes to
the IDE Browser and using the Omnis Find and Replace tool.
462
Managing Components
To rename a class
Check out the class and any other classes that contain methods which refer to the
component
Change the name of the component in the Studio Browser, and answer Yes when you
are prompted for whether or not you want to use Find and Replace; this renames the
component and changes all references to it in any other components
Check in all the components except for the renamed one
Select the component in the VCS, and click on the Unlock menu option to release its
lock
Comparing Classes
The Compare Classes option in the VCS lets you compare all the classes in two different
VCS projects, or it lets you compare individual classes in different projects. It also lets you
compare different revisions of the same class. (The Compare Classes tool is also available
in the Studio Browser and allows you to compare classes in libraries not checked into the
VCS.) The Compare Classes tool compares the properties and methods of the specified
classes and highlights any differences. Specifically, the comparison tool will compare each
line in a method of one class with the corresponding lines in a method of the other class and
will highlight even the smallest change or difference between the two classes or revisions.
To use the Compare Classes tool
Select a project or component and click on the Compare Classes option in the VCS
Browser
The Compare Classes tool is also available in the Revision History window to allow you to
compare revisions of the same class.
The Compare Classes window lets you load two different versions of the same VCS project
or library: you should load the older project or library into the Library/Project A list (on the
left) and the newer version into the Library/Project B list (on the right). The context menu
on the Compare Classes window (Right-click to open it) lets you switch libraries from List
A to List B.
You can compare all the classes in a VCS project or library that have a modified $classdata,
which avoids comparing classes that have not changed. The Compare tool shows which
classes have a modified $classdata and by default will compare only these classes. You can
463
VCS Options
You can set your individual preferences for the VCS using the Options option in the list of
options in the VCS Browser. You can set Display, Check out, Check in, Build, Method
Inspector, and Branches options in the VCS Options window.
To set your VCS options
Select the VCS in the Studio Browser, or select a project, and click on the Options
option
Display Options
The Display options let you specify the format of dates and times for the VCS windows and
dialogs. The default format is: D m Y H:N:S, such as 12 May 09 14:30:35.
Show linked icon
(disabled by default) enables the Linked icon for classes and components that are
linked across different projects using the Link option.
VCS Options
the superclass. If this option is set, read-only copies of the superclass(es) are copied
out, as well as the design task for the original classes being checked out.
Default to copy out component if already checked out
when this option is set, it forces components to be checked out even if they are already
checked out. If unchecked, the VCS will warn you that the component is already
checked out and prompt you to Copy out or cancel the operation.
Maintain superclass / design task library name
ensures that classes retain the library name as part of the superclass or design task
name. The preference is unchecked by default to ensure backward compatibility. With
the preference disabled, the library name is stripped out at checkout or build time. This
means that if, for example, you have LibraryA with a class called classA which has a
superclass LibraryB.ClassSuper and there is also a ClassSuper in LibraryA, Omnis
would switch the superclass to LibraryA.ClassSuper whenever the class is checked
out or built. You can check this option to retain the superclass name to avoid this
problem.
Update the destination library with preferences from the VCS
ensures that when checked the preferences of the destination library are updated from
those stored in the VCS.
Check In Options
The Check In options control how components are checked in to the VCS.
If Target Component Does Not Exist
controls what happens when you check in a new component. By default, the
Automatically add it to the Project option is selected and components are added to a
project automatically; otherwise if the Prompt for further instructions option is
selected the VCS asks if you want to add the component to the current VCS project.
When Component Version Number Changes
controls revision numbers for new versions of a component. By default, the Reset
revision numbers to zero option is selected and revision numbers are set to zero for
new versions; otherwise if the Continue to increment revision numbers option is
selected the VCS continues to increment revision numbers regardless of the component
version. (Version and revision numbers are described earlier in this chapter.)
Assign privileges when checking in for the first time
is useful when, as supervisor, you first set up your project. When enabled and you
check in components into the VCS for the first time, the component privileges window
is opened allowing you to set the access privileges for each component.
Disable automatic library preference changes
If enabled, this option prevents the automatic updating of library preferences from the
library containing the classes to be checked in.
465
Build Options
The Build options control builds in the VCS.
Maintain Project Structure
controls whether or not a build retains the library structure of the components within a
project. If this option is checked, components are built into separate libraries mirroring
the original library structure, otherwise all the components in a project are built into a
single library.
Warn if there are classes currently checked out
tells you if there are any classes checked out when you attempt to build a project; if you
build a project containing checked out classes your library may not contain the most
up-to-date version of classes
Only create locked and unlocked folders when required
Selecting this option prevents the VCS from generating locked and unlocked folders in
the build path unless the Build process needs them.
Stripping Comments
During a build all comments in your Omnis code are stripped out. When checked, the
Stripping Comments options ensure that comments are retained in all Variable
definitions (in the Variable pane of the Method Editor), as well as all File, Query, and
Schema classes.
Branches Options
The Branches options only affect projects that contain branches; the options are ignored for
projects without branches. The Checking in/out options on the Branches tab allow you to set
the check in/out preferences for VCS projects that contain branches.
Use Default Branches
If the Use Default Branches option is checked (the default) and the current project has
branches, the default branch is used to check out classes when using the context menu
466
Reports
in the Studio browser. If the option is unchecked, a list of available branches is
displayed to allow you to choose the branch from which to check out the class.
Ignore Branches
If the Ignore Branches option is checked (the default), the VCS automatically uses the
branch the component has been checked out from. If the component is present in more
than one branch, a window is displayed to allow you to choose the branch from which
to check out the class or component.
Reports
The VCS has a number of reports available to those with Supervisor status. You can access
them by clicking the Reports option in the VCS Browser. Users without supervisor status do
not have access to VCS reports and will find this menu option is grayed out.
To use the VCS reports
Select the VCS in the Studio Browser tree and click on the Reports option
The VCS Management Reports dialog lets you select a report. The Parameters pane and
Description field will change depending on the report you click on.
Branches
Where appropriate, the reports in the VCS will reflect the existence of branches in your
projects.
467
Index
Index
# variables, 67
#BFORMS, 47
#DFORMS, 47
#ERRCODE, 91
#ERRTEXT, 91
#EXTCOMPLIBS, 47
#F, 72
#FD, 56
#FT, 56
#ICONS, 47
#MARFONTS, 47, 393
#MASKS, 47
#MAWFONTS, 47
#MXRFONTS, 47, 393
#MXWFONTS, 47
#NFORMS, 47
#NULL, 60
#PASSWORDS, 47
#STYLES, 47, 441
#TFORMS, 47
#UXRFONTS, 47, 393
#UXWFONTS, 47
#WIRFONTS, 47, 393
#WIWFONTS, 47
$accumulate(), 383
$activate(), 107
$add(), 77, 144, 167
$addafter(), 167
$addbefore(), 167
$addcustomtype(), 309
$allowstransactions, 205
$allrowsfetched, 247
$alwaysprivate property, 110
$appendfile, 381
$assign(), 77
$assigncols(), 170
$assignrow(), 170
$attributes, 144
$autoactivate, 107
$autobegintran, 206, 207, 330
$average(), 169
$backendpid, 307
$batchsize, 190
$begin(), 206, 219, 299
468
$bindshort0dpassmallint, 279
$blobsize, 214
$calculated, 91
$cancel(), 309
$cancelresultset(), 279
$canclose(), 378
$cangeneratepages, 378
$cankeepopen, 378
$cclass, 74
$cdata, 74
$cdevice, 377, 384
$centuryrange, 57
$cfield, 74
$changeuser(), 296
$char38touuid, 308
$characterset(), 296
$charmap, 210
$charsperinch, 381
$charsperline, 381
$checkbreak(), 383
$cinst, 74
$class, 166
$classes, 25
$clear(), 167, 169, 198, 219, 224
$clearremotepasswords(), 278
$clib, 74
$clientflags, 295, 299
$close(), 108, 378
$close() method, 77
$cmethod, 74
$cobj, 74
$colcnt(), 421
$colcount, 166
$collectperformancedata, 134
$cols, 166
$colsinset, 246
$colsublen, 169
$colsubtype, 169
$coltext, 219
$coltype, 169
$columns(), 200, 224, 298
$commit(), 206, 219, 299
$compevents, 114
$compfuncs, 114
Reports
$componenticon, 140
$components, 113
$comprops, 114
$configdsn(), 332
$connectoption(), 296
$connectstatus(), 309
$constprefix, 113
$construct(), 59, 106, 243, 427
$controlhandler, 113
$controls, 113
$copies, 383
$copydefinition(), 167
$copyref(), 153
$count(), 169
$cparmcount, 74
$createname(), 245
$createnames(), 194, 219, 252
$crecipient, 74
$ctarget, 74
$ctask, 74
$ctask, 109
$cterrorlayer, 277, 279
$cterrornumber, 277, 279
$cterrororigin, 277, 279
$cterrorseverity, 277, 279
$currentcontents, 175, 176
$cursorsensitivity, 330
$cwind, 74
$database, 295, 299, 307
$datesecdp, 329
$datetimeformat, 290
$dbmsname, 327, 341
$dbmsversion, 327, 341
$deactivate(), 107
$defaultdatabase, 327
$defaultdate, 213
$defaultname, 44
$defaultschema, 329
$defaulttask, 105
$define(), 167
$definefromsqlclass(), 61, 62, 63, 160, 167,
236, 238, 242
$delete(), 162, 244, 249
$deleteref(), 152
$designtaskname, 66, 69
$devices, 377
$disablereportcopy, 373
$dodelete(), 245, 251
$dodeletes(), 244, 250
469
Index
$getparam(), 400
$gettablelist(), 421
$gettext(), 421
$group, 170
$hascurrlangnationalsortorder, 433
$height, 388
$hideuntilcomplete, 381
$hostinfo, 295
$hostname, 185
$iconid, 377
$idelistpointsize, 12
$ident, 170, 377
$importencoding, 415
$includelines(), 178
$indexes(), 200, 224
$insert(), 161, 244, 249
$inserted(), 296
$insertnames(), 194, 219, 245, 253
$inst, 387
$inuse, 217
$isa(), 141
$isfixed, 166
$isolationlevel, 330
$isolationoptions, 330
$isopen, 377
$isprivate property, 109
$issupercomponent, 140
$istext, 382
$istextbased, 377
$itasks, 104
$iwindows, 72
$language, 432, 433
$left, 388
$libs, 72
$line, 166, 171
$linecount, 166, 176
$linemax, 166, 189
$linesperinch, 381
$linesperpage, 381
$listrefs(), 152
$loadcols(), 170
$loadcolumn(), 421
$loadexistingtablefromlist(), 421
$loadlistfromtable(), 421
$loadpagesetup, 385
$loadstringtable(), 421
$loadtablefromlist(), 421
$lobthreshold, 215
$local
470
Reports
$pages, 380
$pagesetupdata, 385
$paper, 382
$paperlength, 382
$paperwidth, 383
$parameterstatus(), 309
$password, 185
$pathname, 113
$ping(), 296
$plsql(), 261
$plsqlarraysize, 261
$poolsize, 217
$port, 295, 299, 307
$portdatabits, 382
$porthandshake, 382
$portname, 382
$portparity, 382
$portspeed, 382
$portstopbits, 382
$posdelete(), 261
$poshorzpage, 388
$posmode, 387
$possectident, 388
$posupdate(), 261
$posvertpage, 388
$prepare(), 186, 224
$prepareforupdate(), 261
$primarykey, 237
$print(), 94, 386
$printfile, 380
$printheight, 367
$printif, 368
$printrecord(), 376, 383
$printsection(), 383
$printtotals(), 383
$programname, 277, 328
$protocolversion, 307
$protoversion, 295
$proxyas(), 258
$query(), 296
$queryinfo(), 297
$queryresult(), 297
$querytimeout, 277, 328, 341
$readcharacter(), 415
$readonly, 308
$redraw(), 78, 92
$refilter(), 179
$remove(), 144, 167
List column, 169
471
Index
$sendformfeed, 381
$sendtext(), 379, 400
$sequencetoint, 308
$serializable, 308
$serverdebuginfo(), 297
$servershutdown(), 297
$serverstatus(), 297
$servertablename, 237
$servertablenames, 246
$service, 307
$sessionname, 246
$sessionpools, 215
$setcolumn(), 422
$setdatatypemapping(), 297, 301
$setdriver(), 342
$setinfo(), 332
$setoption(), 333
$setparam(), 400
$setremotepassword(), 278
$skipsection(), 383
$smartlist, 166, 174
$socket, 295, 299, 307
$sort(), 168, 173
$sorts, 369
$sqlclassname, 242, 246
$sqlerror(), 162, 246, 252
$sqlstate, 311
$sqlstripspaces, 213, 305
$sqltext, 187, 208
$startpage(), 383
$startuptaskname, 105
$state, 185, 186, 187, 206
$statementname, 186
$status, 175, 176
$stringtabledata, 420, 426
$stringtabledesignform, 426
$stringtablelocale, 426
$superclass, 216
$suspend(), 108
$tables(), 199, 225
$tasks, 104
$threadid, 295
$threadsafe, 295
$timezone, 307
$title, 377
$toolbars, 25
$top, 388
$topwind, 75
$total(), 170
472
$totc(), 168
$transactionmode, 205, 299
$transactionstatus(), 309
$truetext, 260
$trustedconnection, 328
$txncapability, 330
$undodeletes(), 245, 251
$undoinserts(), 245, 251
$undoupdates(), 245, 251
$undowork(), 245, 252
$unfilter(), 179
$unicode, 404
$unloadall(), 422
$unloadstringtable(), 422
$update(), 162, 244, 249
$updatenames(), 195, 220, 245, 253
$usage, 113
$usecursor, 208
$usefiledsn, 328
$uselogonprompt, 328
$useprimarykeys, 246
$useprogramname, 328
$usequalifiers, 329
$username, 185
$usetimezone, 308
$validateutf8, 406
$validref(), 153
$version, 115
$visible, 377
$waitforuser, 381
$wherenames(), 196, 220, 246, 254
$width, 388
$windowprefs, 381
$windows, 25, 72
$writecharacter(), 415
$writelob(), 279, 282
% numeric variables, 68
%% string variables, 68
Active task, 107
Add line to list command, 164
Add-Ons menu, 14, 16
Associating components, 459
Batch fetching, 190
Begin reversible block command, 90
Begin statement, 187
BEGIN statement, 206
Binary data type, 59
Binary objects, 214
Bind variables, 193
Reports
Blob size, 214
Boolean data type, 54
Branching Commands, 85
Break key, 88
Break to end of loop command, 88
Breakpoint command, 125, 129
Breakpoints, 125
Break on calculation, 126
Break on variable change, 126
Clear breakpoints, 125
Clear field breakpoints, 125
One-time breakpoint, 125
Browser, 9
Creating an object class, 147
Making a subclass, 137
SQL Browser, 28
Build list from file command, 164
Build list from select table command, 163
Building projects, 450
Calculate command, 80
calculated property, 398
Calculation errors, 92
Calculations
Omnis operators, 81
Square bracket notation, 81
Type conversion in expressions, 82
Using constants, 83
Using the Calculate command, 80
Calling methods, 83
Can Be Null field option, 60
Cancel button, 88
Cannot Be Null field option, 60
Case command, 87
Catalog, 27
Entering sort fields, 369
String Tables, 420
Viewing variables, 70
Century range for dates, 57
Character data type, 52
Character Map Editor, 14, 405
Character mapping, 209
Character Mapping
in Unicode Mode, 407
Unicode, 404
Character normalization, 409
Character translation, 412
Charmap.exe, 209
Checking in components, 448
Checking in non-Omnis components, 443
473
Index
Checking or copying out, 446
Component Store, 20
Deleting, 462
Managing, 458
Privileges, 458
Renaming, 462
Sharing components between projects, 459
Unlocking manually, 462
con(), 398
con() function, 60, 81
Connecting
JDBC, 342
Using methods, 183
Constants, 83
Container fields and events, 103
Context menus, 17
Control methods and passing events, 101
Copying out VCS Components, 446
CRB, 60
CREATE TABLE statement, 194
Creating a new project, 441
Current objects, 74
Current record buffer, 60
Current task, 108
Cursor results sets, 208
Custom methods, 143
Custom printing devices, 398
DAMs, 28, 182, 257
Unicode, 404
Data classes, 48, 50
Data type mapping, 50
Data dictionary, 199
Data File Conversion
Unicode, 403
Data mapping, 186
Data type mapping, 50
Data Type Mapping
DB2, 293
JDBC, 343
MySQL, 300
ODBC, 338
Oracle, 274
PostgreSQL, 314
Sybase, 288
Data types, 51
Binary, 59
Boolean, 54
Character, 52
Date time, 55
474
Field reference, 60
Item reference, 59
List, 58
Mapping Omnis to SQL, 197
National, 52
Number, 53
Object, 58
Object reference, 59
Picture, 58
Row, 58
Sequence, 57
Databases
Describing your database, 199
Date time data type, 55
Date time data types
Date and time calculations, 56
Date ranges, 57
Long date and time, 56
Short date, 55
Short time, 56
Date values, 213
DB2, 290
Connecting, 291
Data Type Mapping, 293
Dates, 291
Reserved words, 292
Transactions, 291
Troubleshooting, 292
DDE/Publisher report device, 375
Debug next event, 128
Debugger
Adding comments, 120
Execution errors, 121
Go point, 120
Private methods, 122
Stepping through methods, 121
Tracing methods, 122
Debugger commands, 129
Debugger options, 128
Debugging methods, 119
Breakpoints, 125
Inspecting variable values, 123
Method stack, 127
Using the method checker, 130
Watching variable values, 124
DECLARE, 208
Default classes, 46
Startup task, 46
System classes, 46
Reports
Default command, 87
Default library name, 44
Default task, 105
Define list command, 160
Define list from SQL class, 242
Delete Unused Variables, 69
Deleting data, 249
Descending sort option, 369
Describing results, 191
Describing your database, 199
Design mode, 15, 104
Design tasks
Checking out, 465
Desktop toolbar, 15
Devices for printing, 371
Diagnostic messages, 129
Disable debugger at errors, 128
Disable debugger method commands, 128
Discard event option, 99
Disk report device, 373
Do code method command, 83, 95, 109
Do command, 59, 76
Do default command, 80, 144, 386
in $print() method, 391
Do inherited command, 80, 142
Do method command, 66, 83, 95, 143
Do redirect command, 80, 144
Else command, 85
Else if command, 85
Empty values, 60
Enable cancel test at loops command, 88
End If command, 85
End of loop test, 88
End of report section, 363
End print command, 376
End reversible block command, 90
End statement, 187
Enter data command
Event processing, 102
Environment
Fonts, 12
Error handlers, 91
Errors
Calculations, 92
Escaping from loops, 88
evAfter, 95
evBefore, 95
evCanDrop, 98
evClick, 93
evClose, 100
evCloseBox, 100
evDrag, 98
evDrop, 98
Event handling methods, 64
Discarding events, 99
On command, 95
Quit event handler command, 98
Event messages, 93
Event parameters, 93
Event processing
Enter data mode, 102
Event queue, 103
Events
Mouse, 97
Events and messages
Container fields and events, 103
Control methods and passing events, 101
Event handling methods, 94
Queuing events, 103
Window events, 99
Events, discarding, 99
Events, queuing, 103
Events, window, 99
evKey, 101
evMouseDouble, 97
evMouseDown, 97
evMouseEnter, 97
evMouseLeave, 97
evMouseUp, 97
evRMouseDouble, 97
evRMouseDown, 97
evRMouseUp, 97
evWillDrop, 98
Examples, 9
External components
Events, 114
Functions, 114
HTML printing device, 398
HTML report objects, 401
Java beans, 115
Notation, 113
Properties, 114
Version notation, 115
External objects, 216
External Objects, 154
Events, 155
F1, Help key, 41
Fetch next row, 163
475
Index
Fetching data, 248
Fetching results, 188
External files, 189
Omnis variables, 189
Field reference data type, 60
File report device, 374
Fileops, 415
Find and Replace, 19
Find Next, 19
Flag, 72
Flow control commands, 85
Folders button, 9
Folders, Library, 10
Follow start mode, 366
Fonts, 393
Environment, 12
For each line in list command, 87
For field value command, 87
For Loops, 87
Formatting strings, 60
Formfile, 414
Frombottommarg start mode, 367
Fromend start mode, 367
Fromtop start mode, 366
Fromtopmarg start mode, 367
Get Info, 462
Get statement, 187
Go Point, 120
Hash variables, 67
Help, 41
Help tips option, 22
History, Revision, 460
Hold Updates option, 21
HTML device, 398
Parameters, 399
Sending text or data, 400
HTML report device, 374
HTML report objects, 401
If canceled command, 88
If command, 85
Indexes
Listing, 200
Indirection
Using Square bracket notation, 82
Inheritance, 136
Overloading and overriding, 138
Inheritance notation, 141
Calling properties and methods, 141
Do inherited command, 142
476
Reports
kStatementStatePrepared, 186
kUnknown, 205
Label reports, 397
labelcount property, 397
labelwidth property, 397
Large objects, 214
Libraries, 43
Default name, 44
Multi-library projects, 45
Private libraries, 110
Library
Properties, 44
Library folders, 10
List commands and smart lists, 180
List data type, 58, 158
List variables, 242
list() function, 164
Listing columns, 200
Listing indexes, 200
Listing tables, 199
Listing views, 199
Lists
Accessing columns and rows, 165
Building from Omnis Data, 164
Building from SQL Data, 163
Building list variables, 163
Clearing list data, 172
Declaring list variables, 159
Declaring row variables, 159
Defined from a query class, 160
Defined from a schema class, 160
Defining list variables, 160
Defining row variables, 160
Dynamic redefinition, 171
List and row functions, 164
Manipulating lists, 171
Merging lists, 173
Programming, 158
Properties and methods, 166
Properties of a list cell, 170
Removing duplicate values, 174
Searching lists, 172
Selecting list lines, 172
Smart lists, 174
Sorting lists, 173
Variable notation, 165
Viewing List Values, 164
Load error handler command, 91
Load from list command, 165
LOBs, 214
Oracle, 267
Sybase, 282
Local variables, 66, 68, 159
Locale Identifier, 412
locale(), 412, 429
Localization, 417
Localizing Omnis, 430
Omnis, 428
Remote Forms, 426
Long date and time type, 56
Loops, escaping from, 88
lst() function, 165
Make schema from server table command,
238
Managing components, 458
Mapping
Data types, 50
Memory report device, 374
Menus
Context menus, 17
Omnis menu bar, 15
Menus, Studio, 12
Merge list command, 173
Message boxes, 93
Method checker
Fatal errors, 131
Level 1 warnings, 132
Level 2 warnings, 133
Method Checker, 14, 130
Method editor, 118
Adding variables, 67
Method Editor
Adding a method to a report class, 376
Adding a method to a report field, 376
Command palette, 118
Context menus, 18
Declaring list or row variables, 159
Event handling methods, 94
Menubar and toolbar, 118
Method names and definition, 118
Variables panes, 118
Watch variables pane, 119
Method lines, 71
Method stack, 127
Stack list, 127
Methods, 71
Calculate command, 80
Calling methods, 83
477
Index
Commands, 72
Custom methods, 143
Debugging, 119
Debugging methods, 117
Do command, 75
dragging from the Interface Manager, 157
Error handling, 91
Event handling, 94
Executing using the Do command, 75
Field methods, 94
Flow control commands, 85
Inheriting methods, 138
Inserting and Editing, 118
Line methods, 94
Line numbers, 119
Message boxes, 93
Notation, 72
Overriding inherited methods, 139
Performance, 134
Quitting methods, 84
Redrawing objects, 92
Report and Field Methods, 375
Reversible blocks, 90
Sequence Logging, 135
Tool methods, 94
Using the method checker, 130
Window control, 101
Mouse events, 97
MultipleSelect property, 172
Multi-threaded server, 215
MySQL, 295
Data Type Mapping, 300
Logging on, 298
Transactions, 299
Troubleshooting, 305
Narrow Sections option, 364
natcmp() function, 432
National data type, 52
National Sort Ordering
Localization, 431
New Class templates, 49
New page sort option, 370
New Users, 14, 16
Newpage option, 366
nfc(), 410
nfd(), 410
No/Yes message, 93
Non-Omnis components
Checking in, 443
478
Reports
Operator precedence, 81
Optimizing methods, 89
Optimizing Program Flow, 89
Options, 464
Options (Preferences), 11
Oracle, 258
Connecting, 261
Data type mapping, 274
LOBs, 267
Troubleshooting, 275
Unicode, 262
Oracle 8, 267
Oracle 9i, 271
Overloading properties, methods, and
variables, 138
Owner of VCS project, 458
Page footer section, 363
Page header section, 363
Page layout, 389
Page setup, 385
pagefooter property, 364
pageheader property, 364
pagemode property, 366
pagespacing property, 366
Parameter variables, 66, 68
Reordering in the method editor, 68
Pass to next handler option, 101
Pass to other handlers option, 99
pEventCode, 93
Picture data type, 58
pKey, 101
PL/SQL, 263
Port Profile editor, 14
Port profiles, 395
Port report device, 373
Position sections, 367
Positioning
Report objects, 387
Positioning section, 363
PostgreSQL, 305
Client Libraries, 305
Data Type Mapping, 314
Logging on, 311
Remote Procedure Calls, 312
Transactions, 312
Troubleshooting, 318
Preferences, 464
Preferences, Omnis, 11
Prepare for print command, 376
479
Index
Query classes, 62, 236, 238
Calculated columns, 239
Notation, 239
Queue commands, 103
Quit all if canceled, 84
Quit all methods, 84
Quit command, 84
Quit event handler command, 98, 101
Quit method, 84
Quit method command, 99
Quit Omnis, 84
Quit to enter data, 84
Quitting methods, 84
Recent classes, 10
Record section, 363
Record Sequencing Number (RSN), 57
recordspacing property, 367
Redraw command, 92
Redrawing objects, 92
Ref Cursor data types, Oracle 8, 269
Remote Forms
Localizing, 426
Remote Procedure Calls
Sybase, 283
Remote Procedures, 202
Calling, 204
Listing, 202
Listing parameters, 202
Renaming objects, 20
Repeat Loop, 86
repeatfactor property, 397
Report and Field Methods, 375
Report destination dialog, 371
Report devices, 371
Clipboard, 373
DDE/Publisher, 375
Disk, 373
File, 374
HTML, 374
Memory, 374
Port, 373
Preview, 372
Printer, 372
RTF, 374
Screen, 372
Report field methods, 386
Report fonts, 393
Report heading section, 363
Report inheritance, 392
480
Reports
Context menus, 17
rnd() function, 54
ROLLBACK statement, 206
Row data type, 58, 158
Row variables, 242
row() function, 164
RPC method, 204
RTF report device, 374
Runtime mode, 15, 104
Save debugger options, 128
Schema classes, 61, 236
Building, 201
Notation, 236
Scope
Rescoping a variable, 69
Scope of variables, 65
Screen reports, 372
SEA commands, 91
Searching lists, 172
Section print height, 367
Section properties
Page Mode, 366
Record spacing, 367
Start Mode, 366
Sections, position marker, 366
Sections, Report, 363
Sections, Reports, 366
Select statement, 247
SELECT statement, 195, 208
Send to trace log command, 97, 129
Sequence data type, 57
Sequence Logging, 135
Server
Sending SQL to, 186
Server specific programming, 257
Server tables
Creating from schema and query classes,
241
Session methods, 219
Session objects, 182
Creating, 184
Logging on, 184
Session pools, 215
Session properties, 221
Session, Creating a, 438
Sessions, 28
Clearing, 198
Set reference command, 59, 73
Setting up a project, 437
481
Index
Statement methods, 224
Statement objects, 182
Creating, 185
Statement properties, 225
Statements
Clearing, 198
stgetcol(), 427
stgettext(), 427
String labels, 417
String Table Editor, 14, 417, 419, 428
String Tables
Catalog, 420
Functions, 421
Programming, 423
STRINGID, 419
STRINGID Locale, 420
StringTable component, 417
Stripping spaces
SQL, 213
stsetcol(), 427
Studio Browser, 9, 13
Class Wizards, 49
New Class, 49
Studio menus, 12
Studio toolbars, 12
studio.stb, 428
style(), 396
Subclasses
Making a subclass, 136
Subtotal heading 1 to 9 sections, 363
Subtotal heading section, 363, 370
Subtotal sections, 370
Subtotals in reports, 369
Subtotals level 1 to 9 sections, 363, 370
Subtotals sort option, 369
superclass property, 138
Superclasses
Checking out, 464
Switch command, 87
Sybase, 277
Connecting, 279
Data type mapping, 288
Error handling, 281
Lobs, 282
Multiple select tables, 280
Program Name, 280
Remote procedure calls, 283
Troubleshooting, 286
sys(85) function, 97
482
sys(86) function, 97
System classes, 46
System tables, 441, 452
Table classes, 62, 236, 242
Notation, 242
Table instances, 242
Methods, 247
Notation, 244
Tables
Listing, 199
task $control(), 101
Task classes, 104
Active task, 107
Closing tasks, 108
Creating tasks, 106
Current task, 108
Default and startup, 105
Design task, 109
Multiple tasks, 111
Opening tasks, 107
Private instances, 109
Private libraries, 110
Task variables, 108
Task context switch, 107
Task variables, 66, 69, 159
Testspace option, 366
text property, 398
Tools toolbar, 14
totalmode property, 370
Totals section, 363, 370
Trace all methods, 128
trace log, 122
Trace Log, 14, 16
Trace off command, 129
Trace on command, 129
Transaction modes, 205
Automatic, 205
Manual, 205
Server, 207
Transactions, 205
Type conversion in expressions, 82
unichr(), 412
Unicode, 402
Character Mapping, 404
DAMs, 404
Data File Conversion, 403
Data Handling, 413
What is Unicode?, 402
Unicode Clients, 412
Reports
unicode(), 412
uniconv(), 413
Unlocking components, 448, 462
Until break command, 88
Update files command, 58
UPDATE statement, 195
Updating data, 249
Upper case sort option, 369
Use search option, 173
User privileges, 458
userecspacing property, 367
Users
Adding and managing users, 440
Using tasks
Closing tasks, 108
Creating task classes, 106
Current and active tasks, 107
Default and startup tasks, 105
Multiple tasks, 111
Opening tasks, 107
Private instances, 109
Private libraries, 110
Task variables, 108
Using Tasks, 104
Values List, 123
Variable context menu, 70, 123
Variable Declaration and Scope, 65
Variable menu command, 129
Variable tips, 70
Variables, 65
Adding a variable, 67
Adding local variables, 68
Adding parameter variables, 68
Adding task variables, 69
Bind variables, 193
Building, in lists, 163
Class variables, 66
Context menus, 18
Declaring, in lists, 159
Defining, in lists, 160
Deleting unused, 69
Hash variables, 67
Initial values, 69
Instance variables, 66
Item references, 73
Local variables, 66
Naming, 68
Overriding inherited variables, 139
Parameter variables, 66
Task variables, 66
Viewing in the Catalog, 70
Watched, 124
VCS, 40, 43, 45, 435
Build options, 466
Check in options, 465
Check out options, 464, 465, 466
Checking in non-Omnis components, 443
Checking in Omnis classes, 441
Creating a new project, 441
Deleting components, 462
Display options, 464
Labels, 456
Managing components, 458
Renaming components, 462
Setting up a project, 437
Signing in to the VCS, 439
VCS Component services, 462
VCS Components
Getting info, 462
VCS Options, 464
VCS Reports, 467
VCS Revision History, 460
Version Control System, 40, 45, 435
Version numbers, 442
View menu
Component Store, 20
View toolbar, 13
Viewing the contents of a project, 443
Views
Listing, 199
watched variable, 124
Web client
Session pools, 215
Web Client Tools, 14
Welcome start page, 8
WHERE clause, 196
While command, 86
While Loop, 86
Wizards
Omnis Report Wizard, 362
Working message, 93
XCOMP folder, 113
XML
Oracle, 271
Yes/No message, 93
483