UniData

Developing UniBasic Applications

Version 5.2 June 2000 Part No. 000-6837

Published by Informix® Press

Informix Corporation 4100 Bohannon Drive Menlo Park, CA 94025-1032

© 2000 Informix Corporation. All rights reserved. The following are trademarks of Informix Corporation or its affiliates, one or more of which may be registered in the United States or other jurisdictions: Answers OnLineTM; ArdentTM; AxielleTM; C-ISAM®; Client SDKTM; CloudconnectorTM; CloudscapeTM; CloudsyncTM; CloudviewTM; DataBlade®; Data DirectorTM; Data MineTM; Data Mine BuilderTM; DataStage®; Decision FastStartTM; Decision for Telecommunications Campaign ManagementTM; Decision FrontierTM; Decision Solution SuiteTM; DecisionscapeTM; DialogueTM; Dynamic Scalable ArchitectureTM; Dynamic ServerTM; Dynamic Server.2000TM; Dynamic ServerTM, Developer EditionTM; Dynamic ServerTM with Advanced Decision Support OptionTM; Dynamic ServerTM with Extended Parallel OptionTM; Dynamic ServerTM with MetaCube® ROLAP Option; Dynamic ServerTM with Universal Data OptionTM; Dynamic ServerTM with Web Integration OptionTM; Dynamic ServerTM, Workgroup EditionTM; Dynamic Virtual MachineTM; Encrypt.CSMTM; Enterprise Decision ServerTM; E-stageTM; FormationTM; Formation ArchitectTM; Formation Flow EngineTM; Foundation.2000TM; Frameworks for Business IntelligenceTM; Frameworks TechnologyTM; Gold Mine Data Access®; i.DecideTM; i.Financial ServicesTM; i.FoundationTM; i.IntelligenceTM; i.ReachTM; i.SellTM; Illustra®; Informix®; Informix® 4GL; Informix® COM AdapterTM; Informix® Enterprise Command CenterTM; Informix® Extended Parallel ServerTM; Informix® Informed DecisionsTM; Informix® InquireSM; Informix® Internet Foundation.2000TM; InformixLink®; InformiXMLTM; Informix® Red Brick® Decision ServerTM; Informix Session ProxyTM; Informix® VistaTM; InfoShelfTM; Installation AssistantTM; InterforumTM; I-SpyTM; IterationsTM; J/FoundationTM; LUCIDTM; MaxConnectTM; Media360TM; MediazationTM; MetaArchitectTM; MetaBrokerTM; MetaCube®; MetaHubTM; MetaStageTM; NewEraTM; O2 & DesignTM; O2 Technology & DesignTM; Object TranslatorTM; Office ConnectTM; ON-BarTM; OnLine Dynamic ServerTM; OnLine/Secure Dynamic ServerTM; OpenCase®; OrcaTM; PaVERTM; Prism®; Prism & DesignTM; RedBack®; RedBeanTM; RedBeans & DesignTM; Red Brick® and Design; Red Brick® Data MineTM; Red Brick Decision ServerTM; Red Brick® Mine BuilderTM; Red Brick® DecisionscapeTM; Red Brick® ReadyTM; Red Brick Systems®; Regency Support®; Rely on Red BrickSM; RISQL®; Server AdministratorTM; Solution DesignSM; STARindexTM; STARjoinTM; SuperTerm®; SuperView®; SureStartTM; SystemBuilderTM; TARGETindexTM; TARGETjoinTM; The Data Warehouse Company®; UniData®; UniData & Design®; UniVerse®; Universal Data Warehouse BlueprintTM; Universal Database ComponentsTM; Universal Web ConnectTM; ViewPoint®; Virtual Table InterfaceTM; VisionaryTM; Web Integration SuiteTM; XML DataPortTM; Zero Defect Data®. The Informix logo is registered with the United States Patent and Trademark Office. The DataBlade logo is registered with the United States Patent and Trademark Office. Documentation Team: Claire Gustafson GOVERNMENT LICENSE RIGHTS Software and documentation acquired by or for the US Government are provided with rights as follows: (1) if for civilian agency use, with rights as restricted by vendor’s standard license, as prescribed in FAR 12.212; (2) if for Dept. of Defense use, with rights as restricted by vendor’s standard license, unless superseded by a negotiated vendor license, as prescribed in DFARS 227.7202. Any whole or partial reproduction of software or documentation marked with this legend must reproduce this legend.

ii Developing UniBasic Applications

Contents

Chapter 1 - Introduction to UniBasic............................................13
In This Chapter .........................................................................................14 UniBasic Capabilities ...............................................................................15 UniBasic Statements .................................................................................16 Types of Statements ............................................................................16 Building Blocks for Writing Statements .............................................16 Statement Syntax and Layout .............................................................19 UniData File Types ...................................................................................23 Data Representation in UniBasic Programs ..............................................24 Delimiters and the Null Value ............................................................24 Constants .............................................................................................25 Variables .............................................................................................25 Arrays ..................................................................................................26 Getting System Information ......................................................................27 @Variables .........................................................................................27 STATUS Function ..............................................................................28

Developing UniBasic Applications

3

Contents

Chapter 2 - Program Control.........................................................29
In This Chapter .........................................................................................30 Subroutines ...............................................................................................31 Internal Subroutines ............................................................................31 External Subroutines ...........................................................................33 Looping .....................................................................................................36 Conditional Tests ......................................................................................38 IF/THEN/ELSE Statements ................................................................38 CASE Statements ................................................................................41 Reversing Conditional Evaluations: The NOT Function ....................43 Comparison Operators Used in Conditional Statements ....................44 Branching ............................................................................................48 Summary of Program Control Commands ...............................................49

Chapter 3 - Creating and Running a Program .............................51
In This Chapter .........................................................................................52 Creating a Program with AE .....................................................................53 Creating a Program Record .................................................................53 More AE Commands ..........................................................................56 Compiling a UniBasic Program ................................................................59 Compile Commands ...........................................................................59 Directing the Compiler .......................................................................59 Compiler Messages .............................................................................65 Creating Cross-Reference Reports ......................................................68 Cataloging a UniBasic Program ...............................................................73 Points to Remember about CATALOG ..............................................73

4

Developing UniBasic Applications

Contents

Direct Cataloging ................................................................................74 Local Cataloging .................................................................................75 Global Cataloging ...............................................................................75 Using the ECL CATALOG Command ...............................................77 Removing a Catalog Entry ..................................................................78 CATALOG Examples .........................................................................79 Running a UniBasic Program ...................................................................82 Running a Program from AE ..............................................................82 Running a Program from ECL ............................................................82

Chapter 4 - Maintaining Data in Files ...........................................93
In This Chapter .........................................................................................94 UniData Locks ..........................................................................................95 Database Triggers .....................................................................................96 Trigger Rules ......................................................................................96 The Nature of Triggers .......................................................................97 ECL Commands and Triggers ............................................................97 UniBasic Commands Affected by Triggers ........................................98 Writing an UPDATE Trigger Subroutine ...........................................99 Writing a DELETE Trigger Subroutine ............................................102 UniBasic STATUS Function Return Values ....................................105 Troubleshooting ................................................................................106 Maintaining Files ....................................................................................107 UniData Hashed Data Files ...............................................................107 Alternate Key Indexes ......................................................................108 Non-UniData Sequential Files ..........................................................112

Developing UniBasic Applications

5

Contents

Opening Files ..........................................................................................115 Example ............................................................................................115 Selecting Records ...................................................................................116 Creating a Select List of Record IDs ................................................116 Clearing a Select List ........................................................................118 Reading, Writing, and Deleting Data from Files ....................................119 Getting Ready to Read ......................................................................119 Reading Record IDs from a Select List ............................................119 Reading Data from Files ...................................................................119 Example ............................................................................................122 Writing Data to Files .........................................................................123 Example ............................................................................................125 Deleting Data from Files ...................................................................126 Closing Files ...........................................................................................128 Accessing Data in Unopened Files .........................................................129

Chapter 5 - Using UniData Locks ...............................................131
In This Chapter .......................................................................................132 Understanding the UniData Locking System .........................................133 How UniData Locks Work ...............................................................133 Types of UniData Locks ...................................................................133 When UniBasic Finds a Lock ...........................................................135 Points to Remember about Locks .....................................................135 Locking Commands ................................................................................136 Checking Lock Status .......................................................................137 What Commands Do with Locks ............................................................138

6

Developing UniBasic Applications

Contents

When to Use Locking Commands ..........................................................140 Programming Problems ..........................................................................142 Causes ...............................................................................................142 Minimizing Problems .......................................................................142 Locking Example ....................................................................................144

Chapter 6 - Working with Data in Programs ..............................147
In This Chapter .......................................................................................148 UniData Arrays .......................................................................................149 Dynamic Arrays ................................................................................149 Example ............................................................................................153 Dimensioned Arrays .........................................................................153 Inquiring about Data .........................................................................155 Type ..................................................................................................155 Location ............................................................................................157 Extraction ..........................................................................................157 Performing Numeric Operations .............................................................159 Arithmetic Operators ........................................................................159 Mathematic Functions .......................................................................164 Formatting and Converting Data ............................................................166 ICONV and OCONV: The All-Purpose Functions ..........................166 Character Format Conversion ...........................................................168 Strings and Dynamic Arrays .............................................................168 Numbers ............................................................................................170 Dates and Times ................................................................................175 UniBasic Multibyte Support ...................................................................181

Developing UniBasic Applications

7

Contents

Modified Functions and Commands .................................................181 Single-Byte Functions .......................................................................183 Multibyte Functions ..........................................................................184

Chapter 7 - External Interaction..................................................187
In This Chapter .......................................................................................188 Interacting with Other UniBasic Programs .............................................189 Sharing Data .....................................................................................189 Including Code at Compilation .........................................................193 Interacting with UniData ........................................................................195 Executing Virtual Attributes .............................................................195 Executing ECL Statements ...............................................................196 Executing UniData SQL Statements .................................................197 Defining and Using Programs and Functions ...................................198 Writing User Exits ..................................................................................199 What Are User Exits? .......................................................................199 Calling a User Exit from UniBasic ...................................................200 Calling a User Exit from a Virtual Attribute ....................................200 Calling a User Exit from a Proc ........................................................201 Parameters in User Exits ...................................................................202 Interacting with Hardware I/O Devices ..................................................203 Display Terminals .............................................................................203 Printers ..............................................................................................209 Tape Drives .......................................................................................212 Interacting with the Operating System ...................................................213

8

Developing UniBasic Applications

............................................267 Using CallBasic .......................................259 Dynamic Link Libraries (DLLs) and UniData ..................249 More on make..287 Testing for an Active Transaction .....................................................254 Troubleshooting CALLC .............................217 Calling a C Function from UniBasic with CALLC ..............................215 In This Chapter .................Contents Chapter 8 ...................................................... makeudt...282 Starting a Transaction .................................................................................................................................................282 Executing TP and Non-TP Transactions ..........289 Developing UniBasic Applications 9 ............................................................................................................216 Linking C Programs (UNIX Only) .................217 Before You Begin ......................................................219 Calling a UniBasic Subroutine from a C Program with CallBasic .........283 Committing a Transaction ..............................................235 If This Is Not the First Time ............................................................................246 File Examples ..... and makeudapi ..........................260 Using CALLC ............Linking Programs with UniData ..............281 Transaction Processing Commands ................257 Linking C Programs (Windows NT or Windows 2000 Only) ...........................................................................................288 Transaction Processing Programming Example ......................264 CallBasic Features and Components ...................................259 CALLC Features and Components .....................................................................................................285 Aborting a Transaction ............................................................................................................UniBasic Transaction Processing ...............................................................................272 Chapter 9 .....279 In This Chapter .............................................................................

.................................................................................................330 OSBWRITE ...................................................................................327 OSBREAD .................................................302 The Null Value in Numeric Functions ....301 Printing and Displaying ..................315 Chapter 11 ...........................................................................................................................................................293 Degraded Performance .326 Opening Named Pipes ..................325 OSOPEN ....................305 The Null Value in Conversion Functions .....................293 Transaction Abort ................Null Value Handling............323 Points to Remember ...................................................................................................................................................300 Turning Null Value Handling Off .........................................................................Managing Named Pipes .....................301 Summary of Effects on Commands and Functions ..........................................334 10 Developing UniBasic Applications .........291 Transaction Processing Programming Problems ....................................................................301 Sorting and Indexing .................................................290 Creating a Recoverable File ...Contents Creating or Converting to a Recoverable File ............................................................297 Chapter 10 ...............................................................................330 Reading from a Named Pipe ......................................................................303 The Null Value in Conditional Tests ..................................................................................................313 The Null Value in String Functions .......................................................................................................334 Writing to Named Pipes .........................................................................................................290 Converting to a Recoverable File ..................299 Representing Unknown Values ............................300 Null Value Handling in UniBasic ...........................................

................357 Getting a Response Header ................................................361 Chapter 13 ........345 Configuring the Default HTTP Settings .........................................................................................................................................................................Using CallHTTP ..............355 Submitting a Request .............................................................................................375 Setting the Value for a Socket Option ...........................................................................................................................................................................377 Developing UniBasic Applications 11 ....340 Description ............................................................................337 STATUS Function Return Values .......................340 Troubleshooting .373 Writing to a Socket ..............................368 Closing a Socket ............371 Reading From a Socket ...................................................................................................340 Syntax ................341 Example ........................................................................................................................................................................................Contents OSCLOSE ............................370 Getting Information From a Socket .......................................................................................................................342 Chapter 12 ........................................................360 Protocol Logging ..............................................................................................346 Getting the Current HTTP Default Settings .................Using the Socket Interface ..................................................377 Parameters ....................................................... uest 353 Adding a Parameter to the Request ...350 Setting Additional Headers for a Req ..................339 INMAT ....................................................364 Opening a Socket ...................................................................................................................................................................................................................363 Socket Function Error Return Codes ...........................................349 Creating an HTTP Request .........................................................................

.....................404 Programming to Isolation Levels ..................397 In This Appendix ....................399 Durability ..............................................408 Index 12 Developing UniBasic Applications ...............................................................................................................................................................................406 Example: Programming to Isolation Level 3 ......................................................400 Transaction Isolation ...........................383 Protocol Logging .........387 UPDATE_ORDER ............................................399 Isolation ..............................401 Transaction Processing Errors .......................................................................................................................407 Updating Nonrecoverable Files in Transactions ..........................399 Consistency ...........UniBasic Transaction Processing Concepts...................382 Accepting an Incoming Connection Attempt on the Server Side ..........................................................................................385 Appendix A ....Sample Program ....................................................Contents Getting the Value of a Socket Option .......................................................................................388 DISPLAY_MESSAGE ..............................................................................405 Example: Programming to Isolation Level 2 .395 Appendix B ....................................401 What Are Isolation Levels? ..........................................................................................................................................................................399 Atomicity .......398 Transaction Processing Rules: The ACID Properties .....................................379 Initializing a Server Side Socket Connection ..........................................................

It explains how to use UniBasic commands and functions to write application programs.Chapter 1 . Devloping UniBasic Applications 13 .Introduction to UniBasic This manual is for programmers who write applications that use the UniData relational database management system (RDBMS).

Chapter 1 .Introduction to UniBasic In This Chapter This chapter introduces the concepts and terms used throughout this manual and in the UniBasic Commands Reference. It includes the following sections: • • • • • “UniBasic Capabilities” “UniBasic Statements” “UniData File Types” “Data Representation in UniBasic Programs” “Getting System Information” 14 Devloping UniBasic Applications .

Dynamic arrays and a full set of array commands provide an easy interface to UniData’s extended relational database structure.UniBasic Capabilities UniBasic Capabilities UniBasic is UniData’s structured programming language intended for a variety of applications. For the syntax of UniBasic commands and functions. UniBasic provides you with the following capabilities: • • The modular language style enables you to create general UniBasic subroutines that other processes can call. Manage display terminal input and output. An interface with the query languages UniData SQL and UniQuery enable you to pass record IDs or entire records to the query language. Pass data to and from external C programs. you can perform the following tasks: • • • • • • Access other UniData products and operating system tools. Call external C functions. From within a UniBasic program. see the UniBasic Commands Reference Devloping UniBasic Applications 15 .

such as in a subroutine call: GOSUB update_client.THEN or DO. Control statements – Direct the order in which commands are executed.Introduction to UniBasic UniBasic Statements This section describes the types of statements you can use in UniBasic. Statements are the building blocks you use to write UniBasic programs.UNTIL... This section also describes how you can lay out your statements in a program. “MD/2”). which are described in the following subsections: • • • • • “Commands” “Functions” “Operators” “Special Characters” “Comments” 16 Devloping UniBasic Applications . You also can assign the results of a function to a variable: variable = OCONV(1286.. Conditional statements – Control the execution of a set of operations based on the value of a variable: IF. Types of Statements You can write four types of UniBasic statements: • • • • Assignments – Load numeric or string values into variables. Building Blocks for Writing Statements Statements consist of five types of building blocks.Chapter 1 . Compiler directives – Instruct the UniBasic compiler to evaluate and conditionally include statements: $INCLUDE..

2). see “Chapter 6 . including how they are used in UniBasic programs.2. each statement begins with a command word. In the following statement.$").2.2). This statement extracts data from the array A and prints out the extracted data with two decimal places. In the following UniBasic statement. a function can be an argument in a function as in: PRINT OCONV(EXTRACT(A. The UniBasic Commands Referenceexplains the syntax and use of each function. only one command is included on each line of code. and perform mathematical calculations. extract. You can use the following operator types: • • Relational Boolean Note For information about arithmetic operators. SELECT is the command word. Conditional – For testing data and directing program execution. The result of a function can be stored in a variable or used in a command. In structured coding. Therefore. Functions Functions reformat."MD2. Operators UniBasic supports the following operator types: • • Arithmetic – For computing and assigning values. Generally. and ORDER and 1 are arguments used by the command: SELECT ORDER TO 1. You can nest UniBasic functions. see “Chapter 2 .Working with Data in Programs.” For information about conditional operators. the function EXTRACT is an argument in the PRINT command: PRINT EXTRACT(A. preceded by $.Program Control.” Devloping UniBasic Applications 17 .UniBasic Statements Commands Commands are the primary building blocks of the UniBasic instruction set. The UniBasic Commands Referenceexplains the syntax and use of each command.

though. Backslash (\) – Can also be used to replace quotation marks when a string variable is embedded in a literal.SUP NI.SUP " HISTORY4 = \HEADING "'C'Today is 'DLC' On This Day in History 'LL'" \ HISTORY = HISTORY1:HISTORY2:HISTORY3:HISTORY4 PERFORM HISTORY Comments Comments narrate the actions of a program for clarity. They can be used together to differentiate a literal that is embedded in a string. but the compiler ignores them. To enter a comment on a line by itself. and then enter the comment text. It indicates that a command continues on the next line. begin the line with a comment command.) – Separates commands on the same line. HISTORY4 is assigned to a string that includes the HEADING command. In the following example. or you can enter it on the same line as a program statement. The comment commands are *. and REM. Semicolon (.Chapter 1 . !. that including more than one command on a line makes your code more difficult to read and debug. You can enter a comment on a line by itself. and backslashes are used to enclose the entire string: Program Example MON = @MONTH DA = @DAY HISTORY1 = "LIST ALMANAC WITH MONTH = ":MON:" AND DAY = ":DA HISTORY2 = "BY TYPE BY YEAR" HISTORY3 = "YEAR TYPE EVENT ID. Be aware.Introduction to UniBasic Special Characters You can use the following special characters in UniBasic statements: • • • • Continuation character (|) – Placed at the end of a line. Single quotation marks are embedded in double quotation marks.SUP COL. 18 Devloping UniBasic Applications . Quotation marks (“ ” or ‘ ’) – Must enclose string variables and literal values.

Devloping UniBasic Applications 19 . single statements can extend over several lines.).UniBasic Statements In the following example. Multiple statements can be grouped on one line. and statements can be nested. or Quit) A) Allow the user to change price or address D) Delete the record Q) Exit the program To enter a comment on the same line as a program statement. Stacking Multiple Statements on a Line Structured programming conventions suggest that you place no more than one statement on a single line. a comment is entered on the same line as the GOSUB command: Program Example GOSUB OPEN_FILES . ** go open files based on user input Statement Syntax and Layout The syntax for each command and function is included in the UniBasic Commands Reference. two asterisks (**) are used for commented text: Program Example ** ** ** ** ** ** ** ** ** ** Program : Programmer : Created : Description: : : : : : : UPDATE_ORDERS Todd Roemmich 04/02/1996 Check and/or alter Order records Display Screen and ask for Order # Read record (if it exists) and display fields Prompt for a command (Alter. precede the comment command with a semicolon. Delete. UniBasic enables you to include multiple statements on a single line separated by a semicolon (. In the following example. For backward compatibility.

SS.Introduction to UniBasic Reminder Programs are easier to follow if you place a single command on each line. such as CALL. COMMON. Use a continuation character (|) at the end of the line.CITY.HOME.ACC. The following example prints “This line is CONTINUED”: Program Example 001: PRINT "This line is ": OCONV(| 002: "continued".PHONE."MCU") While Informix recommends that you use a single-line construction.STATE. often require several lines. and DATA. 20 Devloping UniBasic Applications .NUM.ADDRESS.Chapter 1 .PHONE. A multiline COMMON statement follows: Program Example COMMON NAME. often require several lines. Extending Statements Across Multiple Lines Individual statements can extend across several lines if you follow one of these rules: • • Break the statement as shown in the syntax of the command or function in the UniBasic Commands Reference. in two cases you might need to use a multiline construction: • Statements with arguments – Statements or functions that have arguments separated by commas.DOB. such as FOR/NEXT and IF/THEN/ELSE.BUS. ZIP.NUM • Long statements – Lengthy constructions.

which is taken from the sample program in “Appendix A .” shows a lengthy IF/THEN/ELSE construction: Program Example IF PRODUCT_LINE = '' THEN PRODUCT_LINE = PRODUCT_NUMBER "R#10" COLOR_LINE = COLOR "R#10" QUANTITY_LINE = QUANTITY "R#10" PRICE_LINE = PRICE END ELSE PRODUCT_LINE := " ":PRODUCT_NUMBER "R#10" COLOR_LINE := " ":COLOR "R#10" QUANTITY_LINE := " ":QUANTITY "R#10" PRICE_LINE := " ":PRICE END Nesting Statements You can nest a statement within another statement.UniBasic Statements The following example. For example. the second IF/THEN is nested: Program Example IF expression THEN statements IF expression THEN statements END ELSE statements END END Devloping UniBasic Applications 21 . test for an additional condition. and if it is true. In the following example.Sample Program. you can test for one condition.

Program Example LOOP DISPLAY @(15.” is an example of an IF/THEN/ELSE nested inside a conditional LOOP.1] = "Q" THEN VALID_ORDER_NUMBER = 1 END ELSE VALID_ORDER_NUMBER = 0 MESSAGE = "Order # must be a Number. which is taken from the sample program in “Appendix A Sample Program.Chapter 1 . The LOOP test is in the UNTIL statement.Introduction to UniBasic The following program segment."MCU") IF NUM(ORDER_NUMBER) OR ORDER_NUMBER[1. or the letter 'Q'" CALL DISPLAY_MESSAGE(MESSAGE) END UNTIL VALID_ORDER_NUMBER REPEAT 22 Devloping UniBasic Applications .6): INPUT ORDER_NUMBER ORDER_NUMBER = OCONV(ORDER_NUMBER.

UniData automatically resizes the file to avoid level 2 overflow. A directory that contains one or more UniData hashed files. For more information about UniData files. All hashed files in the MULTIFILE share the same dictionary. Data file located in the same directory at the same level as the indexed data file. UniData File Types Description Devloping UniBasic Applications 23 . UniData treats these two portions as one file. Data file that contains attribute definitions for a UniData file. If you copy records from a file into one of the subdirectories. Data file located in the dynamic file directory along with the data file and the overflow file. each record is stored as a text file. An operating system directory directly accessible by UniData. This index is based on an attribute other than the primary key. see Using UniData. There is one dictionary for the MULTIDIR. There is one dictionary for the MULTIFILE.UniData File Types UniData File Types File types that make up the UniData database include those listed in the following table. UniData File Type Static hashed file Dynamic hashed file Dictionary (DICT) file Alternate key index (static file) Alternate key index (dynamic file) DIR file MULTIFILE (multilevel file) MULTIDIR (multilevel DIR file) Data file. A directory that contains one or more subdirectories. Directory file that contains a data and an overflow portion. All subdirectories in the MULTIDIR share the same dictionary.

see “Chapter 10 . The ASCII code used for these values is determined by the language (such as English.” 24 Devloping UniBasic Applications . Chinese.Chapter 1 .Introduction to UniBasic Data Representation in UniBasic Programs Before you can work with data in a program. The @values to use are: • • • • • • Null value – @NULL Record mark – @RM Attribute mark – @AM. you must bring it into the program and store it in a usable form. For a full explanation. data is represented in the following ways: • • • • • Delimiters and the null value Constants Variables Arrays @variables Delimiters and the Null Value Informix recommends that you use @variables to represent UniData delimiters and the null value in UniBasic programs instead of entering the ASCII code directly. or Spanish) being represented. In UniBasic programs.Null Value Handling. @FM Value mark – @VM Subvalue mark – @SM Text mark – @TM Note You turn on or off null value handling with the UniData configuration parameter NULL_FLAG.

such as 25. Type is inferred from the data initially assigned to it.Data Representation in UniBasic Programs Constants A constant can be a numeric value.” Arguments in a program call. For more information. Must begin with a letter.Creating and Running a Program. You can use up to 32.765 constants at one time. such as “inventory. UniBasic does not require explicit declaration of variable data type (unless it is a dimensioned array). see “Chapter 3 . Setting Variable Values Variables receive their values from one of the following: • • • • • • Data input through the keyboard.” Variable Names Variable names must follow the conventions described below: • • • Must be unique. For more information. numbers. An assignment (variable_name = 1234). underscores. or another storage medium. see “Chapter 3 . A computation statement. and dollar signs.” You must use quotation marks to enclose string values. periods. tape. Can contain any combination of letters. Data read from a file. Variables A variable can be as simple as a character string or as complex as a dimensioned array. Devloping UniBasic Applications 25 . Data stored in virtual memory or on hard disk. or a string value.Creating and Running a Program.

unknown. value. or when the data to examine is near the beginning of the array. For a list of reserved words. and subvalue of a record by delimiters. Cannot be a reserved word. Access to data in a dimensioned array is rapid. Arrays An array is simply a form of variable. Each element of an array can contain a constant. which is a place reserved in memory for storing data in a UniBasic program. see the UniBasic Commands Reference.” 26 Devloping UniBasic Applications . see “Chapter 6 Working with Data in Programs. or a dynamic array. Use dimensioned arrays when the number of elements is large or the program will process the elements nonsequentially.Chapter 1 . Tip Use dynamic arrays when the number of elements is small. a simple variable. varied. Dimensioned arrays – Store data in designated cells of a fixed-sized matrix. For more information about using arrays to process data in a UniBasic program. UniBasic allows for two types of arrays: • • Dynamic arrays – Separate each attribute. but less flexible.Introduction to UniBasic • • Are limited to a length of 64 characters.

• UniData – Available through any tool. For a complete list of UniBasic @variables. and returns 0 if no transaction is active.RETURN. For example: @SYSTEM. @Variables UniData @variables store and make available information about the system. the user process. it reports the number of records selected. and the UniBasic program being executed.Getting System Information Getting System Information A wealth of information is available to your UniBasic program through system variables (called @variables) and through the UniBasic STATUS function. For example. @TRANSACTION returns 1 if a transaction is active. Others are available through UniBasic only. Devloping UniBasic Applications 27 . For example: @SENTENCE stores the statement that invoked the current UniBasic program. see the UniBasic Commands Reference. see Using UniData. It also returns additional information. • UniBasic – Available through UniBasic only. after SELECT. For a complete list of UniData @variables.CODE returns a value indicating a condition or error after the execution of an ECL command. Some @variables are available through any UniData or 4GL tool. Reminder Use @variables to represent UniData delimiters and the null value. Do not use the UniBasic CHAR function because the ASCII code varies with language group.

Introduction to UniBasic STATUS Function The UniBasic STATUS function provides information about the last UniBasic statement executed. For more information about triggers. Generally.Chapter 1 . a return value of 0 indicates successful execution. see “Chapter 4 Maintaining Data in Files. those values are documented with the command in the UniBasic Commands Reference. the return values set for the STATUS function. UniData triggers also set STATUS values.” 28 Devloping UniBasic Applications . For cases in which return values are set by a command. while 1 or any other number indicates an error condition. and an additional return value set by triggers.

see UniBasic Commands Reference.Program Control A structured program consists of: • • A main routine that controls the order of program execution. This chapter introduces the UniBasic program control mechanisms that enable you to write structured code. If you are new to programming or new to UniBasic. For more information about the syntax of UniBasic commands and functions. printer. and data manipulation. and Subroutines that perform functions such as screen.Chapter 2 . Developing UniBasic Applicatons 29 . read “Chapter 1 Introduction to UniBasic” first.

These structures and the commands that build them are introduced in the following sections: • • • • “Subroutines” “Looping” “Conditional Tests” “Summary of Program Control Commands” 30 Developing UniBasic Applicatons .Program Control In This Chapter The UniBasic commands control the order of execution of statements in the program. These commands create subroutines. loops. and otherwise direct program flow. and conditional tests.Chapter 2 .

label2[:]. These commands do not return control to the calling statement and are generally not used in structured programs because they make the code difficult to read and maintain. Labels can be numbers or short descriptive strings. Internal Subroutines Internal subroutines are self-contained units within a program. you can code subroutines that are internal to the calling program or separately compiled and cataloged.Sample Program”: INITIALIZE ALTER_RECORD WRITE_RECORD GET_RECORD_COMMAND Developing UniBasic Applicatons 31 .Subroutines Subroutines In UniBasic. They begin with a label and end with a RETURN statement. GOSUB and ON GOSUB are the only acceptable statements to use for calling an internal subroutine: • • GOSUB label1 RETURN [TO] ON expr GOSUB label1[:][. Naming Internal Subroutines Each internal subroutine must begin with a label.] RETURN [TO] Tip GOTO and ON GOTO are provided in UniBasic for backward compatibility.. The following labels are used in the sample program in “Appendix A . Commands That Call Internal Subroutines Within the constraints of structured programming. You can nest subroutines up to 1024 levels deep..

you will be able to locate internal subroutines easily. numbers. choose meaningful. If the label is alpha or alphanumeric. it must contain only numbers.Chapter 2 . underscores. The label cannot be a reserved keyword. Example of an Internal Subroutine The following example. When you select names for subroutine labels. and dollar signs. descriptive names. Spaces are not allowed in subroutine names.1] = 'Q' GOSUB DISPLAY_DATA IF RECORD_FOUND THEN GOSUB GET_RECORD_COMMAND RELEASE REPEAT GOSUB EXIT 32 Developing UniBasic Applicatons . and when you use numeric statement labels. periods. Add comments after the statement label.” illustrates calling internal subroutines: Program Example *-------------. arrange the subroutines in ascending order. Avoid abbreviations. it must end with a colon to differentiate it from a variable.Program Control You must observe the following conventions when creating statement labels: • • • • • If a label begins with a number.Sample Program. taken from the sample program in “Appendix A . it can contain any combination of letters. If the label begins with a letter. If you follow these guidelines.Main Logic ----------------------------GOSUB INITIALIZE LOOP GOSUB DISPLAY_SCREEN GOSUB GET_ORDER_NUMBER UNTIL ORDER_NUMBER[1.

.)] CHAIN and ENTER also execute subroutines. Calling an External Subroutine Use the CALL command to initiate an external subroutine. The syntax of the CALL command follows: CALL sub. The compiled subroutine must be cataloged so that the main program can locate it. until it reaches RETURN: Program Example INITIALIZE: DISPLAY @(-1) PROMPT '' RETURN Processing picks up again at the next line that follows the subroutine call in Main Logic (see the preceding program example). as the following example shows. the first line calls the subroutine INITIALIZE. The structural requirements of external subroutines include the following: • • • • • The SUBROUTINE statement must be the first noncomment line in the subroutine. You can pass variables and constants to an external subroutine through arguments. You can nest subroutines up to 1024 levels deep. Processing proceeds from the “INITIALIZE:” label. but they do not return control to the calling program and are not recommended in structured programming. External Subroutines External subroutines are separately compiled programs that are called from a UniBasic program using the CALL statement.argument2].. The SUBROUTINE statement must contain the same number of arguments as the calling program. This line contains the command LOOP. Developing UniBasic Applicatons 33 . The subroutine must finish with a RETURN command.Subroutines In the previous example.name [(argument1[.

ret. (2)delete.val = "Record updated.PGM.. Program Example PRINT "Enter operation to perform: (1)add.val = "Record deleted. (3)update : "." CASE operation = 2 ret." CASE operation = 3 ret. and returns a value in ret.) statement(s) RETURN Examples The following sample program calls the external subroutine CALLED. It passes on the operation code selected by the user.ret.INPUT operation CALL CALLED. The syntax follows: SUBROUTINE sub.val) PRINT "Operation completed: ":ret.Chapter 2 .val = "Record added.val END The following subroutine accepts the code.PGM(operation. and the last line must be RETURN.PGM(operation." END CASE RETURN 34 Developing UniBasic Applicatons ..value: Program Example SUBROUTINE CALLED.Program Control Naming an External Subroutine The SUBROUTINE command names the external routine.name [(argument1[.val) BEGIN CASE CASE operation = 1 ret. passes in the parameter operation. This command must be the first line of code in the called routine.argument2].

1_ RETURN The following program segment is an example of a call to the preceding subroutine from UPDATE_ORDER: Program Example MESSAGE ="**(Record Does Not Exist)**" GO_BACK = "Y" CALL DISPLAY_MESSAGE(MESSAGE) Developing UniBasic Applicatons 35 .": INPUT PAUSE.20):MESSAGE DISPLAY @(5.” It displays the message passed in the variable MESSAGE.Subroutines The following program is the globally-cataloged subroutine DISPLAY_MESSAGE that is included in “Appendix A . Program Example SUBROUTINE DISPLAY_MESSAGE(MESSAGE) DISPLAY @(5.Sample Program.21):"Press the (Return) key.

Program Control Looping UniBasic provides the following commands that support looping to repeatedly execute a set of commands. The loop continues until the counter reaches a specified number or the UNTIL condition is satisfied or until WHILE is false.” 36 Developing UniBasic Applicatons .Chapter 2 . The loop continues until the UNTIL condition is satisfied or until WHILE is false. you must test the return value of the function ISNV or ISNVS. Command LOOP/REPEAT Action Statements can precede and/or follow the evaluation. as in LOOP UNTIL X = @NULL. You can include multiple UNTIL and/or WHILE clauses. Transfers control to the next iteration of a FOR/NEXT or LOOP/REPEAT statement.Null Value Handling. because the null value is not comparable to any value. as in LOOP UNTIL ISNV(X) = 1. Transfers control to the line after REPEAT or NEXT. Commands for Looping FOR/NEXT CONTINUE EXIT Note To test for the null value. see “Chapter 10 . For information about how null values affect UniBasic. Executes statements repeatedly while a counter increments or decrements (default is +1). You cannot test for the null value directly.

* Initialize variables and draw the screen NEED.8):"(Press RETURN to leave un-changed)" DISPLAY @(8.ENTRY> = NEW.9+ENTRY):OCONV(ORDER.PRICE NEW.PRICE NEED.PRICE = "" DISPLAY @(10.PRICE = OCONV(NEW.REC<7.Looping Example The following program segment is taken from the sample program in “Appendix A .” This segment updates the price if the user has entered a new one.PRICE) THEN ORDER.WRITE = 0 DISPLAY @(-1):@(15.9+ENTRY):NEW. and allow PRICE and ADDRESS to be changed.REC<7."): INPUT @(45.PRICE # '' AND NUM(NEW.5):"Alter ORDER": DISPLAY @(10.9):"New Price (Enter 2 decimal places)" * Change the PRICE field (if desired) FOR ENTRY = 1 TO NUM_ENTRIES NEW.Sample Program."MR2$. Program Example *-----------.PRICE.TO.TO.9):"Old Price":@(42."MCN") IF NEW.ENTRY>.WRITE = 1 END NEXT ENTRY Developing UniBasic Applicatons 37 .Subroutines ---------------------------ALTER_RECORD: * Create a new screen.

..Chapter 2 ... UniBasic conditional statements include the following: • • IF/THEN/ELSE CASE Within these statements.. IF .” You can use the syntax in any of the following IF/THEN/ELSE statements. To evaluate data. IF/THEN/ELSE Statement Syntax 38 Developing UniBasic Applicatons .. THEN . you need to build conditional statements...... Note For information about how null values affect UniBasic..THEN .. Type 1 2 Syntax IF .Null Value Handling.Program Control Conditional Tests Two primary functions of a program are evaluating and processing data appropriately based on that evaluation. IF confirmed = "Y" THEN GOSUB DISPLAY ELSE . see “Chapter 10 . ELSE .. you can nest additional conditional tests with the following keywords: • • WHILE UNTIL IF/THEN/ELSE Statements An IF/THEN/ELSE statement evaluates a piece of data and then processes it in a manner appropriate for that particular data. Example IF confirmed = "Y" THEN .

THEN .. Developing UniBasic Applicatons 39 .Conditional Tests Type 3 Syntax IF .. GOSUB DISPLAY_INFO END ELSE INFOMESSAGE = .... .. (specifically.. GOSUB DISPLAY_INFO END IF/THEN/ELSE Statement Syntax You can test for a true condition in a variable with a statement similar to the following: IF var THEN statements1 ELSE statements2 When var is true.. END ELSE .. statements1 are executed. GOSUB DISPLAY_INFO END ELSE GOSUB DISPLAY_ERR END 4 IF expr THEN ... Example IF confirmed = "Y" THEN INFOMESSAGE = ... When var is false (when it is 0). when it is anything other than 0)... END ELSE . statements2 are executed... END IF confirmed = "Y" THEN INFOMESSAGE = ..

which is described in the preceding IF/THEN/ELSE Statement Syntax table.Sample Program.” This statement is an example of Type 4.14):STREET2 IF STREET2 = '' THEN STREET2 = CLIENT.REC<4> INPUT @(40. Program Example IF STATUS() = 1 THEN DISPLAY "A Transaction had already been started." END 40 Developing UniBasic Applicatons . NESTED Transactions" DISPLAY "are NOT Allowed.Chapter 2 .Program Control Example The following program segment is taken from the sample program in “Appendix A .13):STREET1 IF STREET1 = '' THEN STREET1 = CLIENT.1_ END ELSE DISPLAY "The Recoverable File System is not enabled. which is described in the previous table. Program Example * Accept INPUT to change values of address INPUT @(40. (Contact System Administrator)" INPUT PAUSE.REC<5> The following program segment is taken from the sample program in “Appendix A .Sample Program.” This statement is an example of Type 1.

the CASE statement is more efficient than IF/THEN/ELSE because when a true condition is encountered. see “Chapter 10 . UniBasic goes on to test the next CASE condition. For information about how the null value affects UniBasic. Syntax: BEGIN CASE CASE expr1 statements CASE expr2 statements . You can enter an unlimited number of CASE conditions. {CASE 1 statements} END CASE If a condition is true. Placed as the last test.Null Value Handling. Note The null value is always evaluated to false.” Developing UniBasic Applicatons 41 . it executes if all previous CASE conditions are false. The CASE 1 statement always evaluates to true. When testing for more than two conditions.Conditional Tests CASE Statements The CASE statement accommodates multiple conditions... If a condition is false. UniBasic performs all statements associated with that CASE statement and then transfers control to the statement that follows END CASE. UniBasic skips all subsequent CASE evaluations.

delete. and then the program calls the appropriate subroutine to perform that operation. Note that CASE 1 handles the user entering an invalid response. Program Example GET_RECORD_COMMAND: * Enter a valid command to act upon (the Desired record is already shown).22):"Enter A)lter.1]."MCU") BEGIN CASE CASE COMMAND = "A" GOSUB ALTER_RECORD CASE COMMAND = "D" GOSUB DELETE_RECORD CASE COMMAND = "Q" FINISHED = 1 CASE 1 MESSAGE = "Valid options are A. or Q)uit: ": INPUT COMMAND. D)elete.Sample Program.1 COMMAND = OCONV(COMMAND[1.Program Control Example The following program segment is taken from UPDATE_ORDER in “Appendix A . D. Please try again" CALL DISPLAY_MESSAGE(MESSAGE) END CASE RETURN 42 Developing UniBasic Applicatons .” In this subroutine. or Q. the user selects an operation to perform (alter.Chapter 2 . DISPLAY @(7. or quit).

If the expression is false. search_product ON open.". making a true result false or a false result true. which indicates that the record was not found.STOP PRINT "Enter product to display: ".var.STOP LOOP UNTIL new_product <> search_product READFWD dyn.array. "MCT") new_product = search_product SETINDEX "PROD_NAME".3) IF new_product = search_product THEN PRINT "Record is: ":dyn." .var REPEAT END Developing UniBasic Applicatons 43 . For more information about how the null value is handled in conditional statements.Null Value Handling. Note You cannot use NOT to test for the absence of the null value because NOT @NULL is evaluated to @NULL.file ELSE PRINT "Readfwd error. If the expression is true.file ELSE PRINT "Open error.Conditional Tests Reversing Conditional Evaluations: The NOT Function The NOT function inverts the result of conditional statements.array.array. The STATUS function in the following program tests for a value other than 0." new_product = EXTRACT(dyn.INPUT search_product search_product = OCONV(search_product. the function returns 1 (true).var FROM open. the function returns 0 (false).file IF NOT(STATUS()=0) THEN PRINT "Record not found.” Program Example OPEN "INVENTORY" TO open. Note that the comparison of the STATUS return value with 0 is enclosed in parentheses. You must enclose the expression being reversed in parentheses. see “Chapter 10 .

WRITE must be true for the CLIENT. The values in NEW_CLIENT and OLD_CLIENT must not be equal. either expression (NEW_CLIENT # OLD_CLIENT) or NEED.REC<6> = CITY 44 Developing UniBasic Applicatons . see “Chapter 10 Null Value Handling.REC<5> = STREET2 CLIENT.Program Control Comparison Operators Used in Conditional Statements Comparison operators can be used to make compound conditional statements. the result is true. Boolean Operators Boolean operators combine or compare sets of relational data. Comparison operators include Boolean and relational operators.REC<4> = STREET1 CLIENT. Boolean operators take one of the following forms.WRITE THEN * Re-assign values to CLIENT. the logical operators AND and OR follow the ANSI SQL 3-way logic and null value evaluation comparison rules.TO. the result is true.WRITE must be 1. For more information.REC CLIENT.REC values to be updated. Boolean Operators Note With null value handling turned on. Expression expr1 AND expr2 expr1 OR expr2 Description When both expressions are true.TO. A common use for Boolean operators is to check if a numeric variable falls within a range. Program Example IF (NEW_CLIENT # OLD_CLIENT) OR NEED. or NEED. When either expression is true.Chapter 2 .TO.” In the following example.

Greater than. Not less than. Operator EQ = NE # <> >< GT > LT < GE >= => LE <= =< #> #< MATCH MATCHES Equal to. Not greater than. Less than. Developing UniBasic Applicatons 45 .REC<8> = ZIP GOSUB WRITE_RECORD END Relational Operators UniBasic supports the following relational operators for making comparisons. Less than or equal to.REC<7> = STATE CLIENT.Conditional Tests CLIENT. Relational Operators Description Note Some symbols serve as both relational and arithmetic operators. Not equal to. Greater than or equal to. Value matches a pattern (such as 0N or 0A) or a literal.

Order of Precedence First Second Third Operator ^ ** * / + : CAT Description Exponentiation Multiplication Division Unary minus Addition Subtraction Concatenation Fourth Operator Precedence 46 Developing UniBasic Applicatons . UniBasic uses the following order of precedence. If multiple operators appear within a single command statement or within a single parenthetical expression. For more information.OPTIONS provide settings that modify the operation of UniData and UniBasic. UniData evaluates zero and empty string equally.Chapter 2 . UniBasic performs the operations from left to right.Program Control UDT.OPTION 1 ON. Operator Precedence Within nested operations. if you set UDT. see the UDT.OPTIONS UDT. you can control the order of execution by using parentheses with arithmetic or comparison operators. In the absence of parentheses. UniBasic first resolves the innermost parenthetical expression and then works outward. For value comparison. and the operators have equal precedence.OPTIONS Commands Reference.

one=value PRINT "Second value: Enter true or false: ".one OR val. Program Example PROMPT'' PRINT "First value: Enter true or false: ". substitute AND for OR in the program.Conditional Tests Order of Precedence Fifth Operator > GT < r = EQ >= => GE #> <= =< LE #< <> >< # NE MATCH MATCHES Description Greater than Less than Equal to Greater than or equal to Not greater than Less than or equal to Not less than Not equal to Matching And Or Sixth & AND ! OR Operator Precedence (continued) Example You can use the following sample program to test the logical operator OR.VAL val. To test the logical operator AND.INPUT answer answer = UPCASE(answer) GOSUB SET.two ) = 1 Developing UniBasic Applicatons 47 .INPUT answer answer = UPCASE(answer) GOSUB SET.two=value If (val.VAL val.

Chapter 2 . The GOTO and ON GOTO commands direct the program to jump to another place in the code.Program Control PRINT "Condition True. 48 Developing UniBasic Applicatons . although this practice makes code difficult to follow and maintain." Branching For backward compatibility." ELSE PRINT "Condition is false. For the syntax of these commands. UniBasic supports branching. see the UniBasic Commands Reference.

Program Control Commands EXECUTESQL EXIT FOR/NEXT GOSUB IF/THEN/ELSE Developing UniBasic Applicatons 49 .) Executes a UniData SQL statement from within a UniBasic program. (Identical to PERFORM. or subroutine. or operating system command. UniData SQL.Summary of Program Control Commands Summary of Program Control Commands The following table summarizes the UniBasic commands that facilitate structure and control in programs. Executes statements one time based on a condition. Ends a FOR/NEXT or LOOP/REPEAT statement and transfers control to the first statement after the loop statement. Executes an internal subroutine. Repeats statements based on a condition. Calls an external subroutine. such as a UniQuery. and then returns to the next statement after GOSUB. program. Command ABORT CALL CALLC CASE CHAIN CONTINUE END EXECUTE Action Stops program execution. Calls an external C subroutine. Transfers control to the next iteration of the FOR/NEXT or LOOP/REPEAT statement. Branches to a separate program. Executes an external UniData statement. Indicates the end of a conditional statement. Executes statements based on a condition.

Stops program execution. UniData SQL. such as a UniQuery. Program Control Commands (continued) RETURN STOP 50 Developing UniBasic Applicatons .Program Control Command LOOP/REPEAT ON expr GOSUB name PCPERFORM PERFORM Action Repeats a set of statements based on a condition. Branches to a subroutine based on the value of an expression. or returns control from an internal subroutine to the next statement that follows GOSUB. (Identical to EXECUTE. Executes an operating system command from within a UniBasic program.) Returns control from an external subroutine back to the original program.Chapter 2 . or operating system command from within a UniBasic program. Executes an external UniData statement.

Chapter 3 . Informix recommends that you review “Chapter 1 . Developing UniBasic Applications 51 .Introduction to UniBasic” before you begin this chapter. If you are not familiar with the UniData RDBMS. and how data is represented in UniBasic programs. the UniBasic statement types.Creating and Running a Program This chapter describes how to create and run a UniBasic program.

These topics are presented in the following sections: • • • • “Creating a Program with AE” “Compiling a UniBasic Program” “Cataloging a UniBasic Program” “Running a UniBasic Program” 52 Developing UniBasic Applications .Chapter 3 .Creating and Running a Program In This Chapter This chapter introduces the tools that you need to create and edit UniBasic programs. cataloging. and running the program. It includes compiling.

UniData provides the Alternate Editor (AE) line editor. as long as you save it in ASCII format as a record in a directory file.file is the directory in which the source code is located (usually BP).Creating a Program with AE Creating a Program with AE You can use any ASCII text editor or word processor to create a UniBasic program.” Creating a Program Record Perform the following steps to create a program record: 1. Syntax: AE directory. For information about the building blocks used to create UniBasic programs. prog. UniData creates a basic program (BP) file for this purpose when you initiate a new account.name directory. enter the AE command at the ECL prompt.file prog. Developing UniBasic Applications 53 .name is the name you choose for the program. see “Chapter 1 Introduction to UniBasic. You will use this same command later to edit the program. or you can use the operating system default editor (with the ECL command ED). This section provides instructions for using AE. Start AE To create a program using AE. Tip AE is designed for writing UniBasic programs. Tip UniData creates a BP directory file when you create your account. It recognizes UniData hashed files. and it comes with online help. it enables you to execute UniData commands from within a file you are editing.

File > At this point. Change to dInput Mode For now.Chapter 3 . you are in command mode.Creating and Running a Program If You Are Successful After you start the AE editor. *--: When you first start AE. so you want to be in input mode. 2. UniBasic opens the program at the top and displays the command mode prompt: Screen Example :AE BP NEWFIL Top of New "NEWFIL" in "BP". enter i. your best option is to press ENTER and start over. AE changes the prompt to reflect your current line number. This is where you enter commands that affect the entire file. and it displays a message like this: Screen Example :AE NEWFIL Unable to find file "NEWFIL". AE does not recognize the file name. To change to input mode. you want to key in the program. If You Are Not Successful If you fail to indicate a directory file where the program is to reside (such as the BP file). Screen Example *--: i 001= 54 Developing UniBasic Applications .

Press ENTER at the end of each line. 3. press ENTER at the line number. or execute some other command directive. the line number prompt “004=” is replaced by the command mode prompt “*--”: Screen Example 004= *--: <-. save the file. In the following example.line number prompt <-.Creating a Program with AE Enter as many lines of code as you want. You remain in input mode as long as you enter text on a line before pressing ENTER.is replaced by command mode prompt Developing UniBasic Applications 55 . press SHIFT+6. Return to Command Mode When you want to get help. as shown in the following example: Screen Example 001= ! Program: NEWFIL 002= ! Created: 1/1/96 003= ! Tip To display and enter the ASCII code for control characters (including UniData delimiters and the null value) in AE. compile the program. You are returned to command mode. as demonstrated by the return of the command mode prompt.

enter FI. Save. enter HELP or H at the command-line prompt. the ECL prompt reappears. To quit the program without saving it.Chapter 3 .Creating and Running a Program 4. Use the FIBCFN or ECL NEWPCODE command to dynamically activate a cataloged subroutine. After you quit the program. or Quit You file. File. recatalog.string/new. enter EX or Q. You can use a UniBasic shell to modify. Access AE Help To get help on AE. To save and quit the program. Command C/old.string Description Changes the current character string to a new character string on the current line. as shown in the following example: Screen Example *--: HELP You can also enter a help topic on the same line. save. More AE Commands 56 Developing UniBasic Applications . Screen Example *--: H ALL 5. enter ALL or A. More AE Commands You can enter any of the following basic AE editor commands when you are in command mode. To get a list of all topics. or quit in command mode. recompile. and retest a UniBasic program without returning to the ECL prompt.

You can also enter HELP followed by a topic or AE command. the program you execute is an earlier version that does not include changes in the most recent version. recatalog. compiles it. For more information.Be aware that the version run can differ from the one you are editing. see the online help for the AE editor. Note . recompile. FIBCFN compiles a program and catalogs it (locally) with NEWPCODE.Creating a Program with AE Command R/old. You can use a UniBasic “shell” to modify. Quits the record without saving changes made during this editing session. More AE Commands (continued) Developing UniBasic Applications 57 . and retest a UniBasic program without exiting to ECL. and runs it.string P HELP I EX or Q FI FIB FIBR Description Replaces the current line with new text entered.If the compile is unsuccessful.Use FIBCFN or ECL NEWPCODE to dynamically activate a cataloged subroutine. Files the program record and saves changes. Displays one page of the record. FIR Files the record and runs the compiled version. FIBCFN The N option of the FI command equates to the ECL NEWPCODE command. with no line numbers. Note . Files the record.string/new. You need to use F (force) in conjunction with the N option. Displays online help for AE. Tip . Files the program record and compiles it. LNn Lists the number of lines specified. Changes to input mode so you can enter text.

Returns to command mode.Creating and Running a Program Command n T SPOOLHELP SPOOLHELP -FULL ENTER Description Goes to line number n. n is the number of lines to list. Prints brief help. which lists no line numbers.Chapter 3 . More AE Commands (continued) Tip Do you need to cut and paste lines in a program without the line numbers? AE offers the command LNn. Prints extensive help. Goes to the top of the record. 58 Developing UniBasic Applications .

compiles it.Compiling a UniBasic Program Compiling a UniBasic Program The UniBasic compiler processes UniBasic code into the interpretive code (also called object code) that is used by the UniBasic interpreter at runtime. UniData saves the program.] [option] Developing UniBasic Applications 59 . When you enter FIB.. see “Creating a Program with AE” earlier in this chapter. Syntax: BASIC filename [TO filename] progname1 [progname2. and returns you to the ECL prompt.. • Directing the Compiler You can direct the compiler to take some action during compilation with the following: • • ECL BASIC command options ECL and UniBasic commands ECL BASIC Command Options One way to direct the compiler is with ECL BASIC command options. see “ECL BASIC Command Options” later in this chapter. Compile Commands You can compile a program using the following commands: • Compiling within AE – You can compile a program you are currently editing in AE by entering FIB at the command prompt. For the syntax of the BASIC command. Compiling from ECL – The BASIC command compiles the program from the ECL prompt. For more information about compiling from AE. files the compiled code.

. Note . enter BASIC BP UniData compiles all programs in BP. BASIC Command Parameters The following table lists compile options available with the ECL BASIC command. You must choose and option and include the hyphen." Then. For example. option Specifies additional function(s) to be performed. Specifies the source code program to be compiled and used with the UniData Basic interpreter. Reports on execution time for the program.The compiled version is saved in _filename.. see the BASIC Command Options table. Parameter filename progname Description Specifies the file from which the source program code is compiled. BASIC Command Options 60 Developing UniBasic Applications . Tip . If you do not enter progname. as described in “Reporting Execution Time” later in this chapter. UniData prompts for a program name. Option -D -G Description Creates a symbol table for use with the UniBasic debugger. this compiles all programs in the select list. For more information about the debugger.Creating and Running a Program The following table describes each parameter of the syntax. enter SELECT BP WITH @ID UNLIKE "_.Chapter 3 . For valid options. see Using the UniBasic Debugger. and if you do not have a select list active. to select all UniBasic source files in the BP directory.You can create a select list before executing BASIC.

or mixed case). lowercase. For more information. Define variables and include or exclude blocks of code. Creates a symbol table for use with the UniBasic debugger. Selecting a Compiler Type You can tune your UniBasic program to be more compatible with other software that does not follow UniData syntax. For more information about the debugger. all reserved words in UniBasic are case insensitive. You can also use this command to learn which BASICTYPE is currently active or which BASICTYPE was used to compile a program. see Using the UniBasic Debugger. as follows: • ECL BASICTYPE command. You can direct the compiler to do this from the ECL prompt or from within a UniBasic program. BASIC Command Options (continued) -L -LIST -X -L -XREF -L -Z1 -Z2 -I ECL and UniBasic Commands Some additional ECL and UniBasic commands are provided to instruct the compiler to take action of the following types: • • Select a compiler type. entered from the ECL prompt. If you compile a program with the -I option. For a list of UniBasic reserved words. sets the current BASICTYPE to be used by the UniBasic compiler. the compiler recognizes uppercase reserved words. Generates a cross-reference table of statement labels and variable names used in the program. see “Creating Cross-Reference Reports” later in this chapter. see theUniBasic Commands Reference. Without this option. Developing UniBasic Applications 61 .Compiling a UniBasic Program Option -I Description Compiles UniBasic reserved words regardless of the case in which they are entered (uppercase. Generates a list of the program.

Description More Compiler Directives 62 Developing UniBasic Applications .Chapter 3 . entered as the first line in a UniBasic program.Creating and Running a Program • UniBasic $BASICTYPE command. $BASICTYPE in a UniBasic program overrides the BASICTYPE established at the ECL prompt. These directives are shown in the following table. For more information about the compiler directive $BASICTYPE. see the UniData Commands Reference. see the UniBasic Commands Reference. More Compiler Directives Along with $BASICTYPE. Compiler Command $DEFINE var $UNDEFINE var Description Defines and clears a control variable var. UniData offers other compiler directives that you can use within UniBasic programs to define variables and establish blocks of code based on the variables. determines the BASICTYPE to be used in the compilation of the program that follows. The following options are available for use with both BASICTYPE and $BASICTYPE. Parameter U P R M UniBasic Pick® BASIC Advanced Revelation® BASIC McDonnell Douglas BASIC/Reality® BASIC $BASICTYPE Parameters For more information about the ECL BASICTYPE command.

ELSE logic. THEN.OPEN = '' $DEFINE FACT1 $IFDEF FACT1 OPEN 'PARTS1' TO PARTS ELSE CANT.. or it compiles the second section (line 17) to open files for factory 2: Program Example comp_dir 001: 002: 003: 004: 005: 006: 007: CANT. UniBasic compiles either the first section (line 4) to open files for factory 1.Compiling a UniBasic Program Compiler Command $IFDEF var statements1 [$ELSE statements2] $ENDIF $IFNDEF var statements1 [$ELSE statements2] $ENDIF $INCLUDE $INSERT Description If var is defined. these compiler directives instruct the compiler to include or exclude blocks of code based on the variables provided. include statements1 in compiled code. However. include statements2. include statements1 in compiled code. More Compiler Directives (continued) The constructions of these compiler directives are very similar to Boolean IF. Otherwise. Compiler Directives Example When you compile the following program. If var is not defined. include statements2.. Inserts the indicated UniBasic program or program segment into your program during compilation. A common use is to insert frequently used blocks of code or data into appropriate programs.. Otherwise.OPEN<-1> = 'PARTS1' END Developing UniBasic Applications 63 ..

ORDERS2' END OPEN 'SALES.OPEN THEN PRINT 'Cannot open file(s): ' LOOP REMOVE FILE FROM CANT.OPEN<-1> = 'SALES.OPEN<-1> = 'SALES.ORDERS2' TO SALES.': INPUT ANYTHING STOP END END 64 Developing UniBasic Applications .ORDERS1' END $ELSE OPEN 'PARTS2' TO PARTS ELSE CANT.ORDERS1' END OPEN 'SALES.OPEN<-1> = 'PURCHASE..OPEN<-1> = 'PARTS2' END OPEN 'PURCHASE.Chapter 3 .ORDERS ELSE CANT.OPEN SETTING MORE.ORDERS ELSE CANT.ORDERS1' TO PURCHASE.ORDERS1' TO SALES.ORDERS ELSE CANT..Creating and Running a Program 008: 009: 010: 011: 012: 013: 014: 015: 016: 017: 018: 019: 020: 021: 022: 023: 024: 025: 026: 027: 028: 029: 030: 031: 032: 033: 034: 035: 036: 037: 038: 039: 040: 041: 042: OPEN 'PURCHASE.ORDERS ELSE CANT.OPEN<-1> = 'PURCHASE.FILES PRINT SPACE(5):FILE WHILE MORE.ORDERS2' END $ENDIF IF CANT.ORDERS2' TO PURCHASE.FILES REPEAT PRINT 'Stopping.

Note If you run batch jobs to compile groups of programs. it compiles the program and produces object code. Successful Compilation After UniBasic successfully compiles a program. it displays a completion message and returns you to the UniData colon (ECL) prompt. Developing UniBasic Applications 65 . Object code is stored in the same DIR-type file as the source code. Compiling Unibasic: BP/TEST1 in mode 'u'. but is prefixed with an underscore (_).. The last line of compiler messages indicates whether the program compiled successfully. Warning messages do not terminate processing. The record name for the object code is the same as that for the source code. These messages are preceded by “Warning: ”. The following example demonstrates the successful compilation of program TEST1: Screen Example . it does not produce object code.. For example. you need to code these jobs to terminate only when error messages are returned by the compiler.Compiling a UniBasic Program Compiler Messages The UniBasic compiler displays both warning and error messages. if the compiler generates any error messages. the source code record TEST1 generates object code record _TEST1. However. If the compiler generates warning messages only. compilation finished : The compiler might return warning messages when compilation is successful.

INPUT answer OPEN 'STUDENT' TO STU ELSE PRINT "Can't open STUDENT file.Chapter 3 ." READU RECORD FROM STU..Creating and Running a Program The following program prints a variable that is never assigned a value: Screen Example PROMPT '' PRINT @(-1) PRINT var PRINT "Enter record to update: ". waiting.. Warning: Variable 'var' never assigned a value compilation finished : 66 Developing UniBasic Applications ." RELEASE END The UniBasic compiler returns a warning message when it compiles this program. Screen Example Compiling Unibasic: BP/LOCKUP in mode 'u'. and object code is produced.answer LOCKED PRINT "Record locked by another user." THEN PRINT "I am locking the record now and going to sleep." FOR X = 1 TO 10 SLEEP 2 NEXT X END PRINT "Waking up now. Notice that the program is compiled.

+." THEN PRINT "I am locking the record now and going to sleep. waiting. The example that follows is a UniBasic program that contains the following errors: • • The variable answer is spelled two different ways.string.= ..>.:.AND.” Screen Example 001: 002: 003: 004: 005: 006: 007: 008: 009: 010: 011: 012: 013: 014: PROMPT '' PRINT @(-1) PRINT "Enter record to update: ".<." READU RECORD FROM STU.CAT.variable.MATCH.>=.number.<=." RELEASE END The UniBasic compiler produces the following warning and error messages when it attempts to compile this program: Screen Example Compiling Unibasic: BP/LOCKUP in mode 'u'.!.function. The FOR/NEXT loop beginning on line 8 contains a misspelling: “T” should be “TO..answr LOCKED PRINT "Record locked by another user.Compiling a UniBasic Program Unsuccessful Compilation If UniBasic fails to compile a program. main program: syntax error at or before <line 8> FOR X = 1 T 10 ----------------^ Expecting: array.<>.main program: syntax error at or before <line 10> NEXT X Developing UniBasic Applications 67 .OR. INPUT answer OPEN 'STUDENT' TO STU ELSE PRINT "Can't open STUDENT file. See lines 3 and 5. it returns the cursor to the colon (ECL) prompt.TO." FOR X = 1 T 10 SLEEP 2 NEXT X END PRINT "Waking up now.

Creating and Running a Program -----^ Expecting: end-of-line.. Warning: Variable 'X' never assigned a value Warning: Variable 'T' never assigned a value Warning: Variable 'answr' never assigned a value compilation failed : The missing “O” in “TO” causes the compiler to misinterpret line 8. This capability is especially useful when you use it in conjunction with the UniBasic debugger. This happens when the statement is incomplete. Also. combining multiple statements on the same line. Finally. Creating Cross-Reference Reports With the UniBasic cross-reference capability. However.Chapter 3 . and object code would have been produced.END. the misspelling of the “answer” variable produces an unassigned variable message. 68 Developing UniBasic Applications . you can generate a table that describes statement labels and variables. or including an inordinate number of comment lines could cause the line counter to be incorrect. only warning messages would have been displayed. a runtime error would occur if you tried to execute the program. You can use the cross-referencing feature by compiling programs with the BASIC command and the -L (or -LIST) and -X -L (or -XREF -L) options. the NEXT statement on line10 is not matched. If the only error in this program had been the misspelled variable. and two unassigned variable warning messages result. and the compiler looks for the remainder of the statement on a subsequent line. using the syntax introduced in “ECL BASIC Command Options” earlier in this chapter. Note Syntax errors are sometimes reported on a line following the actual error.

UniBasic produces a cross-reference report listing statement label and variable names used in the program. followed by the program name and a LIST suffix. Type 0 1 2 3 4 5 6 7 8 9 Label Common area Compiler @variable Read-only @variable @variable Variable Variable function Common variable One-dimensioned array Two-dimensioned array Cross-Reference Types Description Developing UniBasic Applications 69 . and ending with equate because it has the highest type number. Type – Type of label or variable. • • Name – Name of the label or variable used in the program. PARTNO. The cross-reference types are described in the following table. or X. including all lines brought in with an $INSERT or $INCLUDE statement. The report states where and how the program uses its labels and variables by listing the name. UniData sorts the report by type starting with label because its type is 0. UniBasic generates a source code listing of the program. which is 14. reference.Compiling a UniBasic Program Listing Included Code When you use the -L (or -LIST) option. type. Listing Statements and Variables When you use the -X -L (or -XREF -L) option. and function of each variable. UniBasic saves the listing in the source directory with an underscore (_) prefix. such as 100.

Argument to called subroutine. Function Symbol References 70 Developing UniBasic Applications . Assignment of variable. Function – UniBasic uses the function symbol to reference the variable. Variable or label is inside an INCLUDE or INSERT statement. Dimension of array.Chapter 3 . Symbols and their functions are listed in the following table. Symbol * = ! @ $ no symbol Function Definition of variable or label. Simple reference such as IF X = 7 THEN.Creating and Running a Program Type 10 11 12 13 14 Description One-dimensioned array argument Two-dimensioned array argument One-dimensioned array in COMMON Two-dimensioned array in COMMON Equate Cross-Reference Types (continued) • • Reference – Line number on which the program refers to the label or variable.

".3) 0010 IF new_product = search_product THEN PRINT "Record is: ":dyn. search_product ON open.INPUT search_product 0003 search_product = OCONV(search_product." 0009 new_product = EXTRACT(dyn.array.test :SPOOL BP _index.file 0006 IF NOT(STATUS()=0) THEN PRINT "Record not found.var 0011 REPEAT 0012 END Developing UniBasic Applications 71 .file ELSE PRINT "Open error.LIST -T BP: _index.array.test." .test. "MCT") 0004 new_product = search_product 0005 SETINDEX "PROD_NAME".LIST BP/index.var FROM open.STOP 0002 PRINT "Enter product to display: ".var.STOP 0007 LOOP UNTIL new_product <> search_product 0008 READFWD dyn.array.Compiling a UniBasic Program Cross-Reference Report Examples The following example shows the compile command with cross-referencing options and the listing UniData generates using the -L option: Screen Example :BASIC BP -X -L Please enter BASIC program file name: index.test Source Listing 0001 OPEN "INVENTORY" TO open.file ELSE PRINT "Readfwd error.

.....XREF BP/index.array.....Creating and Running a Program The following example shows the output from the -X -L option: Screen Example :SPOOL BP _index.......test.....Chapter 3 ....var new_product open....test..file search_product Type....................test Cross Reference Listing Name..... dyn.....XREF -T BP: _index... 5 5 5 5 References. 0008= 0009 0010 0004= 0007 0009= 0010 0001= 0005 0008 0002= 0003= 0003 0004 0005 0007 0010 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 * = ! @ $ Label Common Area Compiler @ Variable Readonly @ Variable @ Variable Variable Variable Argument Common Variable One Dimension Array Two Dimension Array One Dimension Array Argument Two Dimension Array Argument Common One Dimension Array Common Two Dimension Array Equate Definition of Symbol Assignment of Variable Dimension of Array Argument to CALL Include or Insert statement 72 Developing UniBasic Applications ...

see Administering UniData on UNIX or Administering UniData on Windows NT or Windows 2000. more than one user can run the program at the same time. The process and options for cataloging a UniBasic program are introduced in the following sections: • • • • • • • “Points to Remember about CATALOG” “Direct Cataloging” “Local Cataloging” “Global Cataloging” “Using the ECL CATALOG Command” “Removing a Catalog Entry” “CATALOG Examples” Points to Remember about CATALOG The ECL CATALOG command copies the compiled code of a UniBasic program or list of UniBasic programs into the system catalog. Compiled UniBasic programs can be cataloged directly.Cataloging a UniBasic Program Cataloging a UniBasic Program Cataloging UniBasic programs simplifies program execution and can improve efficiency of system resource use by letting multiple users access a single copy of a compiled program from memory. Note For more information about the CATALOG command. or globally. locally. even though only one copy resides in system memory. For more information about managing catalogs. Use the ECL CATALOG command to catalog one or more UniBasic programs. Some points to remember about cataloged programs are listed below: • When you catalog a program globally. see the UniData Commands Reference. Developing UniBasic Applications 73 .

and the UniData Commands Reference. A recataloged program is not available until the user who is recataloging it returns to the ECL prompt. Because users execute the programs from their own address space.Chapter 3 . Users in the same account can execute the program by entering the program name at the ECL prompt. UniData loads a copy of the program into the address space of the user.Creating and Running a Program • • You can use the ECL VCATALOG command to find out if your source code is the same version as the cataloged program. You can use the ECL NEWPCODE command to ensure that you are running the latest version. When a user executes a directly cataloged program. Because users access the compiled code in the program file. • • • 74 Developing UniBasic Applications . Direct Cataloging Keep in mind the following points about direct cataloging: • • Compiled code is located in the program file in the UniData account where the program was compiled and cataloged. Note For more information about NEWPCODE and VCATALOG. developers do not need to recatalog the code if they recompile. see Administering UniData on UNIX or Administering UniData on Windows NT or Windows 2000. The VOC file in the account contains a pointer to the compiled code in the program file. one user can recompile a directly cataloged program while another user is running the program.

When a user executes a locally cataloged program. Developers must recatalog a program after recompiling. The account’s VOC file contains a pointer to the compiled program in the CTLG. and each record is a compiled UniBasic program. CTLG is a directory. • • Global cataloging is the default. If a copy does not exist in memory. to place a new copy of the compiled code into the CTLG. If you execute the CATALOG command without specifying local or direct cataloging. a process is currently executing either the program in question or a program that called the program in question. Developing UniBasic Applications 75 . The program in question cannot be recataloged until all processes executing it.Cataloging a UniBasic Program Local Cataloging Keep in mind the following points about local cataloging: • Compiled code is located in the CTLG directory in the UniData account where the program was cataloged. have completed. Users in the same account can execute the program by entering the program name at the ECL prompt. Because users execute the programs from their own address space. • • • • Global Cataloging Keep in mind the following points about global cataloging: • When a user tries to globally catalog a UniBasic program. your program is globally cataloged. UniData checks to see if a copy of the program resides in memory. • If a copy exists in memory. UniData loads a copy of the program into the user’s address space. UniData copies the new compiled code into the global catalog. or all programs that called it. and the CATALOG command fails. UniData displays an error message. no one is currently executing it and no program that is still running has called it. one user can recompile a directly cataloged program while another user is running the program. as well as in the program file.

The program name can be the same as the source and object. Cataloged programs that begin with nonalpha characters are stored in the subdirectory named X. as in *prog. Compiled code is stored in the subdirectory corresponding to the first letter of the program name. Developers must recatalog a program after recompiling. For more information about multiple global catalog spaces. 76 Developing UniBasic Applications . To run a globally cataloged program if you have a program with the same name cataloged locally or directly.Creating and Running a Program • Compiled code is located in a system wide global catalog. udthome determines which global catalog space a particular UniData session accesses. Even though Windows NT or Windows 2000 do not require file and path names that are case sensitive.name. Tip Consider your program naming conventions if you are using global cataloging. • A system-wide global catalog space is a directory with 26 subdirectories named A through Z. see Administering UniData on UNIX or Administering UniData on Windows NT or Windows 2000. • • • Note A UniData installation can have more than one global catalog space. Because the compiled code is placed in subdirectories according to name. you could have an unbalanced situation if a large number of your program names begin with the same letter (for instance. UniData checks to see if a copy already exists in shared memory.Chapter 3 . UniData uses case-sensitive strings for comparing and searching for names in cataloged programs. The default global catalog is /udthome/sys/CTLG (for UNIX) or \udthome\sys\CTLG (for Windows NT or Windows 2000). to place a new copy of the compiled code into the global catalog. a general ledger application in which all the files begin with “gl”). When a user executes a globally cataloged program. • • A globally cataloged program is available to users in all UniData accounts. or you can specify a different name when you execute the CATALOG command. precede the program name with an asterisk.

name cat. The following table describes each parameter of the syntax. Catalog Command Options LOCAL Developing UniBasic Applications 77 . the compiled code is placed in the program file and in the system global catalog. This is the default option (do not specify it in the CATALOG command). cataloged code is placed in the program directory with the source code and in the system global catalog. The LOCAL option is available on the local account. UniData notifies the udt process where to locate the copy in shared memory. Users share one copy of the cataloged code. To use it from another account. This makes the program available to all accounts. This makes the program available to all accounts. Option file. Compiled code is located in the program file and in local catalog space. enter the following command at the ECL prompt: Syntax: CATALOG file. catalog it in the other account also. Using the ECL CATALOG Command To catalog a program.Cataloging a UniBasic Program • • If so. Users share one copy of the compiled code. Specifies the name of the system catalog into which the object code is to be copied. If not. UniData loads a copy into shared memory for the user to execute.name prog.name [LOCAL | DIRECT] [FORCE] [NEWVERSION | newversion] By default.name GLOBAL Features Specifies the file containing the program to be cataloged. Specifies the UniBasic program containing object code to be cataloged. Usually a basic program (BP) file.name cat.name prog.

For example. For more information. Replace a cataloged program without prompting. To use it on another account. catalog it in that account also. you must have root privileges on UNIX or Administrator privileges on Windows NT or Windows 2000. Removing a Catalog Entry Use the ECL DELETE.For more information about the NEWVERSION option.Creating and Running a Program Option DIRECT Features The compiled code is placed in the program file only and is available only on the local account. You need to use F (force) in conjunction with the N option. recataloging is not required when you recompile the program. Tip . Directs the shared basic code server (sbcs) to replace the current program version in shared memory with the new version just cataloged. Note . Catalog Command Options (continued) FORCE NEWVERSION newversion Reminder You can execute a cataloged program from the ECL prompt or from any UniBasic program. FIBCFN compiles a program and catalogs it (locally) with NEWPCODE.CATALOG command to remove a cataloged program.The N option of the Alternate Editor (AE) FI command equates to NEWPCODE. see the UniData Commands Reference.Chapter 3 . see Administering UniData on UNIX or Administering UniData on Windows NT or Windows 2000. 78 Developing UniBasic Applications . To use NEWVERSION. see the online help for AE. For more information about this command.

. do you want to overwrite?(Y/N)Y The following example lists the contents of the CTLG file in the demo database: Screen Example :LIST CTLG LIST CTLG 17:39:37 Aug 04 1999 1 CTLG.UTIL CUST. AddRecord DelRecord DUMMY EXAMPLE FndRecord UpdRecord 6 records listed : Developing UniBasic Applications 79 .XREF FORCE The next example shows the CATALOG command without the FORCE option. whose source code is located in the BP.UTIL directory file: Screen Example :CATALOG BP... Screen Example :CATALOG BP GPA /usr/ud/sys/CTLG/GPA exists.XREF.Cataloging a UniBasic Program CATALOG Examples The following example shows the FORCE option to globally catalog the object code of the program CUST.. UniData requests verification before proceeding to recatalog the item.. Because the program GPA was already cataloged.

\UniData\demo\CTLG) and shows where the program source is kept (BP_SOURCE). In the next example. Screen Example :CATALOG BP_SOURCE PSTLCODE_FMT LOCAL :LIST CTLG LIST CTLG 17:39:37 Aug 04 1999 1 CTLG. Afterwards. notice the following: • • The local CTLG directory shows an entry for PSTLCODE_FMT.Creating and Running a Program Reminder You must compile your programs successfully before you can catalog them...Chapter 3 . A VOC pointer exists that shows a path to a copy of the program (in this case... UniData catalogs the compiled object code of the PSTLCODE_FMT program locally.. AddRecord DelRecord DUMMY EXAMPLE FndRecord PSTLCODE_F MT UpdRecord 7 records listed :CT VOC PSTLCODE_FMT VOC: PSTLCODE_FMT: C D:\UNIDATA\DEMO\CTLG\PSTLCODE_FMT BP_SOURCE PSTLCODE_FMT : 80 Developing UniBasic Applications .

and notice how the path to the program has changed. use the ECL DELETE command or DELETE. The DIRECT keyword causes UniData to create a VOC pointer that points to the file in which the program resides. Screen Example :CATALOG BP_SOURCE PSTLCODE_FMT DIRECT PSTLCODE_FMT has been cataloged. UniData does not place a copy of the program in either CTLG directory. Compare the VOC record to the previous example. In ECLTYPE P.Cataloging a UniBasic Program In the next example. UniData directly catalogs the PSTLCODE_FMT program.CATALOG. you also can use the DECATALOG command. do you want to overwrite(Y/N)? Y :CT VOC PSTLCODE_FMT VOC: PSTLCODE_FMT: C BP_SOURCE\_PSTLCODE_FMT : Tip To remove a copy of a program from the local or system CTLG directory. Developing UniBasic Applications 81 .

the last successfully compiled version runs. Reminder The FIR command files the source code you are editing and runs the compiled version. BP). enter its cataloged name at the ECL prompt. enter the AE command FIBR at the AE command prompt. Be sure to use the AE command FIBR to compile. Running a Program from AE To compile and run a program you are currently editing. Syntax: catalog.file program. To run the program.Creating and Running a Program Running a UniBasic Program You can run a program from AE or from ECL. If the program is not globally cataloged. runs the compiled version.name [-option] If the program is globally cataloged. UniData compiles and files the program. The two versions will be different if you have modified the program since the last compilation. and displays the ECL prompt. Syntax: RUN directory. you must specify the directory file that contains the program (for example. file.name [-option] 82 Developing UniBasic Applications .Chapter 3 . If compilation is unsuccessful. and run the program. you must have a pointer to the directory file that contains the program in your VOC file to execute the globally cataloged version. Running a Program from ECL The RUN command tells UniData to run a compiled UniBasic program.

Invokes the UniBasic debugger when a warning or runtime error occurs.Running a UniBasic Program In addition. Invokes the UniBasic debugger immediately.name [-option] RUN Options The following table describes the options [-option] in the syntax for running a program. see “Reporting Execution Time” later in this chapter. you can run a program that is locally cataloged by entering the its name at the ECL prompt. Option -D -E -F -D -E Description Invokes the UniBasic debugger immediately before the program executes. you must prepare your program as explained in the Using the UniBasic Debugger. UniData returns to the debugger. Invokes the UniBasic debugger immediately. UniBasic programs are usually stored in the BP directory. Creates a cross-reference report (program profile). if UniData encounters a fatal error. After you execute the program from the debugger. Program Run Options -D -F -G Developing UniBasic Applications 83 . Syntax: program. if UniData encounters a warning or runtime error. UniData returns to the debugger. Reminder Several of the following RUN options invoke the UniBasic Debugger. To make full use of the debugger. For further information. Invokes the UniBasic debugger when a fatal error occurs. After you execute the program from the debugger.

Without this option. If you previously compiled the program with the -G option.elapse. the profile also reports on internal subroutines. 84 Developing UniBasic Applications .OPTIONS Commands Reference. profile. and are named as follows: • "profile. scrolling stops at the bottom of each page.Use UDT."@USERNO (for UNIX) or "profile.OPTIONS You can determine how UniBasic sets an uninitialized variable with UDT.elapse. prompting the user to press ENTER to continue. -P -S Routes all program output to the system printer. the file profile.OPTIONS 15 on for empty string or off for zero. UniData creates two reports that it stores in the current directory."pid (for Windows NT or Windows 2000) – Calculates real execution time (CPU and I/O).3 would be the corresponding report of real execution time for the same user. For example.Creating and Running a Program Option -N Description Displays output without pausing at the bottom of the screen."pid (for Windows NT or Windows 2000) – Calculates CPU execution time. Both reports are of the same format.OPTIONS. Suppresses warning messages. For more information about UDT.Chapter 3 . Tip .OPTIONS 32 to direct UniData to retain or suppress the HEADING statement when the “no page” option is used. For example. see the UDT. • "profile."@USERNO (for UNIX) or "profile. Reporting Execution Time UniData generates a program profile report when you run or execute a program with the -G option.elapse.3 would be a report of CPU time generated for the user whose user number is 3. Program Run Options (continued) UDT.

00 0.0 0.04 0. Each index is analyzed in a subsection delineated by dashed lines. Parent programs and subroutines are analyzed on the lines preceding the index number.08 0.08 0.02 0. It is listed as USRNBR.00 0.06 0. subroutine.00 0. Layout of Profile Reports Summary Section – Summary statistics regarding execution time are listed for each program.Running a UniBasic Program Note For Windows NT or Windows 2000. run the LISTUSER command to determine the process ID (pid). Body Section – Each program or subroutine is assigned an identifying index number.0 0. For more information about program profiling.0 0. see Administering UniData on UNIX or Administering UniData on Windows NT or Windows 2000.Sample Program”: Screen Example %time cumsecs seconds %time cumsecs seconds 25.0 25.0 0.0 0.00 0.0 0. the indexed item is analyzed on the line containing the index number.08 0.08 0.0 0.08 0.02 0.0 25.02 0. in descending order of execution time. and child programs or subroutines are analyzed on subsequent lines.0 25. the first column lists the index number for the program or subroutine analyzed in that section.0 0.02 0.02 0.00 0.08 0. and called program.00 0.08 0. entries are sorted by decreasing execution time. The following UNIX example is the profile report for the UPDATE_ORDER program in “Appendix A .00 calls name calls name 1 3 2 1 1 1 3 1 1 1 1 BP/_UPDATE_ORDER BP/_UPDATE_ORDER:DISPLAY_SCREEN BP/_UPDATE_ORDER:DISPLAY_DATA BP/_UPDATE_ORDER:ALTER_RECORD BP/_UPDATE_ORDER:OPEN_FILES BP/_UPDATE_ORDER:INITIALIZE BP/_UPDATE_ORDER:GET_ORDER_NUMBER /users/ud_51/sys/CTLG/d/DISPLAY_MESSAGE BP/_UPDATE_ORDER:GET_RECORD_COMMAND BP/_UPDATE_ORDER:WRITE_RECORD BP/_UPDATE_ORDER:EXIT Developing UniBasic Applications 85 .08 0. Within the subdivided sections.

Creating and Running a Program index %time self descendents called/total called+self called/total 1 3/3 2/2 [1] [2] 100.02 0.00 1/1 /users/ud_51/sys/CTLG/d/DISPLAY_MESSAGE [9] ---------------------------------------------0.00 3/3 BP/_UPDATE_ORDER:GET_ORDER_NUMBER [8] 0.0 0.00 3 BP/_UPDATE_ORDER:DISPLAY_SCREEN [2] ---------------------------------------------0.00 2 BP/_UPDATE_ORDER:DISPLAY_DATA [3] 0.00 1/1 BP/_UPDATE_ORDER:GET_RECORD_COMMAND [5] [4] 25.00 1 BP/_UPDATE_ORDER:OPEN_FILES [6] ---------------------------------------------- 86 Developing UniBasic Applications .00 1/1 BP/_UPDATE_ORDER [1] [6] 0.00 1/1 BP/_UPDATE_ORDER:EXIT [11] ---------------------------------------------0.00 1/1 BP/_UPDATE_ORDER:OPEN_FILES [6] 0.00 0.02 1/1 BP/_UPDATE_ORDER [1] [5] 25.06 0.00 0.00 parents name index children <spontaneous> BP/_UPDATE_ORDER [1] BP/_UPDATE_ORDER:DISPLAY_SCREEN BP/_UPDATE_ORDER:DISPLAY_DATA [3] 0.02 0.02 0.00 0.02 1 BP/_UPDATE_ORDER:GET_RECORD_COMMAND [5] 0.00 0.0 0.02 0.0 0.00 1 BP/_UPDATE_ORDER:ALTER_RECORD [4] 0.00 0.00 1/1 BP/_UPDATE_ORDER:INITIALIZE [7] 0.02 0.02 0.0 0.Chapter 3 .02 1/1 BP/_UPDATE_ORDER:GET_RECORD_COMMAND [5] 0.02 0.0 0.00 3/3 BP/_UPDATE_ORDER [1] [2] 25.00 0.00 0.00 0.00 0.00 0.02 0.00 1/1 BP/_UPDATE_ORDER:ALTER_RECORD [4] ---------------------------------------------0.00 2/2 BP/_UPDATE_ORDER [1] [3] 25.02 0.02 0.00 0.00 0.0 0.00 1/1 BP/_UPDATE_ORDER:WRITE_RECORD [10] ---------------------------------------------0.

in number of seconds.00 0.00 1/1 BP/_UPDATE_ORDER:DISPLAY_DATA [3] [9] 0.00 3/3 BP/_UPDATE_ORDER [1] [8] 0.00 1/1 BP/_UPDATE_ORDER [1] [7] 0.00 1/1 BP/_UPDATE_ORDER [1] [11] 0.00 1 /users/ud_51/sys/CTLG/d/DISPLAY_MESSAGE [9] ---------------------------------------------0.0 0. Execution time.0 0.00 0. for this program or subroutine and all called programs and subroutines.00 1 BP/_UPDATE_ORDER:EXIT [11] ---------------------------------------------- ---------------------------------------------- The summary section of the report provides information in the following columns.00 0. for this program or subroutine alone.00 0.00 0.00 0. in number of seconds. Name of the program or subroutine.00 0.0 0.0 0. Number of times this program or subroutine is called. Program Profile – Summary Developing UniBasic Applications 87 .00 1 BP/_UPDATE_ORDER:WRITE_RECORD [10] ---------------------------------------------0.00 0. Parameter %time cumsecs seconds calls name Description Percentage of the total runtime used by this program or subroutine.00 1/1 BP/_UPDATE_ORDER:ALTER_RECORD [4] [10] 0.0 0.00 0. Execution time.Running a UniBasic Program 0.00 3 BP/_UPDATE_ORDER:GET_ORDER_NUMBER [8] ---------------------------------------------0.00 1 BP/_UPDATE_ORDER:INITIALIZE [7] ---------------------------------------------0.00 0.

name index Name of the program or subroutine analyzed in this row of the report subsection. Program Profile – Body The tables that follow the next example explain the detail report lines for item [3] in the report. lists number of times the routine is called and the number of times it calls itself. Execution time for this program or subroutine. Index identifying the program or subroutine listed in the name field. Index numbers are assigned in descending order of execution time.Creating and Running a Program The body of the report provides information in the following columns. Parameter index %time self descendents called Description An identifying number assigned to this program or subroutine. The subject lines are repeated here. • called/total – Lines following the index number analyze children and descendents. 88 Developing UniBasic Applications . Line contents differ according to the line of the subsection you are reading: • called/total – Lines preceding the index analyze parents. lists number of times this index is called by the parent listed in the name field.Chapter 3 . Percentage of the total program runtime used by this program or subroutine and its descendents. lists number of times this index calls the child listed in the name field. Execution time for descendents of this program or subroutine. • called+self – Line containing the index.

The index number for BP/_UPDATE_ORDER. 0. The parent (calling subroutine). The number of times parent BP/_UPDATE_ORDER called BP/_UPDATE_ORDER:DISPLAY_DATA.00 0.Running a UniBasic Program Screen Example called/total parents called+self name index called/total children <spontaneous> ---------------------------------------------0. BP/_UPDATE_ORDER.00 2/2 BP/_UPDATE_ORDER [1] Program Profile Detail: First Line Developing UniBasic Applications 89 . The execution time for parent (calling program).02 0. BP/_UPDATE_ORDER.00 2 BP/_UPDATE_ORDER:DISPLAY_DATA [3] 0.02 0. Data 0.00 2/2 BP/_UPDATE_ORDER [1] [3] 25.02 Column self descendents called/total parents index Description The execution time for parent (calling program).00 1/1 /users/ud_51/sys/CTLG/d/DISPLAY_MESSAGE [9] ---------------------------------------------index %time self descendents The following table describes the first line of the preceding report segment.0 0. in this case. in this case.

BP/_UPDATE_ORDER: DISPLAY_DATA [3] The name of this subroutine. 0.0 The percentage of the total program runtime used by BP/_UPDATE_ORDER:DISPLAY_DATA. 25. The execution time for BP/_UPDATE_ORDER:DISPLAY_DATA. The execution time for child (called program).00 self descendents name index number 0.Chapter 3 . in this case. Program Profile Detail: Second Line The final table describes the third line of the preceding report segment. /users/ud_52/sys/CTLG/d/ DISPLAY_MESSAGE.00 Column self Description The execution time for child (called program).02 The execution time for /users/ud_52/sys/CTLG/d/DISPLAY_MESSAGE. Data [3] Column index %time Description The index number for BP/_UPDATE_ORDER:DISPLAY_DATA . /users/ud_52/sys/CTLG/d/ DISPLAY_MESSAGE. in this case.00 descendents Program Profile Detail: Third Line 90 Developing UniBasic Applications . The index number for BP/_UPDATE_ORDER: DISPLAY_DATA . Data 0.Creating and Running a Program The next table describes the second line of the preceding report segment. 0.

Program Profile Detail: Third Line (continued) Developing UniBasic Applications 91 . The index number for /users/ud_52/sys/CTLG/d/ DISPLAY_MESSAGE.Running a UniBasic Program Data 1/1 Column called/total Description The number of times parent BP/_UPDATE_ORDER:DISPLAY_DATA called child /users/ud_52/sys/CTLG/d/DISPLAY_MESSAGE. /users/ud_52/sys/CTLG/d/ DISPLAY_MESSAGE [9] child index The name of this child (called program).

Creating and Running a Program 92 Developing UniBasic Applications .Chapter 3 .

Maintaining Data in Files This chapter provides the information you need to select the correct command or function for maintaining data in files through UniBasic programs. For the syntax of these commands. Developing UniBasic Applications 93 .Chapter 4 . see the UniBasic Commands Reference.

Writing. and Deleting Data from Files” “Closing Files” “Accessing Data in Unopened Files” 94 Developing UniBasic Applications .Chapter 4 .Maintaining Data in Files In This Chapter This chapter introduces the concepts and commands you use to maintain files. It consists of the following sections: • • • “UniData Locks” “Database Triggers” “Maintaining Files” • • • • • • • • “UniData Hashed Data Files” “Alternate Key Indexes” “Non-UniData Sequential Files” “Opening Files” “Selecting Records” “Reading.

check. and release UniBasic locks. You can use resource locks to reserve computer resources for your exclusive use. For information about using UniBasic locks. you must use the commands specifically created for the purpose. For more information. record and file locks.” Developing UniBasic Applications 95 . UniBasic locks are advisory only. You must observe locking conventions consistently in all of your applications to prevent one user from overwriting another user’s updates. To set.Using UniData Locks.UniData Locks UniData Locks In a multiuser system. prevent more than one user from accessing the same record at the same time.UniBasic Transaction Processing Concepts. when used consistently.UniBasic Transaction Processing. see “Chapter 9 . see “Chapter 5 .” Tip Another way to ensure consistency among files is through UniData transaction processing.” or “Appendix B .

When running Network File Access (NFA). • • • Writing from a trigger subroutine: 96 Developing UniBasic Applications . the trigger subroutine and the trigger itself must reside on the server where the hashed file resides. UniData triggers are activated before the update or delete. A UniData trigger can be used to validate an attempt to make a change to the database against user-defined constraints. or prevent entry of the null value. so the business rules are applied to any access to the file or record. For instance. The UniBasic subroutine can then allow or prevent access. You can call an external C routine from a trigger. or prevent some records from being updated at all. Trigger Rules UniData triggers are governed by the following rules: • • • • A UniData trigger must be a globally cataloged UniBasic subroutine. Be careful to use conditional statements to avoid infinite loops that can be caused by nested triggers. A trigger can invoke another trigger. Triggers are associated with the data file.” and allow the change only if the constraint is satisfied.Chapter 4 . No DIR or multilevel directories – You cannot set a trigger on a DIR file or a multilevel directory. File types: • • Hashed files – You can use triggers only with static or dynamic hashed files. Triggers are tied to record updates (modifying or inserting) and deletions. not on the host. or “business rules. not just access through a particular application.Maintaining Data in Files Database Triggers A database trigger specifies a UniBasic subroutine to call when a user attempts to access a record. The files can be recoverable or nonrecoverable. a trigger subroutine might allow only certain users to update records in a UniData file. You can associate triggers with the static or dynamic subfiles within a multilevel file. but not with the multilevel file itself. UniData does not limit the number of levels you can nest triggers.

Use the ECL CREATE.Database Triggers • • Writes allowed to DIR files – You can write to a directory file from within a trigger subroutine. The Nature of Triggers Triggers are composed of the trigger definition. UniData does not overwrite the existing trigger. and lists ECL commands that are affected by triggers. delete. Note To create or delete a trigger. and a globally cataloged UniBasic subroutine that is called when you attempt to update or delete a record. For example. The UniBasic trigger subroutine can contain any operation on a file. and list triggers.TRIGGER command to define a trigger. You might want to do so to create a log of trigger operations. which is stored in the file header. Instead. If the file header already contains a trigger by the same name. You can change the underlying trigger subroutine without having to delete and re-create the trigger. Developing UniBasic Applications 97 . you must delete the existing trigger before you can create the new one. Command syntax and details about how to code these commands follow this section. or it might place restrictions on whether users can delete records from a particular file. the subroutine could stipulate that certain kinds of record modifications are not allowed for a file. Writes allowed to hashed files – You can include write commands within a trigger subroutine. you must be the owner of the file at the operating system level. Note that these changes to the trigger in the file header do not affect the UniBasic subroutine. including writing to it. or you must have root privileges on UNIX or Administrator privileges on Windows NT or Windows 2000. ECL Commands and Triggers This section discusses ECL command that create or maintain triggers. Three ECL commands let you create.

DELETE. see the UniData Commands Reference. see the UniData Commands Reference. For the syntax of these commands.FILE COPY DELETE ED MODIFY UNIENTRY UniBasic Commands Affected by Triggers The following UniBasic commands invoke triggers: • • • • • DELETE DELETEU WRITE WRITEU WRITEV 98 Developing UniBasic Applications .Chapter 4 . • • • • • • CLEAR.Maintaining Data in Files ECL Commands That Create or Maintain Triggers The following ECL commands create or maintain triggers.TRIGGER – Deletes the trigger definition from a file header. ECL Commands Affected by Triggers The UniData triggers feature has an impact on how some ECL commands behave. LIST.TRIGGER – Displays a list of triggers. For the syntax of these commands. The following commands have changed behavior. It does not affect the UniBasic trigger subroutine. • • • CREATE.TRIGGER – Creates a trigger in a file header that calls a UniBasic subroutine.

control is passed to the ON ERROR clause of the command.Database Triggers • WRITEVU If a trigger returns a constraint violation. Developing UniBasic Applications 99 . if one exists. If no ON ERROR clause is included in the command. the UniBasic program aborts.

The trigger subroutine also returns a value indicating its status in the parameter execstat. filename. Tip You can call an external C routine from the UniBasic subroutine or function that is called from a trigger. the values returned in execstat are listed in the Parameters sections for the UPDATE and DELETE trigger subroutines. filename. Syntax: SUBROUTINE trigname(execstat. These values are listed in “UniBasic STATUS Function Return Values” later in this chapter. Syntax: FUNCTION trigname(dictflag. recordval) The parameters in this statement are defined later in this section. record. record.expr.ID. dictflag.Chapter 4 . recordval) 100 Developing UniBasic Applications .expr.ID. Subroutine The following SUBROUTINE definition must be the first noncomment line in the UniBasic trigger subroutine. You can place it within the trigger subroutine to learn about the status of individual commands executed within the trigger. Writing an UPDATE Trigger Subroutine A UniBasic subroutine or function serves as the UPDATE trigger that is executed when a user attempts to update a record in the subject file. it returns the status of the UniBasic command as determined by the trigger.Maintaining Data in Files Tip The UniBasic STATUS function returns the status of the preceding command. If you place it immediately after the statement that calls the trigger. Function The following FUNCTION definition must be the first line in the UniBasic trigger function.

Trigger Parameters Developing UniBasic Applications 101 . • “” – Indicates that the trigger is operating on the data file. dictflag • “DICT” – Indicates that the trigger is operating on the dictionary file. The execution status returned by the trigger subroutine: • 0 – No updates are allowed.Database Triggers The function must include the following statement: RETURN excstat Parameters The following table describes each parameter of the syntax. The record to be updated. filename record.ID.The quotation marks are required. using the return recordval. Parameter trigname execstat Description The name of the globally cataloged subroutine.expr The name of the file on which the trigger is operating. • 1 – Updates are allowed. • 2 – Updates are allowed. Note .

the UniBasic STATUS function returns 3 when executed immediately after the command that calls the trigger.trig.val) exec. Note . Trigger Parameters (continued) UPDATE Trigger Example The following example begins with an UPDATE trigger subroutine called TRIG1. no record in the file can be updated.rec.id.stat.expr. Only strings and numbers are valid. Program Example SUBROUTINE TRIG1(exec. the record is not updated. Because the return status is always 5. Only strings and numbers are valid.stat=5 RETURN 102 Developing UniBasic Applications .dict. if the trigger sets execstat to 2.Maintaining Data in Files Parameter recordval Description The input record value submitted to the UPDATE trigger.rec. recordval is both an input and output parameter.flag. Then. even if the trigger subroutine sets execstat to 2.If the value returned in recordval is invalid. The trigger can change this value (for example.name.Chapter 4 . In this case. by performing a conversion). this value is passed back in recordval and updates the data record.

Developing UniBasic Applications 103 . we create the trigger. and the trigger prevents the copy: Screen Example :COPY FROM ORDERS TO ORDERS 969. 0 records copied Writing a DELETE Trigger Subroutine A UniBasic subroutine or function serves as the DELETE trigger that is executed when a user attempts to delete a record in the subject file.TRIGGER ORDERS TRIG1 UPDATE :LIST. Tip You can call an external C routine from the UniBasic subroutine or function that is called from a trigger.TRIGGER ORDERS BEFORE UPDATE TRIGGER: TRIG1 BEFORE DELETE TRIGGER: not defined Finally. we attempt to copy record 969 into record 970 in the ORDERS file.970 Cannot update 970. due to trigger constraint. and list the triggers associated with the ORDERS file: Screen Example :CREATE.Database Triggers Next. associate it with the ORDERS file.

Parameter trigname execstat Description The name of the globally cataloged subroutine.ID. The execution status returned by the trigger subroutine. Syntax: SUBROUTINE trigname(execstat. dictflag.Maintaining Data in Files Subroutine The following SUBROUTINE definition must be the first line in the UniBasic trigger subroutine.expr) The function must include the following statement: RETURN execstat Parameters The following table describes each parameter of the syntax. Valid values for this include: • 0 – Delete is not allowed • 1 – Delete is allowed Trigger Parameters 104 Developing UniBasic Applications .ID.Chapter 4 . filename.expr) The parameters in this statement are listed later in this section. record. Syntax: FUNCTION trigname(dictflag. record. filename. Function The following FUNCTION definition must be the first line in the UniBasic trigger function.

expr The name of the file the trigger is operating on.trig.flag. Trigger Parameters (continued) DELETE Trigger Example The following example begins with a DELETE trigger subroutine called DEL_TRIG that always returns 1 and always allows records to be deleted: Program Example SUBROUTINE DEL_TRIG(exec.expr. Note .Database Triggers Parameter dictflag Description • “DICT” – Indicates that the trigger is operating on the dictionary file. Next. • “” – Indicates that the trigger is operating on the data file.rec.name.stat.id.TRIGGER ORDERS DEL_TRIG DELETE Developing UniBasic Applications 105 . we create the trigger and associate it with the ORDERS file: Screen Example :CREATE.rec.val) exec.The quotation marks are required.ID.dict. you must catalog it globally.stat=1 RETURN Reminder After creating and compiling the subroutine. filename record. The record to be deleted.

Screen Example :DELETE ORDERS 912 '912' deleted. we delete records in the ORDERS file. : UniBasic STATUS Function Return Values The UniBasic STATUS function returns values that give information about trigger operations. within a trigger or outside a trigger. indicating that the update or delete is not allowed. Trigger execution error or unexpected return from trigger routine (for example. set the value of STATUS. Return Value 0 1 2 No error. In this case. the UniBasic trigger subroutine returns a value of 0 in the parameter excstat. 106 Developing UniBasic Applications . STATUS Function Values Description 3 Note Most UniBasic commands and some ECL commands. The trigger always allows the deletion because the subroutine sets the execution status to 1. trigger subroutine is not cataloged).Maintaining Data in Files Finally. such as a damaged file.Chapter 4 . Constraint violation. System error.

Database Triggers

Warning
When you write UniBasic programs or subroutines, always include the ON ERROR clause for statements that update hashed files. This is especially important when using triggers, because any failure caused by a trigger aborts the UniBasic program unless the ON ERROR clause is present.

Troubleshooting
If a trigger does not work correctly, check the following: • • • Debug and test trigger subroutines. Check the return values. Are they what UniData expects? Is the trigger subroutine cataloged?

Developing UniBasic Applications

107

Chapter 4 - Maintaining Data in Files

Maintaining Files
You can write UniBasic programs to maintain hashed data files, alternate key indexes, and nonUniData sequential files. The following sections describe how to maintain them: • • • “UniData Hashed Data Files” “Alternate Key Indexes” “Non-UniData Sequential Files”

UniData Hashed Data Files
The types of UniData files that you can maintain with UniBasic programs are introduced in “Chapter 1 - Introduction to UniBasic.” This section suggests the steps you might follow to maintain files.

Maintaining UniData Hashed Files
The following procedure is one that you might follow when updating a UniData hashed file. (For a sample program, see “Appendix A - Sample Program.”) 1. Use the OPEN command to open the data file. 2. Use one of the following methods to select records: • • Create a select list using SELECT, SELECTINDEX, UniQuery SELECT, UniData SQL SELECT, or a paragraph select. Set a pointer in an alternate index with SETINDEX.

3. Use one of the following commands to read data from selected records: READU (use this command to set an exclusive lock), READ, READV, READVL, READVU, READNEXTTUPLE, READFWD, READBCK, READFWDL, READBCKL, READFWDU, READBCKU 4. Manipulate data in arrays. See “Chapter 6 - Working with Data in Programs.”

108

Developing UniBasic Applications

Maintaining Files

5. Use one of the following commands to write data to selected records: WRITE, WRITEU, WRITEV, WRITEVU, WRITET 6. Use the CLOSE command to close the data file.

Alternate Key Indexes
Alternate key indexing speeds searching for records within a database. Alternate keys allow access to records without the need to use the record ID or read through the entire file. An alternate key index consists of values for the alternate key and the associated @IDs of each record.

The Primary Key
UniData requires that each record in the database have a unique identifier, which is called the record ID, @ID, or primary key. The UniData hashing algorithm uses the @ID to locate the record in the database. When UniData looks for a record, it uses the @ID as the “key” to finding the record quickly.

Tip
Create an index for @ID to speed access to data records.

The Alternate Key
UniData allows only one primary key for a record. If you are searching for a record based on the primary key, searches are fast. Most of the time, however, searches are based on other information contained in a record, such as a name, city, phone number, or the result of a virtual attribute calculation. These searches are slower than a search based on the primary key. You can create alternate keys any time after you create the data file. For more information, see Using UniData or the CREATE.INDEX command in the UniData Commands Reference.

Developing UniBasic Applications

109

Chapter 4 - Maintaining Data in Files

Duplicate Alternate Keys
Although primary keys must be unique, duplicate alternate keys can be entered. To block the entry of duplicate keys in indexes of non-RFS files, specify the NO.DUPS keyword when you create the index (with CREATE.INDEX). However, if you do so, you will not be able to build the index by using BUILD.INDEX if duplicate values are already present in the key attribute in your data file. Also, any WRITE command that attempts to create a duplicate alternate key will generate a fatal error if no ON ERROR clause is coded.

Note
The Recoverable File System (RFS) does not support NO.DUPS. You can detect duplicate keys by executing the ECL command DUP.STATUS ON, then checking for a STATUS function return value of 10 immediately after the following UniBasic commands: • • • WRITE, WRITEU, WRITEV, WRITEVU READFWD, READFWDL, READFWDU READBCK, READBCKL, READBCKL

Creating and Maintaining Alternate Indexes
You might perform the following steps to create and manage alternate indexes. For the syntax of the ECL commands, see the UniData Commands Reference. 1. Use the ECL CREATE.INDEX command to create the index. 2. Use the ECL BUILD.INDEX command to load alternate keys into the index.

Note
You cannot execute BUILD.INDEX while users are accessing the file. 3. Use the ECL ENABLE.INDEX or DISABLE.INDEX command to enable or disable (respectively) the automatic updating of the alternate key index. You also can use the ECL UPDATE.INDEX command to update the index manually.

110

Developing UniBasic Applications

Maintaining Files

4. Use the SELECTINDEX command to build a select list based on the alternate index file, or use the SETINDEX command to set a pointer to an alternate key value in the index. 5. Read records from the UniData file by using the alternate index and any of the following UniBasic commands: READFWD, READFWDL, REAFWDU, READBK, READBKL, READBKU

Using Alternate Index Files
Use the following alternate index commands and functions to speed access to UniData files. For syntax and usage, see the UniBasic Commands Reference. Command/ Function FILEINFO Action Returns the name of the index to which the last SETINDEX statement was applied. Also requests the key value of the index for the record that was read by the last browsing statement, such as READFWD or READBCK. Retrieves one record ID from an index, assigns the contents of the record to a dynamic array, and assigns the record ID to the @ID variable. Same as READBCK, but places a shared lock on the record. Same as READBCK, but places an exclusive lock on the record. Retrieves one record ID from an index, assigns the contents of the record to a dynamic array, and assigns the record ID to the @ID variable. Same as READFWD, but places a shared lock on the record. Alternate Index Commands

READBCK

READBCKL READBCKU READFWD

READFWDL

Developing UniBasic Applications

111

Chapter 4 - Maintaining Data in Files

Command/ Function READFWDU SELECTINDEX

Action Same as READFWD, but places an exclusive lock on the record. Creates a select list based on an alternate key. The list can contain all records for this alternate index or a subset based on a particular key value. Sets a pointer to the initial alternate key value in the alternate index. Use READFWD or READBACK to traverse the index. Alternate Index Commands (continued)

SETINDEX

The following program demonstrates use of an alternate index file for the demonstration database file INVENTORY. The index is on attribute 3, PROD_NAME. The program prompts the user for a product, and then it prints all records for that product.

Program Example
OPEN "INVENTORY" TO open.file ELSE PRINT "Open error." ;STOP PRINT "Enter product to display: ";INPUT search_product search_product = OCONV(search_product, "MCT") new_product = search_product SETINDEX "PROD_NAME", search_product ON open.file IF STATUS()>0 THEN PRINT "Record not found.";STOP LOOP UNTIL new_product <> search_product READFWD dyn.array.var FROM open.file ELSE PRINT "Record not found." new_product = EXTRACT(dyn.array.var,3) IF new_product = search_product THEN PRINT "Record is: ":dyn.array.var REPEAT END

112

Developing UniBasic Applications

Maintaining Files

The following example shows user input and output from the preceding program:

Screen Example
Enter product to display: ?trackball Record is: 01/17/1996p09:00AMpTrackballpDeluxe ModelpGrayp2373p5799p30 Record is: 01/18/1996p10:00AMpTrackballpEconomy ModelpWhitep2299p4499p30 Record is: 01/11/1996p12:00PMpTrackballpSuper Deluxe ModelpGrayp494p9899p70

Non-UniData Sequential Files
You can use the following types of commands to maintain data in non-UniData sequential files: • • Sequential File Commands – Specifically for manipulating non-UniData sequential files. UniData Hashed File Commands – You can use these after you make an entry for the sequential file in the UniData VOC file. For instructions about creating a VOC entry, see Using UniData.

Sequential File Commands
UniBasic provides commands to manipulate non-UniData sequential files, including files that contain data stored in binary format. These commands access the file via the operating system file name or place name and therefore do not use a VOC entry to locate the file. Access to different types of sequential files lets you modify print jobs, log files, and source code using a UniBasic program.

Developing UniBasic Applications

113

Chapter 4 - Maintaining Data in Files

UniBasic provides several sets of commands to handle sequential file operations. To open a sequential file, use either the OSOPEN or OPENSEQ command. After opening a file, you can read and write the entire file, read and write one record at a time, or read and write the file beginning at a specified byte location. The following table lists the commands that pertain to sequential read and write operations. Read/Write Starting at a Specified Byte Location OSBREAD OSBWRITE n/a

Read/Write Entire File OSREAD OSWRITE n/a

Read/Write One Record READSEQ WRITESEQ WRITESEQF WEOFSEQ

Commands for Reading/Writing Non-UniData Sequential Files To close a sequential file, use either the OSCLOSE or CLOSESEQ command. To delete a sequential file, use the OSDELETE command.

Note
Even though you can use any combination of sequential read and write commands, you should be careful to avoid writing data in unintended areas of the file. Informix recommends you become thoroughly familiar with them before you mix their use. For the syntax and use of these commands, see the UniBasic Commands Reference. In addition, if you have opened a named pipe, you cannot use the READSEQ command to read a record from it, and you cannot use WRITESEQ or WRITESEQF to write a record to it. You must use the OSBREAD and OSBWRITE commands.

114

Developing UniBasic Applications

Maintaining Files Warning The UniBasic OSDELETE command is intended for use on OS-type files (not UniData hashed files). we discourage this practice because UniData could. and DELETE) on nonUniData sequential files that have VOC entries. Use the sequential file commands listed earlier. However. insert characters in the file. If you execute the command against a recoverable hashed file. but other unpredictable problems could occur. WRITE. CLOSE. READ. or operating system commands. If the command is executed against a nonrecoverable hashed file. UniData could crash immediately or at the next RFS checkpoint. even upon opening it. UniData Hashed File Commands You can use hashed file commands (OPEN. Developing UniBasic Applications 115 . in some cases. UniData will not crash.

" CALL DISPLAY_MESSAGE(MESSAGE) STOP END 116 Developing UniBasic Applications . see the UniBasic Commands Reference. You must open a file in a UniBasic program before you can access the data in it. Generally.” It demonstrates opening a UniData hashed file. Commands That Open Files For the syntax and use of these commands. starting at the beginning of the file.Sample Program. Command OPEN Action Open a file.Maintaining Data in Files Opening Files UniBasic provides the following commands for opening files. Program Example OPEN_FILES: OPEN "CLIENTS" TO CLIENT_FILE ELSE MESSAGE = "The CLIENT file could not be opened. Open a sequential file. you store a pointer to the open file in a variable. you can open a default file by omitting the variable.Chapter 4 . Then you can execute file-level commands against this default file by again omitting the file variable. OPENSEQ OSOPEN Example The following program segment is taken from the sample program in “Appendix A . However. Open a sequential file that does not use CHAR(10) as the line delimiter.

Saving a Select List Select lists are available only during the current work session. Executing conditional tests. Developing UniBasic Applications 117 . Creating a Select List of Record IDs The record IDs of selected records are placed in a select list. the prompt changes to a greater than symbol (>).LIST in the UniData Commands Reference or the UniBasic CLEARSELECT command in the UniBasic Commands Reference. Then. a paragraph. UniBasic supports record selection by internal and external statements and commands. You must delete or deactivate the select list before retrieving IDs based on completely new criteria. execute the SELECT command followed by the name of the file. For information about deleting and deactivating select lists. any subsequent select statement acts against that list. or externally from ECL.Selecting Records Selecting Records Some ways you might determine which record(s) to retrieve include: • • • Prompting the user or a data stack for record ID(s) or other selection criteria. Performing calculations. UniData provides ten storage areas identified by their number: 0 through 9. or a paragraph that performs an ECL (UniQuery or UniData SQL) SELECT statement. If you do not specify a list number when you select records IDs. when you want to use the list again. You can save a select list to a file by using the UniBasic WRITELIST command. You can use multiple select lists to process data from several files simultaneously. see the ECL commands CLEARSELECT and SAVE. UniData stores them in list 0. After you create a select list.

The list can be made up of an entire index or can be limited to a particular alternate key value or values. For the syntax and use of UniQuery commands. see the UniBasic Commands Reference. Selecting Records within a UniBasic Program For the syntax and use of UniBasic commands. Note . Then run the program or paragraph using the select list.You must use the SETINDEX command to set the pointer before you can read records. Create a select list based on an alternate key index. see Using UniQuery. Command SELECT SELECTINDEX Action Collect a list of all @IDs from a specified file. SELECTINFO Determine if a select list is active.These SELECT statements offer the advantage of letting you use selection criteria. FORMLIST EXECUTE a UniQuery SELECT EXECUTE a UniData SQL SELECT Create a select list from a dynamic array.Maintaining Data in Files Internal Select You can select records within a UniBasic program using the following commands. For the syntax and use of UniData SQL SELECT. see the UniData SQL Commands Reference. Note . 118 Developing UniBasic Applications . Execute a UniData SQL or UniQuery SELECT command using the UniBasic EXECUTE or EXECUTESQL command to create a list of record IDs.Chapter 4 . External Select You can select records from the ECL prompt or from a UniData paragraph.

a UniQuery SELECT is executed from the ECL prompt. You can clear one or all select lists. any subsequent select statement acts against that list. Developing UniBasic Applications 119 . see the UniData Commands Reference. The ECL commands CLEARSELECT and SAVE. CLEARSELECT empties a record ID list created by a SELECT statement. You must delete or deactivate the active select list before retrieving IDs based on completely new criteria. For more information about these commands. The UniBasic program executed from this prompt uses the active select list. Screen Example :SELECT INVENTORY WITH QUANTITY > '999' >RUN BP OVERSTOCK_REPORT The following example UniData paragraph selects a stored select list. The > prompt indicates that a select list is active.Selecting Records Examples of External Select In the following example. and then it runs a UniBasic program using the selected records: Program Example PA SELECT INVENTORY3 RUN BP NEWITEMS_REPORT Clearing a Select List Once you create a select list.LIST also clear or deactivate select lists.

Getting Ready to Read Before you start reading records. see the previous section. you can use the UniBasic READNEXT command to assign the next record ID from an active select list to a variable. Set a pointer to an initial alternate key value in an alternate index with the SETINDEX command. see “Chapter 5 . write. and Deleting Data from Files This section describes how to read. Writing. which can result from multiple users updating files at the same time. Reading Record IDs from a Select List After you have selected record IDs for processing. Reading Data from Files Reminder You must understand the UniBasic record locking system to select the appropriate combination of commands to prevent data inconsistency.” 120 Developing UniBasic Applications .Chapter 4 .Maintaining Data in Files Reading.Using UniData Locks. you need to select records for processing. For more information. Reminder After you open a file and before you read data. For information about selecting records and creating select lists of record IDs. you might want to take one of the following steps: • • Make a record ID available to the program with the UniBasic READNEXT or READNEXTTUPLE command. and delete data from files.

If the record is available (no locks). Retains existing locks. sets a shared lock. Reads data from an attribute and assigns it to a variable regardless of lock status. sets a shared lock on the record. sets a shared lock on the record. READ Command MATREAD Action Assigns values in attributes of a record to corresponding elements of a dimensioned array regardless of lock status. If the record is available (no locks). Writing. Reads a record regardless of lock status and assigns its contents to a dynamic array. READ Commands MATREADL MATREADU READ READL READU READV READVL READVU READSEQ Developing UniBasic Applications 121 .Reading. Retains existing locks. If the record is available (unlocked or shared lock). Assigns the contents of the record to a dynamic array. and the type of lock (if any) you want to check for and set. Assigns the record’s contents to a dynamic array. Reads data from an attribute and assigns it to a variable. the type of variable you are reading into. If the record is available (no locks). sets an exclusive lock on the record. If the record is available (unlocked or shared lock). Assigns the attributes of the record to a dimensioned array. Reads data from an attribute and assigns it to a variable. If the record is available (unlocked or shared lock). Reads the next record from a non-UniData sequential file and assigns the data to a variable regardless of lock status. Retains existing locks. and Deleting Data from Files UniBasic supplies a number of commands for reading records so that the data in them can be manipulated in a UniBasic program. set an exclusive lock. sets an exclusive lock. You will want to use the proper command for the type of file from which you are reading. Assigns the contents of the record to a dimensioned array. The following table introduces the UniBasic commands that read records from files and data from records.

Using a list of record IDs. Use operating system commands instead. such as cp (for UNIX) or copy (for Windows NT or Windows 2000). directory files such as BP) could have unpredictable results. and assigns the record ID to the @ID variable. Retains existing locks. 122 Developing UniBasic Applications . READ Commands (continued) READT READNEXTTUPLE READFWD READBCK READFWDL READBCKL READFWDU READBCKU For syntax and instructions for coding read statements. Tip Using UniBasic commands to modify files and records containing binary data (for example. sets a shared lock. Retains existing locks. Retrieves one record ID from an index. Regardless of lock status. and assigns the record ID to the @ID variable. Retrieves one record ID from an index. Retrieves one record ID from an index. reads the next available record from a tape and assigns it to a variable. assigns the contents of the record to a dynamic array. Reads data from a sequential file starting at a specified byte location for a certain length of bytes. reads the next record to a variable regardless of lock status. If the record is available (unlocked or shared lock).Maintaining Data in Files READ Command OSREAD OSBREAD Action Reads an entire sequential file and assigns the contents to a variable. If the record is available (no locks). assigns the contents of the record to a dynamic array.Chapter 4 . see the UniBasic Commands Reference. and assigns the record ID to the @ID variable regardless of lock status. sets an exclusive lock. and assigns the data to a variable. assigns the contents of the record to a dynamic array.

"MT") CLIENT_NUMBER = ORDER.REC FROM ORDERS_FILE. and Deleting Data from Files Example The following program segment is taken from the sample program UPDATE_ORDER in “Appendix A ."D4/") ORDER_TIME = OCONV(ORDER.REC<3> ADDRESS = '' Developing UniBasic Applications 123 . Program Example DISPLAY_DATA: * Display the current information in the desired record.” The READU command reads a record in the ORDERS file (in the demo database). Writing. RECORD_FOUND = 1 ORDER_DATE = OCONV(ORDER.REC<1>.ORDER_NUMBER THEN * Read with a lock so that no one else can modify it at the same time. This is * determined by the number the user entered (ORDER_NUMBER).Sample Program.REC<2>. READU ORDER.Reading. converting attributes in preparation for displaying them on the screen.

but retains locks if present. Releases any record or file lock this process set. sets an exclusive lock. you must precede them with the READU command to prevent data inconsistency that can result from multiple users updating files at the same time. Writes an expression to an attribute of a data record regardless of lock status.Maintaining Data in Files Writing Data to Files Reminder Write statements execute regardless of lock status. For more information. Writes elements of a dimensioned array to corresponding attributes of a record. see “Chapter 5 . For this reason. Writes elements of a dimensioned array to corresponding attributes of a record.Using UniData Locks. Writes an expression to a record regardless of lock status. WRITE Command MATWRITE MATWRITEL Action Writes elements of a dimensioned array to corresponding attributes of a record regardless of lock status. sets a shared lock on the record.Chapter 4 . Writes an expression to a record regardless of lock status. If the record is available (no locks). including dynamic and dimensioned arrays. Writes an expression to an attribute of a data record. If the record is available (unlocked or shared lock).” UniBasic supplies a number of commands for writing records into UniData hashed files from UniBasic variables. You will want to use the proper command for the type of file you are writing to and the type of variable you are writing from. WRITE Commands MATWRITEU WRITE WRITEU WRITEV WRITEVU 124 Developing UniBasic Applications . Use the following table to decide which UniBasic command to use to write to a file.

Writes a variable as a record on a sequential file from a current record pointer position. Writes a variable as a record on a sequential file from a current record pointer position. directory files. such as BP) could have unpredictable results.Reading. such as cp (for UNIX) or copy (for Windows NT or Windows 2000). WRITE Commands (continued) WRITET For syntax and instructions for coding write statements. Writes a variable starting at a specified byte location to a sequential file. Developing UniBasic Applications 125 . see the UniBasic Commands Reference. Writes the value of an expression onto a tape. Writing. and Deleting Data from Files WRITE Command OSWRITE OSBWRITE WRITESEQ WRITESEQF Action Writes the contents of a variable to a sequential file. Use operating system commands instead. Forces UniData to immediately write the data to the disk. Tip Using UniBasic commands to modify files and records containing binary data (for example.

12 THEN LOCATE ORDER_NUMBER IN ORDER_LINE<1> SETTING POSITION THEN DEL ORDER_LINE<1. CLIENT_NUMBER. UPDATE_ORDER in “Appendix A .CLIENT_NUMBER RETURN 126 Developing UniBasic Applications .Chapter 4 .Sample Program.” The WRITEV command writes an attribute to the ORDERS file (in the demo database) after an order number (one value in a multivalued attribute) has been deleted from it.Maintaining Data in Files Example The following program segment is taken from the sample program. Program Example DELETE_RECORD: * (Assuming the order #'s are on line 12) READVU ORDER_LINE FROM CLIENT_FILE. ORDER_NUMBER RELEASE CLIENT_FILE.CLIENT_NUMBER. 12 END * DELETE ORDERS_FILE.POSITION> END WRITEV ORDER_LINE ON CLIENT_FILE.

Command DELETE DELETEU OSDELETE Action Deletes a record from a UniData file regardless of lock status. If the command is executed against a nonrecoverable hashed file. Commands that Close Files Warning The UniBasic OSDELETE command is intended for use on OS-type files (not on UniData hashed files). Writing. If the command is executed against a recoverable hashed file. deletes it. but other unpredictable problems could occur. If the record is available. see the UniBasic Commands Reference. The only way to prevent data inconsistency that can result from multiple users updating files at the same time is to precede DELETE with READU. For the syntax and use of these commands. and Deleting Data from Files Deleting Data from Files Reminder DELETE executes regardless of lock status.Reading. Checks for locks. Deletes a sequential file. For more information. UniData will not crash. see “Chapter 5 . UniData could crash immediately or at the next RFS checkpoint. Developing UniBasic Applications 127 .” The following table provides a brief introduction to the UniBasic commands that delete data from files and/or records. Releases all locks set by this process.Using UniData Locks.

POSITION> END WRITEV ORDER_LINE ON CLIENT_FILE.12 THEN LOCATE ORDER_NUMBER IN ORDER_LINE<1> SETTING POSITION THEN DEL ORDER_LINE<1. ORDER_NUMBER RELEASE CLIENT_FILE.Chapter 4 . CLIENT_NUMBER.CLIENT_NUMBER.CLIENT_NUMBER RETURN 128 Developing UniBasic Applications . 12 END * DELETE ORDERS_FILE.Maintaining Data in Files Program Example DELETE_RECORD: * (Assuming the order #'s are on line 12) READVU ORDER_LINE FROM CLIENT_FILE.

Closes a sequential file. see the UniBasic Commands Reference. Developing UniBasic Applications 129 . Commands that Close Files For the syntax of these commands and instructions for coding close statements. Releases locks and closes a sequential file.Closing Files Closing Files The following table introduces the commands that close files. Command CLOSE CLOSESEQ OSCLOSE Action Releases locks and closes a data or dictionary file.

The second line prints the value in that attribute. accessing the record with @ID 912.ret END The following output is obtained by running the preceding program: Screen Example Record retrieved: 12:30PM 130 Developing UniBasic Applications .Chapter 4 ."TORDERS.2") PRINT "Record retrieved: ":record. You can also use these functions to determine if a particular record or attribute exists or contains an empty string.. multivalued. Program Example record.V.Maintaining Data in Files Accessing Data in Unopened Files With the ICONV T and OCONV T functions you can access singlevalued. The first line of the following program segment reads the demonstration database file ORDERS. and retrieving the second attribute.ret = OCONV("912". OCONV T also converts the internal date to external display format. and multisubvalued attributes in a file that you have not opened.

You can also use locks to reserve computer resources. This chapter introduces UniBasic locks and the commands that comprise the UniBasic locking system. you can provide this protection.UniBasic Transaction Processing.Using UniData Locks In a multiuser environment. By observing the UniBasic locking conventions consistently in all of your applications. For more information about ensuring database consistency.” Developing UniBasic Applications 131 . see “Chapter 9 . you must be able to prevent more that one user from updating records simultaneously.Chapter 5 .

Using UniData Locks In This Chapter This chapter contains the following sections: • • • • • • “Understanding the UniData Locking System” “Locking Commands” “What Commands Do with Locks” “When to Use Locking Commands” “Programming Problems” “Locking Example” 132 Developing UniBasic Applications .Chapter 5 .

• • Are accessed and modified by any WRITE or DELETE command. Shared lock – Used for read-only operations. Types of UniData Locks The UniData lock types are: • • Exclusive lock – Checks for and sets locks before updating data. Exclusive Locks (U) Records locked with exclusive (U) locks: • • Cannot be accessed by any READ U or L command. How UniData Locks Work Unlike physical locks that prevent access. UniBasic locks merely inform others attempting access that the “locked” entity is in use.Understanding the UniData Locking System Understanding the UniData Locking System In a multiuser system. although ignored. Note The original lock. Are accessed by commands that do not check for locks and that are issued from other processes. Are released by the commands WRITE and DELETE issued from the same process. while not explicitly preventing access. Prevents other users (who also use locking commands) from writing to the record while it is being read. is retained. Developing UniBasic Applications 133 . UniBasic locks are advisory only. record and file locks prevent more than one user from accessing the same record at the same time. Imagine a physical lock as the deadbolt on a hotel room door and an advisory lock as a “Do Not Disturb” sign.

For this reason. Are accessed by READ L commands. Cannot be locked by RECORDLOCKU from another process. Shared Locks (L) Records locked with shared (L) locks: • • Cannot be accessed or locked by READ U commands. Note The original lock is retained. Note Even though these commands update regardless of lock status. • • Are accessed by READ commands that do not check for locks.Chapter 5 .Using UniData Locks • Cannot be locked by RECORDLOCKU or RECORDLOCKL issued from another process. Are accessed and changed by any WRITE or DELETE command. they retain the original lock. 134 Developing UniBasic Applications . these commands must be preceded by READU or another command that issues locks. Tip WRITE and DELETE commands execute regardless of lock status. • • Are released by the commands WRITE or DELETE issued from the same process. to prevent data inconsistency.

but does not send a signal to the terminal. Points to Remember about Locks Keep in mind the following points about locks: • • Anyone can update or delete locked files and records with any WRITE or DELETE command. if present. UniBasic does one of the following (in order of preference): 1. Executes the LOCKED clause of the UniBasic command.LOCKED. only you. Beeps periodically while waiting if the ECL command DEFAULT. can release it. Waits for the record to be unlocked. 3. If you set a lock.ACTION BELL [interval] is set. • Note For more information about using transactions to ensure database consistency. or someone signed on with root privileges on UniData for UNIX or Administrator privileges on UniData for Windows NT or Windows 2000. TRANSACTION COMMIT and TRANSACTION ABORT releases all locks your process has set within the transaction.” Developing UniBasic Applications 135 .Understanding the UniData Locking System When UniBasic Finds a Lock When a locking command encounters a locked file or record. 2. see “Chapter 9 UniBasic Transaction Processing.

Unlock the resource with the UNLOCK command. 136 Developing UniBasic Applications . UDT. use the CLEAR. Use the FILEUNLOCK command to unlock the file. see the UDT.OPTIONS 78 addresses two situations in which UniBasic locking is incompatible with Pick®-style locking.LOCKS commands. all programs that update the database must check for locks. For more information about UDT.OPTIONS.OPTIONS Setting UDT. and delete commands that check and set locks. To maintain data consistency. • • • For more information about ECL commands. see the UniData Commands Reference.OPTIONS 35 on prevents locking a record in a called subroutine that was locked in the calling program. indicating the type of locks they set. operating as if no lock is set.LOCKS and SUPERCLEAR. Locking Resources – Use the LOCK command to set an advisory lock that reserves a computer resource (such as a printer or tape drive) for use by a particular program. All other commands ignore locks.OPTIONS Commands Reference. Keep the following points in mind when writing UniBasic programs: • Locking Records – UniBasic provides distinct read.Using UniData Locks Locking Commands Reminder UniBasic locks are advisory only. These commands all have an appended U or L in the command name. Unlocking – You can use the ECL command SUPERRELEASE to release record and file locks. Locking Files – You can set an advisory lock on an entire file by issuing a FILELOCK against it. To unlock resources. UDT.Chapter 5 . write. A chart of locking commands is provided in “What Commands Do with Locks” later in this chapter.

QUEUE also provides this information (for more information. Developing UniBasic Applications 137 . see GETQUEUE in the UniBasic Commands Reference). The ECL command LIST.Locking Commands Checking Lock Status To learn about a the lock status of a record. The GETREADU function returns a dynamic array containing detailed information about all records that have been locked by any UniBasic or ECL command.READU also provides this same information (for more information. The ECL command LIST. see GETREADU in the UniBasic Commands Reference). The GETQUEUE function returns a dynamic array that contains information about all records currently locked and waiting to be released. use the UniBasic RECORDLOCKED function. you can use the STATUS function to obtain the user number of the user who set the lock. After calling RECORDLOCKED.

Note that some commands execute regardless of lock status.Using UniData Locks What Commands Do with Locks The following table identifies how the previously discussed commands react to UniBasic locks. release locks and execute (Releases column). regardless of lock status. Still others delay file activity until locks are released (Sets Exclusive and Sets Shared columns). Command READ READU READV READVU MATREAD MATREADU READBCKU READFWDU RECORDLOCKU READL READVL MATREADL READBCKL Ignores X Sets Exclusive Sets Shared Releases X X X X X X X X X X X X What Commands Do with Locks 138 Developing UniBasic Applications . Others.Chapter 5 . but leave locks in place (Ignores column). Reminder Include the LOCKED clause in command statements to tell UniData what to do when it encounters a lock.

What Commands Do with Locks Command READFWDL RECORDLOCKL WRITE WRITEU WRITEVU MATWRITE MATWRITEU DELETE DELETEU Ignores Sets Exclusive Sets Shared X X Releases X X X X X X X What Commands Do with Locks (continued) Developing UniBasic Applications 139 .

and file-locking commands. Updating records (must be preceded by READU to ensure data consistency). allowing update while reading. WRITEU WRITEVU MATWRITEU Record Locking Guidelines 140 Developing UniBasic Applications . keeping ownership of lock (other programs must check for locks). Write. Updating.Chapter 5 . Reading and securing information for update (other programs must check for locks). do not release locks. FILELOCK READU RECORDLOCKU READVU MATREADU Write. release locks. READ WRITE WRITEV MATWRITE Read and set exclusive lock. Attributes of Dynamic Arrays READV When to Use Action Files Dynamic Arrays Dimensioned Arrays MATREAD Retrieving information. Read without checking locks.Using UniData Locks When to Use Locking Commands Follow the guidelines in this table when selecting record.

Release locks you placed.When to Use Locking Commands When to Use Action Files Dynamic Arrays Attributes of Dynamic Arrays READVL Dimensioned Arrays MATREADL Retrieving information. but keeping others from updating (using READU or WRITEU) while you are reading (other programs must check for locks). FILEUNLOCK RELEASE RELEASE RELEASE Record Locking Guidelines (continued) Developing UniBasic Applications 141 . Read and lock for read-only. READL Release locks.

not while the records are locked. Dirty reads – A program reads a record that is in the process of being modified by another. To do so. and the second read executes after the record has been updated. Minimizing Problems Using record locking consistently. you can eliminate the programming problems listed earlier while reducing bottlenecks and deadlocks. and provides suggestions on how to minimize the problems. This results when the first read executes while the record is in the process of being updated. Causes A multiuser environment creates opportunities for two programs to access the same record at the same time. For example.Chapter 5 . the protocol might let programs lock record B only after locking record A (to avoid deadlocks).Using UniData Locks Programming Problems This section discusses how UniBasic programming problems may arise. Deadlocks – Occur when two or more programs are waiting for each other to release records with no chance of either being released. use the following guidelines: • • • • Always check for locks and always lock records before writing. • • Bottlenecks – Result when one program retains a lock on a file or record for an inordinate amount of time. Impose a protocol on the order data items can be updated. 142 Developing UniBasic Applications . causing other programs to wait. Request user input before locking records. Minimize the amount of time records are locked. Unrepeatable reads – A program reads the same record twice. resulting in the following types of problems: • Inconsistent data caused by the following: • • • Lost updates – The updates from one program overlay those of another. obtaining two different values.

For more information about UniData transactions. see “Chapter 9 .Programming Problems Note Deadlocks cause transaction processing to abort one of the deadlocked transactions.UniBasic Transaction Processing.” Developing UniBasic Applications 143 .

144 Developing UniBasic Applications . records are released as soon as they are written to the file. READU ORDER.Sample Program. In almost all cases.Main Logic ----------------------------GOSUB INITIALIZE LOOP GOSUB DISPLAY_SCREEN GOSUB GET_ORDER_NUMBER UNTIL ORDER_NUMBER[1.1] = 'Q' GOSUB DISPLAY_DATA IF RECORD_FOUND THEN GOSUB GET_RECORD_COMMAND RELEASE REPEAT GOSUB EXIT The following program segment shows the READU command that sets an exclusive lock on the record that the user has selected for update: Program Example DISPLAY_DATA: * Display the current information in the desired record. Program Example *-------------. This is * determined by the number the user entered (ORDER_NUMBER). Notice that RELEASE is executed as the last step in the LOOP.REC FROM ORDERS_FILE.Chapter 5 . some error conditions could cause records to remain locked when control is returned to the LOOP.ORDER_NUMBER THEN * Read with a lock so that no one else can modify it at the same time. drives the program by calling subroutines to perform the main tasks.Using UniData Locks Locking Example The following program segments are portions of the sample program in “Appendix A . However.” The main routine (Main Logic).

WRITE CLIENT.REC ON CLIENT_FILE.REC<1>. the WRITE command updates the previous record read and releases the exclusive lock (WRITE always releases locks that were set by the same user process): Program Example WRITE_RECORD: .REC<3> "R#5" In the next program segment.Locking Example ORDER_DATE = OCONV(ORDER. ."D4/") ORDER_TIME = OCONV(ORDER.CLIENT_NUMBER WRITE ORDER."MT") CLIENT_NUMBER = ORDER.ORDER_NUMBER Developing UniBasic Applications 145 . .REC ON ORDERS_FILE.REC<2>.

Chapter 5 .Using UniData Locks 146 Developing UniBasic Applications .

Developing UniBasic Applications 147 . you select from a number of similar commands to perform a specific task.Chapter 6 .Working with Data in Programs In most cases. This chapter provides the information you need to select the correct command or function to manipulate data in UniBasic programs.

Working with Data in Programs In This Chapter You have read data into the program from files or accepted input from the user. You are ready to manipulate the data before writing it to a file or report.Chapter 6 . This chapter introduces in the following sections the concepts and commands you will use to do this manipulation: • • • • • “UniData Arrays” “Inquiring about Data” “Performing Numeric Operations” “Formatting and Converting Data” “UniBasic Multibyte Support” 148 Developing UniBasic Applications .

The same delimiters are used in dynamic arrays (see “Dynamic Array Delimiters”). The following two types of UniBasic arrays are introduced in “Chapter 1 . the size of a dynamic array is determined by the data contained in it. Dynamic Arrays The UniData file structure uses reserved delimiters to partition data items that are stored sequentially.” • • Dynamic arrays – Separate each attribute. Developing UniBasic Applications 149 . access to data in a dimensioned array is rapid but less flexible. Advantages of Using Dynamic Arrays Dynamic arrays have the following advantages over dimensioned arrays: • • • • Need not be defined before you use them. they are flexible.UniData Arrays UniData Arrays You generally use an array to store data that you read into a UniBasic program from UniData hashed files. and subvalue of a record by delimiters. Require less memory than dimensioned arrays. Dimensioned arrays – Store data in designated cells of a fixed-sized matrix. allowing easy modification. Multivalued and multi-subvalued attributes can be loaded into an array in the same way that you load an individual value into a variable. Can be assigned quickly. As the name implies. Can be three-dimensional.Introduction to UniBasic. value.

replace. @FM @VM @SM @TM Dynamic Array Delimiters Note You must use the @variables to refer to delimiters within UniBasic programs. The character used to display the delimiter symbols depends on your terminal emulation. The symbols that display for these delimiters could differ on your system. 2. and delete data in the array: 1. Performing a LOCATE or FIND on unsorted data produces unpredictable results. you might use the following procedure to add.Working with Data in Programs Dynamic Array Delimiters UniData uses the same delimiters to separate elements in a dynamic array as those used in a UniData hashed file. 150 Developing UniBasic Applications . The following table illustrates common symbols used to represent delimiters.Chapter 6 . Execute the LOCATE or FIND command to determine the location of one of the following: • Where new data should be inserted in a multivalued attribute. not the delimiter symbols. UniBasic evaluates the delimiter symbols and writes the correct ASCII values when you write a record.” After data is loaded into the sorted array. Make sure that the data in the array is sorted. insert. Delimiter Symbol (unprintable) ~ } | { Meaning Record mark Attribute mark Value mark Subvalue mark Text mark @variable @RM @AM. Maintaining Dynamic Arrays The commands you use to load data into an array and write to a file from an array are introduced in “Chapter 4 .Maintaining Data in Files.

Use the EXTRACT command (or < >) to extract an attribute (value. Sets a pointer to the location where an array element should be inserted. Dynamic Array Commands EXTRACT. Copies an array element (attribute. value. multivalue. delete. or replace an array element: • • • INSERT. 3. Deletes an array element. < > REPLACE. multivalue. multivalue. or multi-subvalue) from the array. INS DEL. DELETE Developing UniBasic Applications 151 . Command/ Function FIND. Use one of the following commands as appropriate to insert.UniData Arrays • Of a string that you intend to update or delete within a multivalued attribute. or multisubvalue) into a variable. update. DELETE (the function) REPLACE (or < >) Summary of Dynamic Array Commands Use the following commands and functions to create and maintain data in a dynamic array. 4. Inserts or replaces an array element (attribute. LOCATE Action Determines the location of an existing array element. value. < > DEL. or multi-subvalue) from a variable.

matrix element. LOCATE UniBasic provides two commands that return the location of a string within a dynamic array: FIND and LOCATE. or subvalue. Can find the nth occurrence of a string. and subvalue position. Expression searched for must be numeric or string. LOCATE Returns attribute. Locates an element or part of an element in an array. SETTING returns the position after the last value if the string is not found. Can limit the search to a specific attribute. Assumes the records are sorted and justified.Chapter 6 . see the UniBasic Commands Reference manual. Expression searched for could be a variable. The following table contrasts the two commands. Can begin the search at a specific attribute. 152 Developing UniBasic Applications . or subvalue. or a literal string. Searches the entire array. value. Must match the entire element in an array at the level specified. value. SETTING returns 0 if the string is not located.Working with Data in Programs FIND vs. LOCATE For the syntax and use of these commands. FIND Returns attribute position. Assumes the records are sorted and justified. function. value. FIND vs.

Access time is not affected by the size of the array. all leftover data is placed in the zero element. The array must be declared in your UniBasic program before you can use it. Then..CLIENT_NUMBER. Can contain dynamic arrays. When you read data in from a UniData hashed file. That order is deleted and the attribute is written back to the file. Advantages of Using Dimensioned Arrays Dimensioned arrays have the following advantages over dynamic arrays: • • • Access is faster. Developing UniBasic Applications 153 . Program Example DELETE_RECORD: .UniData Arrays Example The following example is taken from the sample program UPDATE_ORDER in “Appendix A Sample Program. even if more than one attribute is left over.” In this example. CLIENT_NUMBER.. the user has entered a record to be deleted. The desired attribute (containing the order line) is read from the CLIENT file and placed in a dynamic array (ORDER_LINE). If your array is not large enough to contain all the data read in. the delimited data is placed in the matrix elements in the order they appear in the file. (Assuming the order #'s are on line 12) READVU ORDER_LINE FROM CLIENT_FILE. the LOCATE command is used to determine the position of the order in the array.POSITION> END WRITEV ORDER_LINE ON CLIENT_FILE.12 THEN LOCATE ORDER_NUMBER IN ORDER_LINE<1> SETTING POSITION THEN DEL ORDER_LINE<1. 12 END * Dimensioned Arrays A dimensioned array stores data in the elements of a fixed-size matrix.

3. or MATREADU command to place data in the array from a record. MATWRITEL. 2. Use the MATBUILD command to convert a dimensioned array to a dynamic array. Use the MATPARSE command to place data in the array from a dynamic array or string. Command/ Function DIM DIMENSION INMAT MAT Action Creates a dimensioned array.Working with Data in Programs Maintaining Dimensioned Arrays Perform the following steps to create and use a dimensioned array: 1. Returns the number of elements or the dimension of the array. Assigns a value to all elements of a dimensioned array. Use the DIM or DIMENSION command to create the array and assign a static dimension. or MATWRITEU command to write array elements to a record. Manipulate data in the array: • • • • Use the MATREAD. Also returns the status of some commands. Dimensioned Array Commands 154 Developing UniBasic Applications . Required before data can be loaded into the array. or copies one array to another. Summary of Dimensioned Array Commands Use the following commands and functions to create and maintain data in a dimensioned array. Use the MATWRITE. X1 = var) to update elements in the dimensioned array. Use the MAT command to assign a single value to all elements of the array or to copy one dimensioned array to another. 4. Use a statement (for example. MATREADL.Chapter 6 .

or Chinese) ASCII code. which is translated into a specific language-dependent (such as English. this unknown value is represented by @NULL. Distributes elements in a delimited string or dynamic array to consecutive elements of a dimensioned array. Developing UniBasic Applications 155 . German.z)=var Action Generates a dynamic array from a dimensioned array.UniData Arrays Command/ Function MATBUILD MATPARSE dim. Location – Functions that return the positions of strings or attributes in the data.y. Dimensioned Array Commands (continued) For the syntax and use of these commands and functions. represented by “” is no longer considered to be null in UniData. Two functions test for the null value: ISNV and ISNVS. Extraction – Functions that return values found within the string or array. Type This section describes functions that qualify the data. Extracts a value from an element of a dimensioned array.array(x. as opposed to an empty string. The empty string. see the UniBasic Commands Reference. Inquiring about Data A number of UniBasic functions provide information about a string or array without modifying the original data. In UniBasic programs. Testing for the Null Value The null value is defined within UniData as an unknown value. They fall into three categories: • • • Type – Functions that qualify the data (such as alpha or numeric and length).

NUMS LEN MAXIMUM MINIMUM COUNTS COUNT DCOUNT ISNV/ISNVS Action Determines whether a string is made up exclusively of alphabetic characters. Tests for the null value (the unknown value. Determines the largest numeric element found in an array. see theUniBasic Commands Reference. Functions That Inquire about Data Type For the syntax and use of these functions. Determines the number of times a substring appears within one or more elements of an array. Determines the number of times a substring appears within a string or all elements within an array.Chapter 6 . Determines the length of a string. Determines whether a value is numeric. not empty string).Working with Data in Programs Testing for Other Data Types The following functions provide information about type of data. Determines the number of delimited substrings in a string. Determines the smallest numeric element in an array. 156 Developing UniBasic Applications . Function ALPHA NUM.

For an introduction to FIELD. FIND LOCATE FINDSTR INDEX Determines the position of a string in a dynamic array element. Determines the position of a string in a dynamic array. see the UniBasic Commands Reference. Functions That Extract Without Modifying Developing UniBasic Applications 157 .UniData Arrays Location The following functions return the location of substrings in a string or array. Note . Functions That Inquire about Location For the syntax and use of these functions. see “Extraction” in this chapter. user can specify occurrence. Function COL1 Action Returns the column position before the string located by the FIELD function. Function [] Action Returns a specified number of characters beginning at a specified location. Determines the starting position of a substring within a string.For an introduction to FIELD. Note . see “Extraction” following this table. Extraction The following functions return values found in a string or array without modifying the original data. COL2 Determines the column position after the string located by the FIELD function.

see theUniBasic Commands Reference. Returns data from an attribute. Returns one or more strings separated by a specified delimiter. EXTRACT <> FIELD OCONV/S G OCONV/S L OCONV/S R OCONV/S P OCONV/S MCA OCONV/S MC/A OCONV/S MCN OCONV/S MC/N OCONV/S MCB OCONV/S MC/B Functions That Extract Without Modifying (continued) For the syntax and use of these functions. value. Extracts all alphabetic characters. Returns data values that fall within specified ranges. Extracts nonnumeric characters.Working with Data in Programs Function OCONV/S T REMOVE Action Returns a contiguous string of a specified length starting at a specified location. Returns data values that match a specified pattern. Successively copies each element of a dynamic array to a variable. 158 Developing UniBasic Applications . Returns a string if it is of a specified length or falls within the specified range of lengths. Treats a string as an array with fields delimited by any specified ASCII character. Extracts all numeric characters (0-9).Chapter 6 . Returns a substring or group of substrings. Maintains a pointer to the location in the array of the last element copied. Extracts all nonalphabetic characters. Extracts characters that are neither alphabetic nor numeric. or subvalue in a dynamic array. Extracts all alphabetic and numeric values.

Operator + + * / ** or ^ : Action Unary plus (same as multiplying by +1). Addition. Unary minus (use to change a value to negative: var = -var). Subtraction.Performing Numeric Operations Performing Numeric Operations You can perform numeric operations in UniBasic with the two tools. Multiplication. Division. For example. the following statement multiplies the value of COST by the value of QUANTITY and stores the result in the variable PRICE: PRICE = COST * QUANTITY The following table lists valid arithmetic and concatenation operators. Exponentiation. Arithmetic Operators Developing UniBasic Applications 159 . Concatenation. which are described in the following sections: • • “Arithmetic Operators” “Mathematic Functions” Arithmetic Operators Arithmetic operators compute values.

When the results are converted to string format for print or display. as in var *= var. LINES += 1 is more efficient than LINES=LINES+1. If you use more than 14 digits. -= *= /= := Combined Arithmetic and Concatenation Operators Points to Remember Keep in mind the following points when you write UniBasic commands that perform calculations: • Floating point – When you execute an arithmetic operation. LINES –= 1 is more efficient than LINES=LINES-1. UniData invokes the appropriate host operating system command. Use the ECL command FLOAT.Chapter 6 . Decrements the value of a variable. as in var := var.PRECISION to control when and how rounding is applied. accuracy is not • 160 Developing UniBasic Applications . Significance – UniData supports up to 14 digits of significance (although this significance can vary across hardware lines). as in var /= var. the rounding that is automatically applied can produce unexpected results. Concatenates the value to the left of the operator by the value to the right of the operator. Multiplies the value to the left of the operator by the value to the right of the operator. Divides the value to the left of the operator by the value to the right of the operator. Operator += Action Increments the value of a variable.Working with Data in Programs You can combine arithmetic and concatenation operators to perform special functions as the following table shows. which performs the operation in floating point.

Use the UniBasic PRECISION command to set significance for a work session. you can set UDT. Arithmetic Operations on Arrays When you execute arithmetic operations on dynamic arrays. The trim prevents a runtime error.OPTIONS Before you execute an arithmetic operation. null is converted to 0 for arithmetic calculations.Performing Numeric Operations guaranteed. Reminder The null value is defined within UniData as an unknown value. Apply an operation to two arrays (for example. Results of the same calculations executed on string and numeric data occasionally differ.OPTIONS Commands Reference.OPTIONS 10 on to trim blank spaces around a numeric value. UDT. 1 is used to avoid a system error. Null value – The result of calculations on data containing the null value is the null value. as opposed to an empty string. when UniData encounters the null value as a divisor.OPTIONS. • • Data type – Be aware of data type when you execute arithmetic calculations. The default is 4. Apply the operation to all elements in the array. For more information about UDT. you can apply them in one of the three following ways: • • • Apply the operation to just the first element in the array. However. Generally. see the UDT. multiply one array by another). Developing UniBasic Applications 161 .

include the REUSE command. 4000y8000y12000 162 Developing UniBasic Applications . causing the arithmetic operation to be applied to each element in the array (y represents the value mark in this display). The REUSE command is used to produce the second result. 4000y0y0 2. the program segment: X = 1:@VM:2:@VM:3 Y = X/100 PRINT Y 0. ":VCOST In the following execution of this program.Working with Data in Programs Applying the Operation to the First Element in the Array Performing an arithmetic operation on an array applies the operation to just the first element of the array.01y2y3 (where y represents prints the value mark). ":VCOST VCOST = VIEWERS*REUSE(COST) PRINT "2. Applying the Operation to All Elements in the Array To apply the operation to all elements. notice that the first result reflects application of the arithmetic operation (multiplication) is applied to only the first element of the array. as in the following sample program: Program Example VIEWERS = 100:@VM:200:@VM:300 COST = 40 VCOST = VIEWERS*COST PRINT "1.Chapter 6 . Screen Example :RUN BP arith 1. For example.

elements are filled with 1. Program Example VIEWERS = 100:@VM:200:@VM:300 COST = 40:@VM:1 VCOST = VIEWERS*COST However. if you apply the REUSE function. for addition. depending on the operation performed: for division. The following version of the program produces a result of 4000:@VM:200:@VM:300: Program Example VIEWERS = 100:@VM:200:@VM:3 COST = 40:@VM:1 VCOST = VIEWERS*REUSE(COST) Developing UniBasic Applications 163 . elements are filled with 0. the last element in the shorter array is used to complete the operation on the remaining elements of the longer array. the first two elements are multiplied. which results in VCOST = 4000:@VM:200:@VM. and then the second two elements are multiplied. The remaining elements are filled with 1 or 0. and multiplication. The third element is filled with 1. In the following example program. subtraction.Performing Numeric Operations Applying Operations to Two Dynamic Arrays When an arithmetic operation is applied to dynamic arrays of different length. the operation is applied to only the number of element in the shortest array.

Returns the arc sine (inverse sine) in degrees.Working with Data in Programs Mathematic Functions Numeric functions process variables. Returns the base number raised to the power specified.Chapter 6 . Mathematic Functions 164 Developing UniBasic Applications . Return the square root of a positive numeric expression. INT truncates. Returns the cosine of a number. constants. tables. Totals the numeric values in an attribute according to dynamic array delimiters. Returns the arc tangent (inverse tangent) in degrees. Raises a number to the power specified. The following table lists UniBasic mathematical functions. Returns the integer value of a number. it does not round the value. starting position. Returns the sine of a number. or data in a variety of ways. Returns the remainder of the division operation using specified numbers. Returns the arc cosine (inverse cosine) in degrees. Function ABS ACOS ASIN ATAN COS EXP INT LN MOD PWR RND SIN SQRT SUM Action Returns the positive value of a number. and level for which to calculate the total. LN is the inverse of EXP. You can enter a range. Returns the natural base logarithm. Returns a random integer from 0 to a specified number 1. EXP is the inverse of LN.

Mathematic Functions (continued) For the syntax and use of these functions. Reminder Numeric functions on data containing the null value result in the null value.Performing Numeric Operations Function TAN Action Returns the tangent of numeric expression. Developing UniBasic Applications 165 . see the UniBasic Commands Reference.

and hexadecimal. and round numbers. • Before getting into the types of data. Numbers – Justify and format using special characters for dollars and other numeric display formats. 166 Developing UniBasic Applications . decimal. or an invalid conversion code is used. Modify. OCONVS performs on an array the same function that OCONV performs on a variable. You can also convert from ASCII character to ASCII code (decimal value). among numbering systems. Strings and dynamic arrays – Justify and format using special characters. spell out month or day of the week. with UDT. You will see the different options for these commands listed throughout the following sections. and convert the following types of data: • • • Characters – Convert between EBCDIC and ASCII for compatibility with other computer systems. Note When invalid data is submitted to ICONV or OCONV. scale. octal. ICONV primarily converts to internal format for date and number storage. In BASICTYPE P. Format dates and time for display using special characters. binary. and sometimes both execute the same conversion. Dates and times – Convert between external display format and UniData internal format. Convert among ASCII character.OPTIONS 56 on. justify. and OCONV primarily converts to external display format. you should understand the ICONV and OCONV functions. Yet both perform many other conversions. When OCONVS is available.Working with Data in Programs Formatting and Converting Data UniData provides functions to format.Chapter 6 . OCONV returns an empty string if the input value or conversion code is invalid. these functions return the original value. and others. modify. ICONV and OCONV: The All-Purpose Functions The UniBasic functions ICONV and OCONV perform many conversions between internal and display format. the functions are represented in the tables that follow as OCONV/S.

123 Executing OCONV "12.31" Input or output [I/O]? : Developing UniBasic Applications 167 .y_conv_code) END PRINT \"\ : answer : \"\ WHILE 1 DO REPEAT The following screen example shows how you can test the masked extended (MD) option for OCONV by running the previous program: Screen Example Input or output [I/O]?O Conversion code? ME2. "MCU")= "O" THEN PRINT "Executing OCONV" answer = OCONV(z_argument.Formatting and Converting Data You can use the following program example to test the many conversion code options available for ICONV and OCONV: Program Example PROMPT "" LOOP PRINT "Input or output [I/O]?" : INPUT i_or_o IF i_or_o = "" THEN STOP PRINT "Conversion code? " : INPUT y_conv_code PRINT "Argument? " : INPUT z_argument IF OCONV(i_or_o.y_conv_code) END ELSE answer = ICONV(z_argument.1 Argument? 123.

EBCDIC CHAR SEQ Strings and Dynamic Arrays Several formatting functions are available for manipulating data in strings or dynamic arrays. Converts from ASCII character to ASCII code (decimal). starting at the position indicated.expr from EBCDIC to the corresponding ASCII values. Converts the string expression str. or other number formats. Converts from ASCII code (decimal value) to ASCII character. Concatenates strings.Chapter 6 .Working with Data in Programs Character Format Conversion Use the character conversion functions described in the following table to convert data to and from formats for other computer systems. This is the inverse of the EBCDIC function. Replaces a string.expr from ASCII to the corresponding EBCDIC values. dates. Converting Character Formats For the syntax and use of these functions. see the UniBasic Commands Reference. Function FMTS [] : Action Formats a multivalued attribute for output. Function ASCII Action Converts the string expression str. Formatting and Modifying Strings 168 Developing UniBasic Applications . This is the inverse of the ASCII function. adding special characters for dollars.

Converts to initial caps style. Converts all occurrences of substring x to substring y. Formatting and Modifying Strings (continued) For the syntax and use of these functions. Replaces selected characters in a string. Converts to SOUNDEX phonetic code. see the UniBasic Commands Reference. The first character in each word is uppercase. Removes all trailing spaces from a string.Formatting and Converting Data Function DOWNCASE ICONV MCL OCONV/S MCL UPCASE ICONV MCU OCONV/S MCU OCONV/S MCT ICONV MCT OCONV/S ML ICONV ML CONVERT OCONV/S MCC ICONV MCC OCONV/S MCP ICONV MCP TRIM TRIMB TRIMF OCONV/S S Action Converts characters to lowercase. Converts characters to uppercase. and the remaining characters are lowercase. Removes all leading spaces from a string. Left-justifies a string or dynamic array. Converts nonprinting characters to tildes (~). Developing UniBasic Applications 169 . Removes all extraneous spaces from a string.

Chapter 6 - Working with Data in Programs

In the following example, OCONV MCU converts all characters in the variable i_or_o to uppercase:

Program Example
PROMPT "" LOOP PRINT "Input or output [I/O]?" : INPUT i_or_o IF i_or_o = "" THEN STOP PRINT "Conversion code? " : INPUT y_conv_code PRINT "Argument? " : INPUT z_argument IF OCONV(i_or_o, "MCU")= "O" THEN PRINT "Executing OCONV" answer = OCONV(z_argument,y_conv_code) END ELSE answer = ICONV(z_argument,y_conv_code) END PRINT \"\ : answer : \"\ WHILE 1 DO REPEAT DISPLAY @(10,9+ENTRY):OCONV(ORDER.REC<7,ENTRY>,"MR2$,"):

Numbers
You can round and scale numbers, and you can use special characters to format numbers for display as dollars or other styles. You can also convert numbers among decimal, binary, octal, hexadecimal, and ASCII. The following two sections introduce the conversions available and the functions for performing these conversions: • • Formatting and modifying numbers. Converting among numbering systems and ASCII.

170

Developing UniBasic Applications

Formatting and Converting Data

Formatting and Modifying Numbers
You can use the functions described in the following table to format, convert, and modify numbers. Function FMT OCONV/S ML Action Right or left justifies, suppresses zeros, and formats using special characters. Left justifies, suppresses zeros, scales a specified number of decimal places, rounds to specified number of decimal places, and formats using special characters. Left justifies, scales a specified number of decimal places, and rounds to specified number of decimal places. Right justifies, scales a specified number of decimal places, rounds to the number of decimal places indicated, and suppresses or adds zeros to the left or right. Formats for dollars using special characters. For OCONV only, adds special characters for credit, debit, and other monetary indicators.

ICONV ML ICONV MR OCONV/S MR ICONV MRn OCONV/S MRn ICONV MD OCONV/S MD FMT

Specifies length of converted string, fills string with a specified character if data is shorter than the length indicated, breaks up the string if it is longer than the length indicated, centers text, scales a specified number of decimal places, and adds other special characters. Converts decimal to integer, scales a specified number of decimal places, and rounds to specified number of decimal places. Converts integer to packed decimal. Converts packed decimal to integer. Functions for Formatting and Modifying Numbers

ICONV MD OCONV/S MP OCONV/S MP1 ICONV MP

For the syntax and use of these commands, see theUniBasic Commands Reference.

Developing UniBasic Applications

171

Chapter 6 - Working with Data in Programs

The following program segment is taken from the sample program in “Appendix A - Sample Program.” In this example, OCONV MR2$ is used to display the price of an item.

Program Example
ALTER_RECORD: * Create a new screen, and allow PRICE and ADDRESS to be changed. * Initialize variables and draw the screen NEED.TO.WRITE = 0 DISPLAY @(-1):@(15,5):"Alter ORDER": DISPLAY @(10,8):"(Press RETURN to leave un-changed)" DISPLAY @(8,9):"Old Price":@(42,9):"New Price (Enter 2 decimal places)"

* Change the PRICE field (if desired) FOR ENTRY = 1 TO NUM_ENTRIES NEW.PRICE = "" DISPLAY @(10,9+ENTRY):OCONV(ORDER.REC<7,ENTRY>,"MR2$,"): INPUT @(45,9+ENTRY):NEW.PRICE NEW.PRICE = OCONV(NEW.PRICE,"MCN") IF NEW.PRICE # '' AND NUM(NEW.PRICE) THEN ORDER.REC<7,ENTRY> = NEW.PRICE NEED.TO.WRITE = 1 END NEXT ENTRY

Alternate Numbering Systems and ASCII
You can convert among decimal, ASCII character, binary, octal, and hexadecimal by using various options of the ICONV and OCONV functions. Function ICONV MB ICONV MB0C OCONV/S MB Binary Binary Decimal From Decimal ASCII characters Binary To

Converting Among Numbering Systems and ASCII

172

Developing UniBasic Applications

Formatting and Converting Data

Function OCONV/S MO OCONV/S MX OCONV/S MCD[x] ICONV MCX[D] SEQ ICONV MO ICONV MO0C OCONV/S MCX[D] OCONV/S MCD ICONV MX ICONV MCD[X] ICONV MX0C ICONV HEX OCONV/S MB0C OCONV/S MO0C

From Decimal Decimal Octal

To

Hexadecimal

Decimal Octal Octal Hexadecimal

ASCII character Decimal ASCII characters Decimal

Hexadecimal ASCII character ASCII character

ASCII characters Binary Octal

Converting Among Numbering Systems and ASCII (continued) OCONV conversions from ASCII characters produce multiple-digit numbers in the target numbering system: • • • Hexadecimal – One ASCII character produces two hexadecimal characters. For example, ASCII character 0 is equal to hexadecimal 30. Octal – One ASCII character produces three octal characters. For example, ASCII character 0 is equal to octal 060. Binary–One ASCII character produces eight binary characters. For example, ASCII character 0 is equal to octal 00110000.

For the syntax and use of these commands, see the UniBasic Commands Reference.

Developing UniBasic Applications

173

Chapter 6 - Working with Data in Programs

Numbering System Examples
The following table provides examples using the ICONV and OCONV functions to convert among numbering systems and ASCII characters. Function ICONV MB ICONV MB0C OCONV/S MB OCONV/S MO OCONV/S MX SE ICONV MO ICONV MO0C ICONV MX ICONV MX0C ICONV HEX OCONV/S MB0C OCONV MO0C OCONV/S MX0C OCONV/S HEX CHAR From 01100100 01100100 100 100 100 100 144 144 64 64 d d d d 100 d 01100100 144 64 d 100 d 100 d 01100100 64 64 100 To

Examples of Numbering System Conversions For the syntax and use of these functions, see the UniBasic Commands Reference. The following example demonstrates the use of ICONV to convert from hexadecimal to ASCII character:

174

Developing UniBasic Applications

Formatting and Converting Data

Program Example
PRINT PRINT INPUT o_num PRINT END "Convert hex to ASCII character." "Enter hex number to convert: " : i_num = ICONV(i_num,'MX0C') "hex ":i_num:" = ASCII character ": o_num

Here is the output from the previous program:

Screen Example
Convert hex to ASCII character. Enter hex number to convert: ?64 hex 64 = ASCII character d

Dates and Times
The OCONV and ICONV functions convert dates and times from the internal format stored in UniData files to a more readable external format suitable for display or inclusion in a report.

Developing UniBasic Applications

175

Chapter 6 - Working with Data in Programs

Date Formats
Valid formats for internal storage and external display of dates include the following: • • Internal format – The number of days before or since December 31, 1967. External format – You can direct UniData to use spaces, forward or backward slashes, periods, or commas as delimiters when converting to or from the following output formats: • • • Standard U.S.: MM/DD/YY International: DD/MM/YY Month, Day, Year (month can be a number, three-digit abbreviation, or can be spelled out; day of the week can be added)

Tip
Store dates in internal format so that you can then perform arithmetic operations on them.

Functions for Converting Dates
Use the ICONV and OCONV functions to convert between internal and external date formats. Function ICONV D OCONV/S D ICONV MT OCONV/S MT Action Converts from standard U.S. external date format to system date. Converts from internal system date to a specified external date format. Converts from external time format to system time. Converts from internal system time to external time format. Functions for Converting Dates For the syntax and use of these functions, see the UniBasic Commands Reference.

176

Developing UniBasic Applications

Formatting and Converting Data

Points to Remember When Entering Dates
If you are not aware of the following defaults, conversions into internal date format (using ICONV) might not produce the effects you expect: • • If you do not enter a year, UniData defaults to the current year. For example, if you enter 12/1 and the year is 1996, the system stores 10563 (12/1/96). If you enter a number between 1 and 12, UniData defaults to the first day of the month and the current year. For example, if this year is 1996 and you enter 12 only as the date, UniData stores 10563 (12/1/96).

UDT.OPTIONS
You can invalidate all date input of less than six digits by setting UDT.OPTIONS 82 on.

Century Pivot Date
Prior to UniData 5.2, any 2-digit year entered from 01 through 29 defaulted to the next century. For example, UniData interpreted 12/31/29 as December 31, 2029. 1930 was the century pivot date. You can now set your own century pivot date. The century pivot date only applies to the ICONV function when using the D2 format, not D3 or D4. The udtconfig file, located in /usr/ud52/include on UniData for UNIX or \udthome\include on UniData for Windows NT or Windows 2000, now contains the CENTURY_PIVOT parameter, with a default value of 1930. You can change this value in one of the following ways: • Enter a 4-digit year. UniData interprets this first 2 digits as the century, and the last 2 digits as the year. The last 2 digits of the year you enter, through 99, are considered to be in the century you specify. 0, through the year you entered -1, are considered to be in the next century. For example, if the century pivot date is 1950, years 50 through 99 are in the 1900’s, and years 0 through 49 are in the 2000’s. If the century pivot date is 2000, 0 through 99 are in the 2000’s. Enter a code in the form of nn, indicating that the next nn years are in the next century. UniData calculates the century pivot date as: current_year - (100 - nn)

Developing UniBasic Applications

177

External format – You can direct UniData to use spaces or special characters such as slash. The CENTURY. or asterisk as delimiters when converting to the following output format: HH MM [SS]. the century pivot date is 1950 (2000 . comma.PIVOT ECL command overrides the systemwide century pivot date defined in the udtconfig file.PIVOT(4-digit year | nn) Time Formats Valid formats for internal and external storage and display of time include the following: • • Internal format – The number of seconds since midnight. 178 Developing UniBasic Applications .PIVOT with no options. UniData returns the current setting for the century pivot date. You can also use the UniBasic CENTURY.PIVOT [4-digit year | nn] If you enter CENTURY.Working with Data in Programs For example.PIVOT function to set the century pivot date.50)). period.(100 .Chapter 6 . Syntax: CENTURY. if the current year is 2000 and the century pivot code is 50. Syntax: CENTURY.

On the first print line. Program Example PRINT "Enter date to be converted to internal format:" INPUT i_date o_date = ICONV(i_date. First. Function OCONV/S D2/ OCONV/S D4* ICONV MT Input Value 1 10300 12:00 Output Format 1/1/68 03*13*1996 43260 Date and Time Conversion Examples Developing UniBasic Applications 179 .Formatting and Converting Data Date and Time Examples The following program demonstrates conversion into internal date format. the user is prompted for date."D2/") END The following results if the year is 1995 and you enter 3 in response to the prompt: Screen Example Enter date to be converted to internal format: ?3 Date 3 was converted to 9922 9922 converts back to 03/01/95 The following table shows several date and time conversions. the date is displayed both as entered and in internal format. and year. and that date is converted to internal format. The next print line displays the internal date converted back to external format with a slash between the two-character month."D") PRINT "Date ":i_date:" was converted to ":o_date PRINT o_date:" converts back to ":OCONV(o_date. day.

S.Working with Data in Programs Function ICONV D OCONV/S DDMY. format.Z4 OCONV/S MT Input Value 12/1/28 22251 82800 Output Format 22251 01 December 2028 23:00 Date and Time Conversion Examples (continued) Note Dates default to U.Chapter 6 .FORMAT. For European format. use the ECL command DATE. which is described in the UniData Commands Reference. 180 Developing UniBasic Applications .A.

because. Multibyte languages require that strings be recognized by character rather than byte. Function CHANGE CHAR CHARS COL1 COL2 CONVERT COUNT Comment Replaces all occurrences of a substring with a string. These changes do not affect functionality for single-byte languages. Changes a numeric value in an array to its ASCII character equivalent. Modified Functions and Commands The following table lists the UniBasic functions that have been modified to analyze strings by character instead of byte. Multibyte Functions – Designed specifically for multibyte language support. • • • Modified Functions and Commands – Support multibyte languages.or multibyte character string to another character string. Returns the number of times a substring appears within a string.UniBasic Multibyte Support UniBasic Multibyte Support This section summarizes the support of languages that require multiple bytes to represent a single character. Returns the column position following a substring found by the FIELD function. UniBasic Character Recognition Functions Developing UniBasic Applications 181 . one byte represents each character. Returns the column position preceding a substring found by the FIELD function. Converts a single. for these languages. Changes a numeric expression to its ASCII (American Standard Code for Information Interchange) character string equivalent. Single-Byte Functions – Support only single-byte languages.

Receives unprompted input from an attached line.Chapter 6 . See the note on mask parameters later in this chapter. See also COL1 and COL2 in this table. Places the cursor at a specific location on the terminal screen and requests input from the user. Returns the length of an expression. Returns the length of the values within each element of a dynamic array. Determines if a variable matches a specific pattern of characters or numbers. Only single-byte characters are considered to be alphabetic or numeric. UniBasic Character Recognition Functions (continued) FINDSTR GET ICONV INDEX INPUT INPUT @ LEN LENS MATCH MATCHFIELD OCONV 182 Developing UniBasic Applications . Converts string or numeric data to internal representation format based on conversion codes. Determines the position of a substring in a dynamic array. Returns a substring that matches a pattern or literal. Only single-byte characters are considered to be alphabetic or numeric. with fields delimited by any ASCII character. Counts delimited substrings. Returns the starting position of a specified occurrence of a substring within a string. treats a string as an array. Converts string or numeric data from internal format to display format based on conversion codes. Locates and returns a substring or group of substrings.Working with Data in Programs Function COUNTS DCOUNT FIELD Comment Returns the number of times a substring appears within each element of an array. Requests data from an input queue or the terminal screen.

Converts only single-byte characters to lowercase. each double-byte character uses two display characters. Converts a single character to its ASCII code value. four double-byte characters displayed in the mask "######" prints as "XX -XX " (two characters. then assigns the delimiter and following array element to a variable. UniBasic Character Recognition Functions (continued) SEQ SEQS SUBSTRINGS SWAP Note Mask – Multibyte characters could be masked for display purposes. Converts the first character in each element of a dynamic array to its ASCII code value. Function ALPHA DOWNCASE Comment Because UniBasic does not recognize multibyte characters as alphabetic. However. a space. Extracts strings from elements within a dynamic array. Replaces all occurrences of one substring with a second substring. two characters. So. Single-Byte Functions Developing UniBasic Applications 183 . Recognizes col. Single-Byte Functions The following table lists the functions that might not work properly when used with a multibyte character set. returns 0 instead of converting them.pos as a character position. and a space).UniBasic Multibyte Support Function REMOVE Comment Searches a dynamic array for system delimiters. a hyphen.

Function BYTELEN CHARLEN Description Returns the number of bytes in a string. Determines if an expression is numeric. Single-Byte Functions (continued) NUM NUMS PROMPT SOUNDEX UPCASE Note Mask – Multibyte characters can be masked for display purposes. Converts an expression into a phonetic code. Converts only single-byte characters to uppercase. So. for each element of an array. Can return unpredictable results with multibyte characters. hyphen. Returns 0 for multibyte characters. Returns 0 if the dynamic array element contains multibyte characters. Returns the number of characters in a string. four double-byte characters displayed in the mask “######” prints as “XX -XX ” (two characters. You cannot prompt with a multibyte character. space. See the note on mask following this table. Sets the prompt displayed by the INPUT command to a specified singlebyte character. UniBasic Functions for Multibyte Languages 184 Developing UniBasic Applications . two characters. Multibyte Functions The following UniBasic functions are designed for use with multibyte character sets. Determines.Chapter 6 .Working with Data in Programs Function FMT Comment Formats an expression for display. each double-byte character uses two display characters. The fill character must be single-byte. if that element is numeric. The length parameter defines the number of display characters. However. and a space). and the justification option does not work for multibyte languages.

Returns the number of bytes in a string. see UniData International. Returns the number of bytes required to display a character.UniBasic Multibyte Support Function DISPLAYWIDTH ISMB LEN MBLEN Description Returns the number of bytes required to display a string expression. Developing UniBasic Applications 185 . UniBasic Functions for Multibyte Languages Note For examples of these commands in multibyte languages. 1 for multibyte language setting. Returns a 0 for single-byte language setting.

Chapter 6 .Working with Data in Programs 186 Developing UniBasic Applications .

Developing UniBasic Applications 187 .Chapter 7 .External Interaction This chapter introduces the concepts and commands that enable you to write a UniBasic program that communicates with external software and hardware.

see the UniData Commands Reference. For more information about using C programs (for UNIX) or external programs (for Windows NT or Windows 2000) with UniData.Chapter 7 . menus. 188 Developing UniBasic Applications .” For more information about the interaction of UniBasic with paragraphs. see the Using UniData.External Interaction In This Chapter UniBasic program interaction with software and hardware is presented in the following sections: • • • • • “Interacting with Other UniBasic Programs” “Interacting with UniData” “Writing User Exits” “Interacting with Hardware I/O Devices” “Interacting with the Operating System” For more information about running UniBasic programs from ECL. see “Chapter 8 .Linking Programs with UniData. and virtual attributes.

Interacting with Other UniBasic Programs Interacting with Other UniBasic Programs You can interact with other UniBasic programs by sharing data. Tip Remember that if you include EXECUTE or CHAIN in the program. You can retrieve arguments that were included in this statement by parsing the contents of @SENTENCE. from a paragraph. Developing UniBasic Applications 189 . You can use one of the following vehicles for passing variables among UniBasic programs: • • • • Program Arguments (using @SENTENCE) Subroutine Call Arguments COMMON Data Stacks Program Arguments You can execute a UniBasic program from ECL. the value of @SENTENCE will be updated. you can divide processing into several programs that use the same variables. The statement that executes the program is stored in @SENTENCE. by incorporating code at compilation. and by calling programs. or from another UniBasic program. These commands and concepts are presented in the following parts of this section: • • Sharing Data Including Code at Compilation Sharing Data When you design an application.

For this reason. So when xx is updated by being concatenated with !.sub(tv1. both variables. and when yy. The output for this program follows: xx = howdy!? yy = howdy!? 190 Developing UniBasic Applications .sub program: SUBROUTINE test.Chapter 7 .tv1) test. is updated by being concatenated with ?. xx and yy refer to the variable tv1.External Interaction Subroutine Call Arguments When only few variables are being passed. if you pass the same variable twice.sub(xx. xx is also updated. which now contains howdy!. yy is also updated. passing variables through arguments is the most expedient method of sharing data. The variables must be defined the same in the calling and called routines. both xx and yy always contain the same value in the following program: test program: tv1 = "howdy" CALL test. or only two programs share them.yy) xx = xx : "!" yy = yy : "?" PRINT "xx = ":xx PRINT "yy = ":yy RETURN In the preceding subroutine. Regardless of the BASICTYPE you use to compile. The SUBROUTINE command begins a cataloged subroutine and lists the arguments to be received. and the called program or subroutine must provide for the arguments in the SUBROUTINE statement. The CALL command transfers processing to the called program and lists the arguments to be passed. UniBasic updates the variable values for both occurrences of the variable whenever you change either one.

This makes it easier to tell which subroutine uses which arguments. before accessing them. Data Stacks You can use a data stack to pass data to INPUT statements in called processes or UniBasic programs. After UniData exhausts all the responses in the data stack. Items in the stack are delimited by CR (carriage return).Interacting with Other UniBasic Programs COMMON When you are sharing groups of variables among multiple programs. You can most efficiently accomplish this by defining common in a file and including that file in programs at compile time (with $INCLUDE). by executing the COMMON command. The data stack is managed as follows: • • • • The stack is stored in the @DATA system variable. returning the user to the ECL prompt. pass parameters in SUBROUTINE arguments rather than through common areas. The stack is loaded by the DATA command. which loads the data stack. you can use the single unnamed common or multiple named common areas to pass a stack or stacks of variables. The stack is available until the user process ends. Warning Trying to access variables in common areas before defining them with the COMMON command could result in a core dump. Tip The DATA statement. Each program that needs to access the variables must define the named or unnamed common area(s). The stack is built and depleted on a first in first out basis. can also be placed in a UniData paragraph. Developing UniBasic Applications 191 . it reverts to the terminal for user input. Tip When possible.

Examples of Passing Data Through a Data Stack In this example.DATE and REGION.END. The first program contains the following code: Program Example PRINT "Enter the last date for activity" INPUT ACT.END. otherwise.External Interaction Tip To suppress output to the terminal.DATE * check for valid dates and convert to internal form PRINT "Enter Region" INPUT REGION * check for valid regions * display data PRINT "Do you want a hardcopy?" INPUT ANS IF ANS = "Y" THEN DATA ACT.END. another program prints the same information in hardcopy. .Chapter 7 . Both programs require input to be loaded into the variables ACTIVITY. the INPUT prompt and data stack response are displayed. .PRINT program END . UniBasic fills them from the data stack. * execute REGION. execute the UniBasic HUSH command immediately before the INPUT command that reads the stack.PRINT are executed.PRINT". When the INPUT statements in REGION. passing the values in a data stack rather than prompting the user for the same data twice. a program prompts for user input and displays information requested by the user on a display terminal. 192 Developing UniBasic Applications .DATE DATA REGION CHAIN "REGION. The first program CHAINs to the second program.

PRINT. You might use these commands to include stack routines that perform frequently used operations. When UniBasic encounters a RETURN statement in the subroutine.END. such as EQUATE and DEFFUN. it displays on the screen followed by the response from the data stack. The presence of the data stack does not inhibit the prompt. prompts for the passed data. Executing UniBasic Programs and Subroutines The following table lists commands that execute other UniBasic programs and subroutines.DATE * check for valid dates and convert to internal form PRINT "Enter Region" INPUT REGION * check for valid regions Note You can clear the stack created by DATA statements using either the UniBasic or ECL CLEARDATA commands. it returns control to the calling program. Including Code at Compilation You can insert a UniBasic program or program segment during compilation with the UniBasic commands $INCLUDE and $INSERT.Interacting with Other UniBasic Programs The following program segment. Executing UniBasic Programs and Subroutines Developing UniBasic Applications 193 . Command CALL Acton Transfers control to an external subroutine. Program Example PRINT "Enter the last date for activity" INPUT ACT. which is taken from REGION.

External Interaction Command CHAIN Acton Terminates the current UniBasic program and executes another program. 194 Developing UniBasic Applications .OPTIONS 11 and 27 clear the data stack.OPTIONS 6 and 40 determine where control is passed on RETURN.OPTIONS UDT. For more information.) ENTER EXECUTE/ PERFORM Executing UniBasic Programs and Subroutines (continued) UDT. A common use of CHAIN is to execute a cataloged program. UDT.OPTIONS Commands Reference. (You can EXECUTE “RUN program.Chapter 7 . see the UDT. Executes an ECL or UniData SQL command. Transfers control to a cataloged program.

The UniBasic @variables are listed in the UniBasic Commands Reference. others are available only through UniBasic. Executing Virtual Attributes Reminder Virtual attributes are dictionary records that contain executable code. They are explained in Using UniData. Some are available through any UniData or 4GL tool. see Using UniData. or the ITYPE function.Interacting with UniData Interacting with UniData Interaction with other UniBasic programs and UniData products is presented in the following sections: • • • • “Executing Virtual Attributes” “Executing ECL Statements” “Executing UniData SQL Statements” “Defining and Using Programs and Functions” Reminder UniData stores and makes available information about the system. and the UniBasic program being executed in @variables. For a complete list of UniData @variables. You must first open the dictionary containing the virtual attribute to @DICT and read a record from the corresponding data file into @RECORD. the user process. You can execute a virtual attribute from within a UniBasic program with the UniBasic CALCULATE or {} command. Developing UniBasic Applications 195 .

Execute Commands The following UniBasic statement executes the ECL command LIST. The following table lists the UniBasic commands for executing UniData commands. Command EXECUTE PERFORM Action Executes an ECL command. Use the RETURNING clause to save error messages.Chapter 7 . Also returns output and error messages in variables if specified.Use the CAPTURING clause to save output of the executed command in an dynamic array. Returns output and error messages in variables if specified. Any entry valid at the ECL prompt can follow an execute command.READU" 196 Developing UniBasic Applications . Executes an ECL command in BASICTYPE U regardless of the BASICTYPE the program was compiled in. Note . and transfers a select list if specified.READU: UDTEXECUTE Program Example EXECUTE "LIST. MDPERFORM Executes a UniData command. Also returns output and error messages in variables if specified.External Interaction Executing ECL Statements You can execute ECL commands within a UniBasic program.

" IN CLIENT.CITY FROM CLIENTS TO SQL_INPUT.Interacting with UniData The next UniBasic statement executes a UniQuery statement: Program Example EXECUTE "SSELECT CUSTOMER WITH STATE='CO' BY ZIP" For more information about ECL. In the following example." DONE=0 LOOP PRINT "DONE = ":DONE READNEXTTUPLE CLIENT. Developing UniBasic Applications 197 . EXECUTE.TO statements.ADDRESS.. ADDR. and CITY: Screen Example EXECUTESQL "SELECT NAME. If you need to return selected items for subsequent processing by the program. Executing UniData SQL Statements You can use the EXECUTESQL.REC = ":CLIENT. include a TO clause and a variable in which UniData SQL can return selected items.REC FROM 'SQL_INPUT' ELSE DONE = 1 UNTIL DONE CONVERT @AM TO " " IN CLIENT. see Using UniData. and PERFORM commands to execute UniData SQL statements..REC CONVERT @VM TO ".REC REPEAT END Note You must use the UniBasic command CLEARSQL to clear active UniData SQL variables created with EXECUTESQL. the variable SQL_INPUT is provided for the return of NAME.REC PRINT "CLIENT.

Commands for Defining and Using Programs and Functions 198 Developing UniBasic Applications .External Interaction Defining and Using Programs and Functions Within a UniBasic program. Creates a user-written function that accepts passed arguments and can return values. Command/ Function PROGRAM FUNCTION DEFFUN Action Provided for backward compatibility. you can use the commands described in the following table to write and call other programs and functions.Chapter 7 . Defines a program. Declares a user-written function that was defined by the UniBasic FUNCTION command.

or a UniData paragraph. UniQuery. You can call user exits from UniBasic. UniData supports user exits. a UniBasic command or function. Developing UniBasic Applications 199 . UniBasic provides many of these conversions in the UniBasic ICONV and OCONV functions.Writing User Exits Writing User Exits An explanation of user exits and the procedures for writing and calling them are explained in the following subsections: • • • • • “What Are User Exits?” “Calling a User Exit from UniBasic” “Calling a User Exit from a Virtual Attribute” “Calling a User Exit from a Proc” “Parameters in User Exits” What Are User Exits? Some RDBMS systems employ “user exits” to convert and format data. Tip You might find that the operations provided by user exits can be performed more efficiently by a UniData @variable. For backward compatibility. UniData supports user exits from Procs. This section focuses on calling user exits from UniBasic programs and calling UniBasic subroutines that serve as user exit functions. for backward compatibility. which consist of a calling statement and a UniDataprovided or user-defined UniBasic subroutine. However. and UniData paragraphs.

type) 200 Developing UniBasic Applications . see Using UniData. The first command in the subroutine must be the following: Syntax: SUBROUTINE Uuser.External Interaction Calling a User Exit from UniBasic Perform the following steps to call a user exit from a UniBasic program. Select a UniData user exit that performs the conversion you want. use the following syntax: Syntax: ret. The first command in the subroutine must be the following: SUBROUTINE Uuser. 1. or Write a UniBasic subroutine to perform the conversion.val. For a list of user exit conversion routines.Chapter 7 .exit") The parameters used in these commands are explained in “Parameters in User Exits” later in this section. status. Calling a User Exit from a Virtual Attribute Perform the following steps to write a virtual attribute that calls a UniBasic user exit or UniDatadefined user exit: 1. For a list of user exit conversion routines.val. status. input. or Write a UniBasic subroutine to perform the conversion. see Using UniData. Write the user exit call in your UniBasic program.exit(ret. Regardless of the type of user exit you are calling. type) 2."Uuser.val = {ICONV | OCONV}(input.val.val.val.exit(ret. The called user exit can be UniData-defined or user-defined. input. Select a UniData user exit that performs the conversion you want.

. see Using UniData.sib.val. or Write a UniBasic subroutine to perform the conversion using the following syntax: Syntax: SUBROUTINE Uuser. Select a UniData user exit that performs the conversion you want."Uuser. For a list of user exit conversion routines. Developing UniBasic Applications 201 .exit(proc.param2].pob. Write a statement in a Proc that calls the user exit."Uuser.cob..or UniData-defined user exit: 1. Syntax: Uuser..input.ibp. Calling a User Exit from a Proc Perform the following steps to write a Proc that calls a UniBasic.val.exit") Multivalued/Multi-subvalued: SUBR(’-{ICONVS | OCONVS}’.exit") The parameters used in these commands are explained in “Parameters in User Exits” later in this section.[.pib.cib. The syntax that you use depends on whether you are converting single or multivalued/multi-subvalued attributes: • • Singlevalued: {ICONV | OCONV}(input..exit param1 [.Writing User Exits 2. Write a virtual attribute that calls the user exit.].sob) 2.

The primary input buffer. The secondary input buffer. The source code of the Proc itself. Parameters in User Exits 202 Developing UniBasic Applications . The secondary output buffer. UniData reads the Proc user exit statement. The input buffer pointer.val type proc cib pib sib ibp cob pob sob Description The name of the UniData user exit or user-defined UniBasic subroutine that performs the conversion. then passes it and all subsequent lines as proc.Chapter 7 . The status of the conversion. 0 indicates a successful conversion. The type of conversion: 0 for external format to internal format and 1 for internal format to external format. The input string or value to be converted.val status input.exit ret. Parameter Uuser. The current output buffer: 0 for primary and 1 for secondary.External Interaction Parameters in User Exits The following table describes each parameter of the syntax. The current input buffer: 0 for primary and 1 for secondary. The primary output buffer. The string or value UniData returns to the calling program as a result of the conversion function.

Input Commands INPUTNULL INPUTERR Developing UniBasic Applications 203 . Allows a single character to be defined as the null character in an INPUT @ statement. and tape drives. For more information about data stacks. you can direct input and output (I/O) devices such as display terminals. printers. and determines the characteristics of the data received. Command INPUT INPUT @ Action Requests data from a user terminal or a data stack. see Using UniData. Prints a user-defined error message on the bottom line of the display terminal and clears the error message when UniData receives the next input.Interacting with Hardware I/O Devices Interacting with Hardware I/O Devices When programming in UniBasic. determines the cursor position and display a mask on the terminal. Requests data from a user terminal or a data stack. These commands are introduced in the following subsections: • • • “Display Terminals” “Printers” “Tape Drives” Display Terminals Input Commands Input commands request data from a user’s keyboard or a data stack and store the result in a variable for use in a UniBasic program. UniBasic provides the following commands for accepting and acting on user input from the terminal.

OPTIONS described in the following table affect the input commands. For example. or see the DATA command in the UniBasic Commands Reference. see “Sharing Data” earlier in this chapter. UniData retains unused characters and they are available for subsequent input statements. the following program segment loads the string “FINISHED” in the data stack and then loads it in the variable CODE.OPTIONS for Input 204 Developing UniBasic Applications . expr with a data stack and an element in the data stack is shorter than expr. Conditionally branches to a specific statement label when specific characters are entered. UDT. Input Commands (continued) Tip You can fill input statements from the data stack rather than from user input. The UDT.External Interaction Command INPUTIF CLEARINPUT INPUTCLEAR INPUTTRAP Action Assigns data from the type-ahead buffer to a variable. OPTION 12 Description When ON If you use INPUT var. Program Example DATA "FINISHED" INPUT CODE UniBasic allows up to 500 elements in the data stack. UDT.Chapter 7 . Clears the type-ahead buffer. For more information about the data stack.

UDT. see the UDT. For more about the @ function.OPTIONS For more information about UDT. Enables or disables terminal output. see “Enhanced Terminal Capabilities” later in this chapter. Command CRT. OPTION 18 65 Description When ON When UniData passes data to a UniBasic program to fill an input statement. Prints to the display terminal at a specific column and row position. UniData suppresses the echo of the prompt character and the data. DISPLAY HUSH PAGE PRINT PRINT @ Action Directs output to the display terminal (CRT) regardless of the setting of the PRINTER command. If you exceed the field length during an INPUT command.OPTIONS Commands Reference.Interacting with Hardware I/O Devices UDT.OPTIONS. Terminal Control Use the commands in the following table to control display on the terminal.OPTIONS for Input (continued) UDT. More Display Terminal Commands and Functions You can use the following UniBasic commands to manage display terminal and keyboard I/O. Prints the current output page. the terminal beeps. Terminal Control Commands Developing UniBasic Applications 205 . Prints to the display terminal or printer.

and Footings The commands in the following table control the display of the prompt character and headings and footings.External Interaction Note Print lines can be up to 256 characters. and Footing Commands 206 Developing UniBasic Applications . Headings. which can be up to 536 characters. Keyboard Control Use the ECHO and BREAK commands to control keyboard input. Keyboard Control Commands Prompt. Enables or disables the break key. the break key interrupts program execution and places the user at the debugger prompt. Heading. Displays a footing at the bottom of each page. When enabled. Command PROMPT HEADING FOOTING Action Sets the input prompt to a user-supplied one-character string or empty string. For more information about LIMITS.Chapter 7 . Displays a heading at the top of each page. Command ECHO BREAK Action Enables or disables display of keyboard input on the terminal. see the UniData Commands Reference. which can be up to 536 characters. Prompt.

see the @ function in the UniBasic Commands Reference.0. such as PRINT @ or DISPLAY @.expr) For a table of all @ options. Clears from cursor to end of line. Places the cursor at position 0.0.) Moves cursor up one line. Perform one of 84 terminal actions. Move cursor down one line. Clears from cursor to end of screen. Reminder Because @ is a function.row]) @(-num. Sends audible signal. it must be used within a statement that contains a command. which enable you to: • • Syntax: @(col[. (Terminal beeps. Developing UniBasic Applications 207 .Interacting with Hardware I/O Devices Enhanced Terminal Capabilities The UniBasic @ function has two forms. Option -1 -2 -3 -4 -19 -10 -17 Action Clears the screen and places the cursor at position 0. @ Function Options for Terminal Control Specify a column and row to position the cursor. Some commonly used options are provided in the following table.

23):"Invalid choice. if udtermcap does not exist. UniBasic queries the /etc/termcap file.1):'***' The following command clears the display terminal and positions the cursor at row 0. 208 Developing UniBasic Applications . For Windows NT or Windows 2000. UniBasic returns a status message stating that it cannot find the file and will default to vt100 terminal emulation. column 0: Screen Example PRINT @(-1) In the next example the terminal bell beeps after an error message is printed: Screen Example PRINT @(0. For UNIX. For example. if terminfo does not exist. Please re-enter. Obtain terminal emulation settings from your hardware vendor.":@(-19) Note UniBasic searches the /usr/lib/terminfo file (for UNIX) or the udthome\include\udtermcap file (for Windows NT or Windows 2000) to obtain terminal configuration and interpretation of the @ code. the following statement prints three asterisks on row 1 beginning in column 38: Screen Example PRINT @(38.Chapter 7 .External Interaction Examples The PRINT @ statement prints data at a specific column and row.

HEADING. see the UniData Commands Reference.Interacting with Hardware I/O Devices Printers The following table lists the commands that direct the printer. Direct output stored in a print file or a print buffer to the print queue. Developing UniBasic Applications 209 . Printer Commands Note Print lines can be up to 256 characters. Command PRINT ON PRINTER CLOSE PRINTER OFF PRINTER ON Action Direct output to a specific printer. and PRINT. Reminder The following commands manage both display terminal and printer output: FOOTING. Direct output to the display terminal. Direct output to the printer. For more information about LIMITS. PAGE.

Retains the heading when the @ function is used. @ function HEADING. Closes the print job after printing completes. 9 25 EXECUTE.OPTIONS in the following table affect the way in which data is printed.OPTIONS for Printing 210 Developing UniBasic Applications . Prints the break line and suppresses the preceding blank line. Pauses at the bottom of each screen page. PERFORM UniQuery BREAK.FORMAT. FOOTING 29 32 34 UDT. UDT.Chapter 7 .External Interaction UDT.ON keyword OCONV HEADING. This option also is affected by the ECL command DATE. formats month in uppercase.OPTION 4 5 7 Command Affected OCONV in the absence of HEADING n/a Effect When On When printing dates. Displays the system date in a specific format. When printing dates. converts Sunday to 7 (rather than 0). essentially inhibiting double spacing. OPTIONS and Printing The UDT. Page feeds or returns to the colon prompt after the last line of data is printed rather than printing blank lines to end of page.

Developing UniBasic Applications 211 . EXECUTE PERFORM. INPUT. Forces the footing to print on the final page of a report. 48 PRINT. DISPLAY. 59 PRINT.) When generating a BSELECT list. does not break as specified in format. STOP Effect When On Waits for PRINT.OPTIONS For detailed information about UDT.OPTIONS for Printing (continued) UDT.OPTIONS. CRT When printing right-justified data. EXECUTE. (Will overwrite another column of data.OPTION 46 Command Affected PRINT.Interacting with Hardware I/O Devices UDT. DISPLAY. CRT 64 FOOTING UDT. CRT DISPLAY. see the UDT.OPTIONS Commands Reference. INPUT. SLEEP. or FLUSH before flushing data to the system buffer. does not create a blank line for a key when the selected attribute is an empty string.

For more information.ATT.External Interaction Tape Drives Before you execute the UniBasic tape drive commands. Writes an EOF (end-of-file) mark to tape. you must: • • Initialize the tape drive with the ECL SETTAPE command. UniBasic manages tape drive I/O with the following commands. Writes a record onto tape.Chapter 7 . Rewinds the tape. Other ECL commands also manage the tape drive. Tape Drive Commands REWIND WEOF WRITET 212 Developing UniBasic Applications .ATT command. Changes the block size used by the WRITET command when the block size in one file is not the same as the block size in T. Command READT RESIZET Action Reads the next available record from a tape. Attach the tape drive with the ECL T. see Using UniData.

Interacting with the Operating System Interacting with the Operating System Use the commands in the following table to interact with the operating system within a UniBasic program. Command/ Function PCPERFORM SYSTEM Action Executes an operating system command within a UniBasic program.LOCATION Developing UniBasic Applications 213 . Retrieve system-level information set by previous UniBasic or ECL commands such as SETPTR and TERM.LOCATION: Screen Example PCPERFORM 'pwd' CAPTURING MY. The following UniBasic statement executes the UNIX command pwd (print working directory) and stores the results in the variable MY. see the UniBasic Commands Reference. UniBasic Operating System Commands For more information about these functions.

External Interaction 214 Developing UniBasic Applications .Chapter 7 .

see Administering UniData on UNIX or the Administering UniData on Windows NT or Windows 2000. Developing UniBasic Applications 215 .Linking Programs with UniData This chapter introduces the concepts and procedures for writing a UniBasic program that calls or is called by an external C program. For more information about CALLC.Chapter 8 .

Linking Programs with UniData In This Chapter This chapter consists of the following sections: • • “Linking C Programs (UNIX Only)” “Linking C Programs (Windows NT or Windows 2000 Only)” 216 Developing UniBasic Applications .Chapter 8 .

For instructions. For more information. The cfuncdef file printed in the section “File Examples” later in this chapter shows the correct version of this file to use with UniData. These files and templates reside in the udthome/work directory. you must restore them to their original state. unless you set up a test environment. or makeudapi command to set up a CallBasic or CALLC link with UniData. makeudt. see Administering UniData on UNIX. Before You Begin Before you try to set up links between UniData and C programs. • Sign on as root UniData supplies required files and templates needed to link the C program or function with UniData. • Before you link a C program for CALLC When you upgrade from an earlier release. Developing UniBasic Applications 217 . If these files have been changed. review the following tips. the wrong version could reside in udthome/work.Linking C Programs (UNIX Only) Linking C Programs (UNIX Only) The information in this section applies to the UNIX operating system only. • Before you link a C program for CallBasic Determine whether someone has previously modified the executable files in udthome/work in an effort to link C programs to your UniData executable. If someone installing or upgrading UniData chose not to overlay this file. If you use Windows NT or Windows 2000. However. UniData asks whether you want to overlay the cfuncdef file. • Set up a test environment You can set up an alternate test environment with a separate udt to use to test linked programs so you do not disrupt the work of others. You can copy the files to another directory temporarily to work on them. see “Linking C Programs (Windows NT or Windows 2000 Only)” later in this chapter. see “If This Is Not the First Time” later in this chapter. they must reside in udthome/work before you run the make. to which only root has read or write access.

and udtbin. (A base compiler is not sufficient. such as /usr/ud52/work. such as udthome/work.Maintaining Data in Files.” • Define environment variables The following environment variables must be defined: udthome. rather than using an environment variable. You must have the following components to use the CallBasic API: • Development environment Your system must have a full software development kit. 218 Developing UniBasic Applications . You will use this makefile as a template to build your application with UniData linked into it.mk is installed into the directory udthome/work. the file callbas. • Function definitions and makefiles When you install UniData. For information about setting up environment variables.) You also will need network libraries if you are using NFA. udtlib. • Regarding triggers You can call a C function from a UniBasic trigger subroutine. • C program You need to code and compile the C application that calls UniBasic.Linking Programs with UniData • Provide absolute path Any time you specify a path in a file. see Administering UniData on UNIX. Tip Consult your host operating system documentation and your hardware vendor if you have questions about your C development environment. you must specify the absolute path.Chapter 8 . see “Chapter 4 . For information about UniData triggers.

1. 3. Guidelines for Writing C Programs You might find the following guidelines helpful when writing the C program. Tip To save time and frustration. Write the C program. Procedure Summary Here is a summary of the steps you must follow to link a C program with UniData so that it can be called by a UniBasic program: 1. 5. such as U_unit and U_errout. Write and compile the UniBasic subroutine. Developing UniBasic Applications 219 . 2. Compile the C program. Execute the UniBasic subroutine. Write the C Program The first step in creating a C function that you will call from a UniBasic program is to write the C program with the standard compiler for your platform and operating system. Tell UniData about the C program (in cfuncdef_user). read “Before You Begin” earlier in this chapter. UniData uses U_ as an identifier for variable names and functions. Rebuild the UniData executable (using makeudt or makeudapi). 4. • Naming Variables Avoid naming variables or functions with the prefix U and an underscore (U_).Linking C Programs (UNIX Only) Calling a C Function from UniBasic with CALLC Follow the procedure described in this section to link a C function with UniData so that it can be called by a UniBasic program. 6.

The U_preprint function refreshes the screen. and set the returning string length (for example. Syntax: • U_preprint pattern. see the “Data Types for UNIX C Definition” table later in this chapter. • Passing Binary Data Include the bstring header file to pass a binary string to or from a C program. U_errout has the same syntax as U_preprint. U_erroutoutput goes to errout whereas U_preprint output goes to stdout. To do this.value). see the “Data Types for UNIX C Definition” table later in this chapter.Chapter 8 . 220 Developing UniBasic Applications . A sample C program is provided in “Passing bstring-Type Data” later in this chapter. use the UniBasic C function U_preprint instead of the C function printf. retbuf->len and out->len). • Returning Arguments The maximum number of bytes allowed in a function return is 256.. If you increase the size of a variable of data type bstring.arg1.arg2."error message from the routine.h. except the variable U_unit is replaced by 0. • Displaying Error Messages To display error messages. For more information. Each argument is limited to 255 characters. especially when that data could contain imbedded ASCII character 0 (which C interprets as a line terminator). Include the bstring header to pass binary data. Syntax: • • U_errout(0. which contains the definition of bstring. the C function must include the header file callc_bstr. value is %d". Printing – To maintain screen integrity and I/O redirection. For more information. use the UniBasic C function U_errout. This function follows syntax similar to printf. you must free the original memory assignment and reallocate it and reassign the length to avoid a memory leak.Linking Programs with UniData • Passing Arguments You cannot pass more than 22 arguments. enabling the C subroutine to properly manage screen I/O..

• Ending the C Program Do not use exit to end the C program. Program Example char *c_example(envar) char *envar."%s".getenv(envar)). return(buf). and then terminates the C program. { char *getenv(). ."message from the routine. C Program Example The following C function (c_example) emulates the UniBasic GETENV function. value is %d". static char buf[100]. which performs various cleanup tasks. sprintf (buf. char *pathlist. . Both retrieve the value of the specified UNIX environment variable using the UNIX getenv system call. /* return string to UniData } */ Developing UniBasic Applications 221 . U_preprint(U_unit.Linking C Programs (UNIX Only) • For example: Program Example extern int U_unit.value). . use U_done. Instead.

Copy the object code to the udthome/work directory: Program Example $ cp c_example. Compile the C Program A. 222 Developing UniBasic Applications . Verify the following before you proceed to the next step: • • The C program does not contain the main() function. For our example. you enter the following commands at the UNIX shell prompt: Screen Example $ cc -c c_example. The C program compiles cleanly. For assistance. Use the UNIX cc command with the -c option to produce the object code.c B.o $UDTHOME/work Permissions To place the program in udthome/work. you must have write permission to that directory. see your system administrator.Linking Programs with UniData 2.Chapter 8 .

o. Look at cfuncdef. along with the makefile (c_example. see the template in “File Examples” later in this chapter.Linking C Programs (UNIX Only) 3. cfuncdef could contain reference to these programs. After making sure that cfuncdef is free of references to other C programs. To proceed. if someone has previously linked C programs to UniData for CALLC. If the person installing UniData Release 5. and the C functions that the makeudt or makeudapi utility uses (funchead. placed in udthome/work at installation. Tell UniData about the C Program A. Check for required files in udthome/work. you could have the wrong version. B. C. Create cfuncdef_user. It could contain reference to site-specific libraries. Also.o).o interfunc.o callcf. For an example of an “empty” cfuncdef file.2 or upgrading from an earlier version chose not to overlay this file. Some earlier releases of UniData included some UniData functions in cfuncdef. make a copy of it. the C program must reside in the udthome/work directory. and call it cfuncdef_user. must not refer to any UniData or sitespecific C programs. This file. and efs_init. The file should contain the following three lines: • • • $$FUN (you put the C function definition here) $$OBJ (you put the object file here) $$LIB (you put the library path here if the C function is not stored in udtlib) Developing UniBasic Applications 223 .mk in this example) and the function definition file (cfuncdef).

The data type of the return value. The following table lists the function definition arguments. and a comma separates multiple arguments. Program Example /* this is a test for adding a C function to the*/ /* Runtime version of UniData. each on a separate line. The function definition line follows $$FUN. Argument fun_name Description The name of the C program as it will be called from UniBasic programs. cfuncdef Function Definition Value in Example c_example rtn_data_type string 224 Developing UniBasic Applications . Syntax: fun_name:rtn_data_type:num_arg:arg_data_type A colon separates each element.o $$LIB /* library comes here */ D.o file comes here */ /usr/ud51/work/c_example. The next few steps refer to this example.arg2. */ /* C function declaration format: function-name:return-type:number-of-argument:arg1.argn */ $$FUN /* beginning of C function */ c_example:string:1:string $$OBJ /* object files or .. You can enter more than one function definition..Linking Programs with UniData cfuncdef_user File Example The following example shows a version of the cfuncdef_user file that has been modified to set up the function c_example on a Hewlett Packard computer.Chapter 8 . Add the function definition to cfuncdef_user..

. A 32-bit signed long word (same as int).. A 32-bit signed long word. Data Types for UNIX C Definition Developing UniBasic Applications 225 . For example: . var = SPACE(64000) CALLC(var.. 1 Value in Example string cfuncdef Function Definition (continued) The following table lists valid data types for arguments and return values. A pointer to a character string terminated by NULL (0) in a 34-K buffer..Linking C Programs (UNIX Only) Argument num_arg arg_data_type Description The number of arguments. A 16-bit signed long word. The buffer size cannot be changed. A signed byte. Data Type int short long double float char string Description An integer. A 64-bit floating point value. The data type of the arguments. you can allocate memory for the variable in a UniBasic program before passing it in the parameter to the C program. A 32-bit floating point value. Although memory reallocation is not supported.) The variable now has been allocated a size of 64 KB.

The function in the example does not link any alternate libraries. but instead list the absolute path.To prevent a memory leak. Defined as: typedef struct ( char *str. enter the library path on the line that follows $$LIB. Do not use the environment variable (udtlib) in the path name. Enter the object code path and file name on the line that follows $$OBJ. Warning .Linking Programs with UniData Data Type bstring Description A pointer to a structure (struc) in a buffer that is a minimum of 34 KB in size. Add the library path to cfuncdef_user. you can pass data contain the NULL (0) character by using bstring. If your function does not reside in udtlib. preceded by -L. You can put it in any directory as long as you specify the absolute path here. F. If the string is changed. Data Types for UNIX C Definition (continued) E. 226 Developing UniBasic Applications . int len } bstring. pointer A 32-bit signed long word. Add the object code path and file name.Chapter 8 . you must free the original buffer assignment before reallocating it. You can reallocate this buffer. Also. the length must also be reassigned.

Tip If users are logged in to UniData. For information about error messages and common problems you could encounter during this process. Warning If you are upgrading from a version of UniData before Release 3. see “Troubleshooting CALLC” later in this chapter. Use the command that is appropriate for your situation to build the executable. the makeudt or makeudapi utility might not finish because it might not be able to overwrite the production udt or udapi_slave. The makeudapi command also builds a new UniData executable (udapi_slave) with links to C programs so that they are accessible through InterCall. and makeudapi” in this chapter. It is best to be logged in as root to execute makeudt or makeudapi because you must have write access to udthome/work. UniObjects. Also. makeudt.mk to create the file new.3 version of the file. These utilities use cfuncdef_user and base. If you use a pre-3.Linking C Programs (UNIX Only) 4. move the new executable to udtbin. makeudt or makeudapi will fail. you will need to install the makefile for Release 5. as in the following examples: udtbin/makeudt or udtbin/makeudapi.mk. If an error message displays indicating an unsuccessful completion. you must be in the udthome/work directory. when UniData is no longer busy.3. For more information about these utilities.2 because the format for this file has changed more than once in subsequent releases. but execute the utility from udtbin. Later on. see “More on make. makeudt Syntax: • makeudt [-n nfa] Developing UniBasic Applications 227 . Rebuild the UniData Executable The system-level makeudt command builds a new UniData executable (udt). you need to locate the new udt or udapi_slave executable in the udthome/work directory. or UniObjects for Java.

you will write the UniBasic program that uses the UniBasic CALLC function to call the C function. makeudapi Syntax: • makeudapi For more information about using the makeudapi utility. Next. and you do not use the -n nfa option. Returns the value of the environment variable requested in the prompt. Write the UniBasic program. 3.Linking Programs with UniData The following table describes each parameter of the syntax. see Administering UniData on UNIX. UniBasic Program Example In the following example. makeudt Parameters For more information about using the makeudt utility.Chapter 8 . makeudt fails. 5. Write and Compile the UniBasic Program A. If your environment does not include these. 2. Prompts for the name of the environment variable for which to display the value. 228 Developing UniBasic Applications . Calls the C program c_example you created. Parameter -n nfa Description Use this option only if you are not using UniData OFS/NFA. This option uses “dummy” libraries rather than network libraries required by NFA. the UniBasic program CDEMO performs the following tasks: 1. see Administering UniData on UNIX. Software development environments may or may not include the network libraries.

The following example demonstrates running the UniBasic program CDEMO: Screen Example :RUN BP CDEMO Enter an environment variable name (such as PATH or TERM) Developing UniBasic Applications 229 .Creating and Running a Program. see “Chapter 3 . For instructions about compiling and cataloging UniBasic programs.Linking C Programs (UNIX Only) Program Example * CDEMO * PROMPT '' PRINT 'Enter an environment variable (such as PATH or TERM)': INPUT VARNAME EVAL = CALLC c_example(VARNAME) PRINT PRINT 'Value of ":VARNAME:" is ':EVAL PRINT STOP END B. Execute the UniBasic Program Execute the UniBasic program using the UniData ECL RUN command. Compile the UniBasic program. as in the following example. Enter the BASIC command at the ECL prompt.” Screen Example :BASIC BP CDEMO 6.

the size of the variable passed by the UniBasic program is changed. and reassigns a buffer of adequate size. then passes this length to the C program (see length in the CALLC statement): Program Example PROGRAM trycallc * * Input a length to indicate that the length of the 2nd IO string * and bstring will be changed in C routine. the C program checks the size of the string to be passed back. however. the user enters TERM. UniData assigns a 34-KB buffer to it.Chapter 8 . The program calls the C function that determines the value of the environmental variable and returns it to the UniBasic program. Notice that the original bstring passed by the UniBasic program is shorter than the minimum buffer size of 34 KB. frees up the original 34-KB allocation.Linking Programs with UniData To continue the example. To avoid a memory leak resulting from assigning a larger buffer. which displays the value. Therefore. Within the C program. Screen Example ?TERM Value of TERM is vt100 Passing bstring-Type Data This example demonstrates passing bstring-type data. The following UniBasic program prompts the user for the length of buffer to assign (see length in the INPUT statement). * PRINT "Input length of new IO strings ": INPUT length <— INPUT statement instr = "THE FIRST INPUT STRING" iostr1 = "THE FIRST IO STRING" iostr2 = "THE SECOND IO STRING" bstring = "THE BSTRING” PRINT "Before calling C function str_arg()" 230 Developing UniBasic Applications .

instr. read only */ char *IOstr1. The buffer size assigned to the arguments IOstr2 and bstring are tested. int str_arg(len. InStr.h> #include <string. /* an IO string. Because IOstr2 is 1KB in size. iostr1. length of which is less than 34K */ char *IOstr2. If either is greater than 34KB.Linking C Programs (UNIX Only) PRINT CALLC str_arg(length.20] The following C program is called by the CALLC statement in the preceding UniBasic program. */ bstring *Bstr. *length of the 2nd IO string and Bstring after updating */ char *InStr. Bstr) int len. * an IO string whose length will be greater * than 34K. Program Example #include <stdio.h> #include "/usr/ud51/include/callc_bstr. IOstr1. the memory allocation is freed and reallocated before passing it to the UniBasic program. bstring) PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT PRINT <— CALLC statement "After called C function str_arg()" "The "The "The "The "The "The 1st input string 1st IO string length of the 2nd IO string length of the bstring is 1st 20 char of the 2nd string 1st 20 char of the bstring is >> >> >> >> >> >> ":instr ":iostr1 ":LEN(iostr2) ":LEN(bstring) ":iostr2[1.h" #define ONEK 1024 extern int U_unit. IOstr2. the memory allocation for that variable must be freed and reallocated. /* an input string.20] ":bstring[1. /* an IO bstring struct pointer */ { Developing UniBasic Applications 231 . iostr2.

10). the buffer 232 Developing UniBasic Applications . 'b'. IOstr2). 100). 'a'. (%d)\n". memcpy(IOstr2. memsize = (memsize > 34*ONEK ? memsize : 34*ONEK). and memory reallocation * is supported. "The 2nd IO string U_preprint(U_unit. IOstr1).Chapter 8 . 10). } /* * For bstring data.) */ strcpy(IOstr1. InStr). /* * For an IO string. (%s)\n". "Length of the bstring (%s)\n". "The 1st IO string U_preprint(U_unit. len *= ONEK. } else { /* no memory reallocation is allowed here */ memset(IOstr2. "The 1st IO string is changed"). /* * What the input strings are */ U_preprint(U_unit. Bstr->str). memcpy(IOstr2. (%s)\n". (%s)\n". (Assign * a long string to the variable as * a work around if the size is known.Linking Programs with UniData char int buf1[30]. the initial memory size is the * same as for string data. "len < 34K ". len). * Allocate memory in the UniBasic program. IOstr2[len] = '\0'. if ( len < memsize ) { memset(IOstr2. IOstr2[30*ONEK] = '\0'. Bstr->len). memsize = strlen(IOstr2). To avoid a memory leak. memsize. Memory reallocation * is not supported for string-type parameters. "len > 34K ". "The 1st input string U_preprint(U_unit. "The binary string U_preprint(U_unit. buf2[30]. the memory size is either 34 KB * or the length of the original string in the basic * program.

Bstr->str. U_preprint(U_unit. (%s)\n". Bstr->len = len. memcpy(Bstr->str. 'c'. "len > 34K ". "len < 34K ". memsize = (memsize > 34*ONEK ? memsize : 34*ONEK). buf1). memset(Bstr->str. len). IOstr2. } /* * print out changed strings */ memcpy(buf1. Bstr->len). IOstr1). 10). U_preprint(U_unit. U_preprint(U_unit. 'd'. memcpy(Bstr->str. 10). */ memsize = Bstr->len. memcpy(buf2. if ( len < memsize ) { Bstr->len = len. memset(Bstr->str. 20). return 0.strlen(IOstr2)). } "\nAfter modification:\n"). (%d)\n". (%d)\n". buf1[20] = buf2[20] = '\0'. "The 1st IO string "Length of the 2nd IO string "Length of the bstring "The 1st 20 char of IO str2 "The 1st 20 char of Bstring (%s)\n". (%s)\n". Developing UniBasic Applications 233 .Linking C Programs (UNIX Only) * size for the bstring needs to be freed * before allocating a larger buffer. U_preprint(U_unit. buf2). U_preprint(U_unit. } else { /* memory re-allocation is allowed here */ free(Bstr->str). U_preprint(U_unit. 20). len). Bstr->str = malloc(len).

..bstring <— argument definitions $$OBJ /* *.string. Notice that the user responded to the prompt of length for the output string with a number less than 34.string. Screen Example :run BP trycallc Input length of new IO strings ?30 Before calling C function str_arg() The 1st input string The 1st IO string The 2nd IO string The binary string Length of the bstring (THE (THE (THE (THE (11) FIRST INPUT STRING) FIRST IO STRING) SECOND IO STRING) BSTRING) After modification: The 1st IO string Length of the 2nd IO string Length of the bstring The 1st 20 char of IO str2 The 1st 20 char of Bstring (The 1st IO string is changed) (30720) (30720) (len < 34K aaaaaaaaaa) (len < 34K cccccccccc) 234 Developing UniBasic Applications .arg2...o <— function definition $$LIB /* library comes here The following shows the output produced by executing the UniBasic program trycallc after linking the C program str_arg with UniData. */ /* C function declaration format: * function-name:return-type:number-of-argument:arg1.Chapter 8 .string.o come here */ str_arg.argn */ $$FUN /* beginning of C function */ str_arg:int:5:int. this will require that the memory allocation for IOstr2 be freed and reallocated to pass back a variable of 1 KB in size.Linking Programs with UniData The following cfuncdef_user file contains the function and argument definitions needed to link the preceding C program with UniData: Screen Example /* comment lines come here.

Linking C Programs (UNIX Only) After called C function str_arg() The 1st input string The 1st IO string The length of the 2nd IO string The length of the bstring is The 1st 20 char of the 2nd string The 1st 20 char of the bstring is Enter <New line> to continue. and catalog the UniBasic subroutine.. Write. read “Before You Begin” earlier in this chapter. 3. Both UniBasic and UniData are invisible to the user. Create a makefile. you can write an application in C to access the UniData database. CallBasic lets you combine the power of C with the advantages offered by UniBasic subroutines. 4. 2. Tip To save time and frustration. or you can retrofit existing C applications to incorporate UniBasic subroutines to access the UniData database.. Developing UniBasic Applications 235 . your UniBasic routine is called from a C program that is executed from the operating system prompt. Compile and link the C program. compile. Write the C program. When you use CallBasic. For example. Procedure Summary Here is a summary of the steps you must follow to link a C program with UniData so that it will call a UniBasic subroutine: 1. >> >> >> >> >> >> THE FIRST INPUT STRING The 1st IO string is changed 30720 30720 len < 34K aaaaaaaaaa len < 34K cccccccccc Calling a UniBasic Subroutine from a C Program with CallBasic You can link a C program with UniData so that it executes a UniBasic subroutine by using the UniData CallBasic application programming interface (API).

1. because the subroutine must return control to the C program. Write. (A base compiler is not sufficient). TCP/IP) if you are using NFA. Tip Consult your host operating system documentation and your hardware vendor if you have questions about your C development environment. You will use this makefile as a template to build your application with UniData linked into it. You cannot use a UniBasic mainline program. • Function definitions and makefiles When you install UniData. Compile. Write a UniBasic subroutine that includes a RETURN statement. the file callbas. 236 Developing UniBasic Applications . The Procedure You are now ready to link a C program that will call a UniBasic subroutine. • C programs You will need to code and compile the C application that calls UniBasic. and Catalog the UniBasic Subroutine Perform the following steps to create a UniBasic subroutine that will be called from a C program: A. Execute the C program.Chapter 8 .mk is installed in the udthome/work directory. Requirements You must have the following components to use the CallBasic API: • Development environment Your system must have a full software development kit. You also will need network libraries (for example.Linking Programs with UniData 5. Write the UniBasic subroutine.

For more information about this command. The remaining arguments. Program Example SUBROUTINE EXAMPLE(RTNVAL. Use the ECL command CATALOG to catalog the UniBasic subroutine. Compile the UniBasic subroutine. Catalog the UniBasic subroutine.Creating and Running a Program. Use the ECL command BASIC to compile the UniBasic subroutine. ARG2) PRINT ARG1 PRINT ARG2 RTNVAL = "val1" RETURN END B. Here we catalog the EXAMPLE subroutine: Screen Example :CATALOG BP EXAMPLE Developing UniBasic Applications 237 . see “Chapter 3 . ARG1 and ARG2.” or the UniData Commands Reference.Linking C Programs (UNIX Only) For example. In this example. pass data from the C program to the EXAMPLE subroutine. ARG1. we compile the EXAMPLE subroutine: Screen Example :BASIC BP EXAMPLE C. the following subroutine (EXAMPLE) returns a value in RTNVAL.

char arg1[BUFSIZ]. a transaction started in a UniBasic program executed from ECL must complete before the process returns to ECL.Linking Programs with UniData 2.c */ #include <stdio.Chapter 8 . char *rtn.h" #endif main() { /* declare variables */ char arg0[BUFSIZ]. Sample Program The following example (mypgm. Write the C Program Write the C program that calls your UniBasic subroutine. char *args[2].c) illustrates a C program that calls a UniBasic subroutine: Program Example /* call a UniBasic subroutine EXAMPLE from mypgm.h> #include <setjmp. Note A transaction started in a UniBasic subroutine invoked by a C program can continue into another subroutine called by the same C program: udtcallbasic_init( ) U_callbas(subroutineA) * this subroutine starts a transaction U_callbas(subroutineB) * this subroutine commits the transaction udtcallbasic_done( ) However. int sts.h> #include "/usr/ud51/include/share. /* initialize UniData environment */ 238 Developing UniBasic Applications .

free(rtn). /* assign arguments to be passed to the subroutine */ strcpy(arg0. } Include Required Functions Three functions must be included in the C program: udtcallbasic_init. args[0] = arg0. args[1] = arg1. Required Functions: Start UniData Your C program must execute this function once and only once. and udtcallbasic_done. "EXAMPLE".0). sts). Developing UniBasic Applications 239 . rtn). sat). "2ND ARGUMENT"). 2. "1ST ARGUMENT"). strcpy(arg1. sat.Linking C Programs (UNIX Only) /* first. which closes files and the UniData session. which calls the UniBasic subroutine. U_SET_JMP(jmpret. which initializes UniData. if (sts = = 0){ printf("Return: %s\n". exit(-1). } printf("Status: %d\n". starting a udt process to execute the CallBasic subroutine call. if (!jmpret) { udtcallbasic_done(1). } udtcallbasic_init(0. args). U_callbas. The C function udtcallbasic_init initializes the UniData environment. set up an error handler */ int jmpret. /* call the subroutine */ sts = U_callbas(&rtn. /* shut down UniData environment */ udtcallbasic_done(sts).

value2) int — value1.Chapter 8 . your program could cause a core dump. If you attempt to call it more than once. Warning You can call udtcallbasic_init only once in your program. 240 Developing UniBasic Applications . Note You must initialize the UniData environment with udtcallbasic_init before calling a UniBasic subroutine.Linking Programs with UniData Syntax: udtcallbasic_init(value1. int — value2.

udtcallbasic_init Arguments Required Functions: Call the UniBasic Subroutine This function calls a UniBasic subroutine.When UDT. • 0400 – U_UDT_SERVER – Sets a flag that. and sets a pointer to the return value. Valid parameters include the following: • 01 – U_PHANTOM – This parameter behaves like the ECL PHANTOM command. Note . argc. when a fatal error occurs. returns control to the calling UniBasic program rather than aborting (same as UDT. passes arguments. argv) Developing UniBasic Applications 241 .OPTION 41 is used. errors are returned in EXECUTE instead of longjmp. progname. The default is 0. Syntax: int U_callbas (rtn. Parameters value1 Description Names the type of UniData process that will be started. value2 Enter one of the following values to clear or not clear the screen when CALLBASIC is initialized: • 0 – Do not clear the screen. • 1 – Clear the screen. it sends UniData output to a file instead of the terminal screen. • 0100 – U_REDIRECT – Use this parameter to override the terminal attributes that UniData sets by default. You can execute this function numerous times in your C application. each time you want to call a UniBasic subroutine.h file in the /usr/ud52/include directory.Linking C Programs (UNIX Only) The following table describes each parameter of the syntax. Values for each parameter are in the share.OPTIONS 41).

Linking Programs with UniData The following table describes each parameter of the syntax. The number of arguments passed to the subroutine. U_callbas Function Arguments Note UniData allocates memory every time you execute U_callbas. Parameter rtn Data Type char Description The address of the pointer to the value returned from the UniBasic subroutine. The address of an array of pointers to arguments. you must free the storage space pointed to by the first argument or the memory will be unavailable to the system. You cannot use these arguments to pass anything to the subroutine. you cannot use this argument to pass anything to the subroutine. 242 Developing UniBasic Applications . However. you must free memory only if the function completes successfully. • -1 – A UniBasic program error occurred in the RUN process. you are out of memory. In the C program. • -2 – A fatal error occurred or a STOP was encountered in a UniBasic program. progname argc argv char int char The pointer to the name of the subroutine. The return values include the following: • 0 – The function executed successfully.Chapter 8 . or the system is performing a CHAIN.

You must also include this function in any error exits in your application that could be taken after udtcallbasic_init. Developing UniBasic Applications 243 .Linking C Programs (UNIX Only) Required Functions: Close Files and UniData This function clears all UniData-related temporary files and other resources and ends the interface between the C application and UniData. You must execute this function once in your C application. Enter the library path. You might want to give the copy a name similar to that of your C function to make it easier to remember later which makefile was used to link which C function. A.mk file from udthome/work to your work directory. if you find a line like the following in the file. but it is currently not interpreted. 3. status is returned. A sample of this file is displayed in “File Examples” later in this chapter. Here is an example of a libpath line: libpath = -L/usr/ud52/lib Also.mk. B. You will need to make a backup copy of this file in case you need to start this process over. Copy the callbas. Syntax: udtcallbasic_done(status) int status. Change the libpath in your makefile file to your udthome/lib directory. using the absolute path instead of udthome. Copy callbas. remove it: libpath = -L$$UDTLIB This ensures that the make process will execute regardless of the definition of the environment variable udtlib. Create a makefile Perform the following steps to create or modify a makefile to specify to UniData the linked program name and location.

Modify the executable name again in a line that looks like this before modification: callbas: $(NEWOBJS) $OBJS) To link our sample C program. Compile and Link the C Program Note Before you execute make. For more instructions.Linking Programs with UniData C. It looks like this: NEWOBJS = callbas. Find NEWOBJS. see “If This Is Not the First Time” later in this chapter. Change callbas.o E. you MUST restore the files modified by this utility. Look for the statement that defines NEWOBJS. see “If This Is Not the First Time” later in this chapter. NEWOBJS must refer to your object file. this line must be: c_example: $(NEWOBJS) $(OBJS) 4. you need to reinitialize the files UniData uses to create the link. For more information. If they have.Chapter 8 . Because our sample C program is c_example. Enter object name again.c. D.o: NEWOBJS = c_example. the object name is c_example. you need to know if anyone has executed the UniData system-level command makeudt or makeudapi since UniData was installed or upgraded.o.o Tip Does your NEWOBJS line differ from this? If it refers to a previously linked C function. 244 Developing UniBasic Applications .

mk. Developing UniBasic Applications 245 ..c into an executable named c_example and links the executable to UniData: Screen Example %make -f c_example. and your path..] If the UniBasic subroutine is globally cataloged. you can execute the C program from any UniData account or directory. see Administering UniData on UNIX. The -f option tells UNIX to use the file specified in makefile_name rather than the default. Execute the C Program Run the C program from the operating system prompt.Linking C Programs (UNIX Only) From the UNIX prompt. callbas.mk 5. If the UniBasic subroutine is locally or directly cataloged. This is the account from which the make utility was executed or one in which you manually create a VOC record for the C program. the following command compiles the C program named c_example. enter the make command to compile the C program and link it to UniData. udtbin. Syntax: [path]executable_name [arg1] [args2. You must set udthome. you must execute the C program in a UniData account that has an entry for the program in the VOC file. For information about setting these environment variables. make Syntax: make -f makefile_name For example.

The instructions in the preceding section (for CallBasic) direct the user to copy cfuncdef to cfuncdef_user. 246 Developing UniBasic Applications .Linking Programs with UniData The following command invokes the program named c_example from the /usr/ud52/work directory: Screen Example %/usr/ud52/work/c_example The sample C program. If you do not find it. Find cfuncdef_user Look in the udthome/work directory for a file named cfuncdef_user. produces the following output: Screen Example 1ST ARGUMENT 2ND ARGUMENT Status: 0 Return: val1 If This Is Not the First Time Perform the following steps to reinitialize the files in udthome/work if someone has already linked C functions to UniData. Here is why: When UniData is installed. which calls the UniBasic program EXAMPLE.Chapter 8 . You need to perform this procedure before you try to execute the make. c_example. look for cfuncdef. the files required for the UNIX make utility to link C programs with UniData are provided in udthome/work. or makeudapi utility. makeudt. 1. then modify this template with information required by the UNIX make utility.

Look for Modifications If you have linked one or more C functions to UniData for the purpose of CALLC. Reinitialize Execute the UniData system-level commands genefs.. you need to reinitialize the files the UNIX make utility uses to create the link between C programs and UniData.o come here */ $$LIB /* library comes here */ 3. interfunc.. and other C functions used by the makeudt or makeudapi utility. cfuncdef or cfuncdef_user will contain references to C functions on the line that follows $$FUN.) 4. Take a Look Inside Use the UNIX more command to look at the contents.. (These are the other files placed in udthome/work when UniData is installed: funchead. Log In as root Before you proceed to the next step. 5. you must log in as root.arg2. It could also list site-specific libraries under $$LIB. */ /* C function declaration format: function-name:return-type:number-of-argument:arg1.c. and so forth. Developing UniBasic Applications 247 ..c. gencdef. and genfunc to update funchead.argn */ $$FUN /* beginning of C function */ $$OBJ /* *. interfunc. and object names in the line following $$OBJ. Does the file look like this template? Program Example /* this is a test for adding C function to the RUN Machine */ /* comment lines come here. If the file has been modified.Linking C Programs (UNIX Only) 2.

c funchead. from the UNIX prompt: Screen Example # $UDTBIN/genefs # $UDTBIN/gencdef # $UDTBIN/genfunc # ls -tl |pg total 26 -r--r--r-1 root -r--r--r-1 root -r--r--r-1 root -rw-rw-rw1 root -rw-rw-rw1 root -r--r--r-1 root -r--r--r-1 root -rw-rw-rw1 root -r--r--r-1 root -rw-rw-rw1 root sys sys sys sys sys sys sys sys sys sys 2735 738 760 97 422 1006 155 985 292 1424 Jun Jun Jun Jun Jun Jun Jun Jun Jun Jun 10 10 10 10 10 10 10 10 10 10 16:08 16:08 16:08 16:08 16:08 16:08 16:04 16:04 16:04 16:04 interfunc. return to the procedure for linking C programs with UniData.Chapter 8 . 248 Developing UniBasic Applications .Linking Programs with UniData Enter the following commands.mk Permissions You must be logged in as root to execute these commands.c ndef cdef efs_init. in the indicated order. and you must execute them in the order shown in the example. After you reinitialize.c efsdef callbas.mk cfuncdef base.c callcf.

mk file released with UniData.-a.mk Example Warning Do not copy the sample makefile onto your system. base.shared -lcurses -lsec = = -lud = -lndbm -lcl -lBSD -llicn = -lnfaclnt libs_clt = -lshare -ludsql -ludmach -lbasic -lret1 -lperf -lides -lpipe Developing UniBasic Applications 249 . The following example shows a base.mk file for UniData on an HP system: Screen Example # pg base. 99 # The System to Be Ported : HPUX10 # CC CFLAGS LDFLAGS OPTFLAGS DBFLAGS libpath addlib addlibpath odslib udlib licnlib = dclcnlib nfalib = dfslib = = cc = -q -z +ESsfc = -Wl.Linking C Programs (UNIX Only) File Examples The base. 11.archive = -O +Ovolatile = = -L/disk1/srcman/alpha/ud_51_990611_2025/bin/lib = -lm -Wl. makeudt or makeudapi will probably fail. If you do. and do not copy a makefile from another platform.-a.mk # # The Porting Date : Jun.mk file and the cfuncdef file are platform-specific. Always start with the base.

o callcf.o efs_init.o udt: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) $(NEWOBJS) $(NEWLIBS) $(libpath) -lapidummy $(libs_clt) $(addlibpath) $(addlib) -o $@ udapi_slave: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) $(NEWOBJS) $(NEWLIBS) $(libpath) -lapidummy -licapi $(libs_clt) -lunirpc $(addlibpath) $(addlib) -o $@ udtsvr: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) $(NEWOBJS) $(NEWLIBS) $(libpath) -lapidummy $(libs_svr) $(addlibpath) $(addlib) -o $@ udsrvd: unirpc_srv.o callcf.Chapter 8 .o $(OBJS) $(libpath) -lapidummy $(libs_srv) $(addlibpath) $(addlib) -o $@ uniapisvr: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) $(NEWOBJS) $(NEWLIBS) $(libpath) -lapisvr $(libs_clt) -lmsg $(udlib) $(addlibpath) $(addlib) \ 250 Developing UniBasic Applications .o interfunc.o UDOBJS = funchead.o interfunc.Linking Programs with UniData -lfunc -lndx $(dfslib) -lshm -lmglm -lglm -lulc -lcmn -llicn -ludus -lunix $(nfalib) $(odslib) libs_svr = -lnfasvr -lshare -ludsql -ludmach -lbasic -lret1 -lperf -lides -lpipe -lfunc -lndx $(dfslib) -lshm -lmglm -lglm -lulc -lcmn -llicn \ -ludus -lunix $(odslib) libs_srv = -lushare -lusql -lumach -lbasic -lret1 -lperf -lides -lpipe -lfunc -lndx -lshm -lmglm -lglm -lulc -lcmn -llicn -ludus -lunix -lunirpc $(nfalib) $(odslib) OBJS = funchead.o $(OBJS) $(CC) unirpc_srv.o efs_init.

*/ /* C function declaration format: function-name:return-type:number-of-argument:arg1. the wrong version could reside in udthome/work..Linking C Programs (UNIX Only) -o $@ .o: $(CC) $(CFLAGS) $(IDIR) $(OPTFLAGS) $(DBFLAGS) -c $< cfuncdef Example Some earlier releases of UniData included some UniData functions in cfuncdef..argn */ $$FUN /* beginning of C function */ $$OBJ /* *..o come here */ $$LIB /* library comes here */ Developing UniBasic Applications 251 .c. If someone upgraded UniData and chose not to overlay this file.arg2.. The cfuncdef file must look similar to the following example. which contains no reference to C functions: Screen Example # pg cfuncdef /* this is a test for adding C function to the RUN Machine */ /* comment lines come here.

Use the template provided in your udthome/work directory for the platform on which you are linking C programs with UniData.o interfunc. This example shows link options that might not be valid on some platforms.-a. Program Example # # # # The Porting Date : Dec.o newlibpath = newlibs = libpath = -L$$UDTLIB 252 Developing UniBasic Applications . 11.debug CC CFLAGS LDFLAGS OPTFLAGS DBFLAGS libpath addlib addlibpath odslib udlib licnlib dclcnlib nfalib dfslib = = = = = = = = = = = = = = cc -q -z +ESsfc -DNULL_OK -DSQLTP -DUDMS -DNEW_INTER -Wl. 96 The System to Be Ported : HPUX10.archive -g -L/disk2/srcman/alpha/ud_pkqa4/bin/lib -lm -Wl.o efs_init.o callcf.-a.mk template might look like.mk Example The following is an example of what the callbas.Linking Programs with UniData callbas. Note Do not copy this example.shared -lcurses -lud -lndbm -lcl -lBSD -llicn -lnfaclnt OBJS NEWOBJS = funchead.o = callbas.Chapter 8 .

o: $(CC) $(CFLAGS) $(IDIR) $(OPTFLAGS) $(DBFLAGS) -c $< bstring Definition File callc_bstr. which is located in /usr/ud52/include. especially when that data contains /0 (called NULL in C). which is interpreted by C as a line terminator.Linking C Programs (UNIX Only) libs = -lshare -ludsql -ludmach -lbasic -lperf -lret1 -lides -lpipe \ -lfunc -lndx $(dfslib) -lshm -lcmn $(licnlib) -ludus $(nfalib) \ $(odslib) $(udlib) callbas:$(NEWOBJS) $(OBJS) $(CC) $(LDFLAGS) $(NEWOBJS) $(OBJS) \ $(libpath) -lapidummy $(libs) $(newlibpath) $(newlibs) \ $(addlibpath) $(addlib) -o $@ . Screen Example typedef struct { char *str. Developing UniBasic Applications 253 .c. int len. Include this header in a C function when you need to pass binary data.h. } bstring. contains the definition of bstring.

c interfunc.c funchead. makeudt or makeudapi executes the following three functions: • • genefs – Needed for NFA (Network File Access) only.c 254 Developing UniBasic Applications . However. 1.o come here */ str_arg. Using one of these utilities forces udt or udapi_slave to be created in udtbin..c • genfunc – Uses the definitions in cdef to create the following UniData functions: callcf. if different from udtlib 2.c funchead. gencdef – Creates a definition file (called cdef) for the following UniData functions: callcf. makeudt.bstring $$OBJ /* *.c interfunc. and makeudapi The utilities make.Linking Programs with UniData More on make.string.string. or use makeudapi to create a new executable udapi_slave. the makeudt and makeudapi commands perform more operations than the make command performs. makeudt and makeudapi Use the makeudt utility to create a new executable udt. in udthome. First..$$FUN /* beginning of C function */ str_arg:int:5:int. makeudt or makeudapi reads cfuncef and cfuncdef_user to obtain the following information: . makeudt. and makeudapi create new UniData executables.o $$LIB /* library comes here */ /disk2/ud52/our_lib <— function and argument definitions <— C program object file name <— site-specific library path.Chapter 8 .string. Using information gained from cfuncdef and cfuncdef_user.

Next. into udtbin when all users are signed out of UniData. udt or udapi_slave. makeudt or makeudapi deletes the cdef file. udtbin/udapi_slave) with the new one. make By default. For more information. gencdef. change the output path for the targets from -o $@ to -o path. You must then copy the executable file. and genfunc. which it obtained from cfuncdef_user: NEWOBJS = str_arg.mk file to new. see the UNIX man page for make. it notifies you. Note makeudt or makeudapi always writes the udt or udapi_slave executable to udtbin. If UniData is executing when it tries to overwrite the file. The make utility performs functions similar to makeudt and makeudapi with the following exceptions: • • The make utility does not automatically execute the three functions genefs. makeudt or makeudapi copies the base. The make utility lets you place the udt or udapi_slave executable in any directory.mk if it already exists. To do so. Finally.o NEWLIBS =/disk2/ud52/our_lib 4.mk and writes the C program and library path. UniData overlays new. 5. Developing UniBasic Applications 255 . in the case of makeudapi.Linking C Programs (UNIX Only) 3. the makeudt or makeudapi utility makes a new UniData executable and replaces udtbin/udt (or.

udt: $(OBJS) <— udt target $(CC) $(LDFLAGS) $(OBJS) $(NEWOBJS) $(NEWLIBS) $(libpath) -lapidummy $(libs_clt) $(addlibpath) $(addlib) -o $@ <— change to -o path udapi_slave: $(OBJS) <— udapi_slave target $(CC) $(LDFLAGS) $(OBJS) $(NEWOBJS) $(NEWLIBS) $(libpath) -lapidummy -licapi $(libs_clt) -lunirpc $(addlibpath) $(addlib) -o $@ <—change to -o path udtsvr: $(OBJS) <— udtsvr target $(CC) $(LDFLAGS) $(OBJS) $(NEWOBJS) $(NEWLIBS) $(libpath) -lapidummy $(libs_svr) $(addlibpath) $(addlib) -o $@ <—change to -o path udsrvd: unirpc_srv.mk .svr target $(CC) $(LDFLAGS) $(OBJS) $(NEWOBJS) $(NEWLIBS) $(libpath) -lapisvr $(libs_clt) -lmsg $(udlib) $(addlibpath) $(addlib) \ -o $@ <—change to -o path 256 Developing UniBasic Applications .o $(OBJS) $(libpath) -lapidummy $(libs_srv) $(addlibpath) $(addlib) -o $@ <— udsrvd target <—change to -o path uniapisvr: $(OBJS) <— uniapi..Linking Programs with UniData The following example shows a sample base.mk with the output destinations indicated: Screen Example # pg base..Chapter 8 .o $(OBJS) $(CC) unirpc_srv.

The new udt or udapi_slave has been built successfully. Check the libpath line in your makefile (the one you created by copying base. It should list the absolute path to the UniData libraries. Check the cfuncdef_user file.To find out where the makeudt or makeudapi utility thinks the libraries are. Problem makeudt or makeudapi aborts with a message indicating that UniData cannot find a library. For example: /usr/ccs/bin/ld: Can't find library for -lapidummy *** Error exit code 1 Solution Add the full path to the C program in the cfuncdef_user file that follows $$OBJ.mk). at the UNIX prompt. Troubleshooting Tips Developing UniBasic Applications 257 . at the UNIX prompt. Tip . This is not an error message. enter env. To find out the path for udtlib. makeudt displays the message: 'udt' is up to date or makeudapi displays the message: 'udapi_slave' is up to date makeudt or makeudapi aborts with an error message such as: unsatisfied symbol: str_arg where str_arg is the object file for your C program. This is stored in the environment variable udtlib. After completing. it lists the absolute path to udtlib.Linking C Programs (UNIX Only) Troubleshooting CALLC The following table contains solutions for some common problems encountered when you attempt to link C programs with UniData. References to libraries are incorrect. look in your makefile at the line beginning with “libpath = L”. If it is correct. Enter the full path to the object file for the C program after the line that contains $$OBJ. To find out the path for udtlib. enter env.

login or .profile file (if you have one). but UniData was unable to overlay the current executable.o: Permission denied Solution Unless the permissions have been changed for the directory udthome since UniData was installed. For more information. replace “udt” with “udapi_slave” in this example): mv: /disk1/ud52/bin/udt: cannot write: Text file busy Execute "mv udt /disk1/ud52/bin/udt" error. To prevent a memory leak.) The new executable has been created. With all users signed off.Linking Programs with UniData Problem When you try to copy your C program to udthome. see “Passing bstring-Type Data” earlier in this chapter. (Execute the command LISTUSER from the ECL prompt to determine who those users are. When you execute the UniBasic program that calls the C program you linked to UniData. Troubleshooting Tips (continued) 258 Developing UniBasic Applications . errno = 0 The udt make failed. you must free the original buffer assignment in the C program before reallocating it. Reset the environment variables udthome and udtbin. a memory leak results. If the string is changed. When you log in as root. you must be logged in as root to copy files into this directory. or see your system administrator or the UNIX man pages for instructions on setting PATH. makeudt or makeudapi aborts with an error message similar to the following (for makeudapi. see Administering UniData on UNIX or the UNIX man pages. UniData cannot find udthome or other files or directories. Reset your path as it is in your . For instructions. copy the udt or udapi_slave executable from udthome/work to udtbin. the length must also be reassigned.Chapter 8 . Users are currently executing UniData sessions. The setting for the UNIX environment variable PATH is lost. UNIX returns an error message like the following: cp: cannot create /disk1/ud52/str_arg.

Note For more information about CALLC. this means that you can upgrade your UniData version without the need to relink with external routines. either the caller or the DLL can be modified independently. The . developers create a DLL and then call that DLL from UniData. This facility lets separate pieces of code call one another without being permanently bound together. • Because linking between caller and DLL is accomplished at runtime.LIB (located in the UniData bin directory) and then make calls into the UniData DLL.LIB file supplies interface information. For CallBasic. see Administering UniData on Windows NT or Windows 2000. Dynamic Link Libraries (DLLs) and UniData Both the CALLC implementation and the CallBasic implementation in UniData for Windows NT or Windows 2000 use the Microsoft Windows Dynamic Link Library (DLL) facility. Linking between the separate pieces is accomplished at runtime (rather than compile time) through a Dynamic Link Library (DLL) interface. • For CALLC.Linking C Programs (Windows NT or Windows 2000 Only) Linking C Programs (Windows NT or Windows 2000 Only) The information in this section applies to the Windows NT or Windows 2000 operating system only. For UniData. Many software development environments for Windows can produce a DLL. Special VOC entries for each function that is called from a DLL communicate interface information to UniData. Both the CALLC interface (for calling external functions from UniData) and the CallBasic interface (calling UniData functions from external code) are implemented as DLLs. Developing UniBasic Applications 259 . A DLL is language-independent. and you can update your external DLL without the need to relink UniData. developers link their code with UniData.

Chapter 8 .Linking Programs with UniData Note For information about linking code into a DLL. This section describes the features of CALLC. both external functions and UniBasic programs. The examples are in the CALLC_DEMO folder located in the UniData demo account. CALLC Syntax and Data Types The UniBasic CALLC command has the following syntax: rtn = CALLC function(arg1. Note UniData includes a series of CALLC examples... Arguments to the external function. see the documentation for your software development environment. For more information.argn Description Return value from CALLC. Must be a valid data type. The name of the external function being called.argn) The following table lists the parameters of the syntax. see Administering UniData on Windows NT or Windows 2000.. CALLC Features and Components CALLC enables users to execute external functions from within a UniBasic application. Each must be a valid data type. Parameter rtn function arg1..arg2. The external functions can be written in C. C++.. CALLC Parameters 260 Developing UniBasic Applications ... or Borland Delphi.

Linking C Programs (Windows NT or Windows 2000 Only) Valid data types for return values and arguments are listed in the following table. A pointer to a 32-bit signed long word. A pointer to a null-terminated character string in a 34K buffer. An integer (32-bit signed). A pointer to a null-terminated character string. Data Type CHAR INT POINTER SHORT LONG STRING CHAR_PTR INT_PTR SHORT_PTR LONG_PTR DESCRIPTOR NONE A signed byte. and identifies the data types for its arguments and return value. A short (16-bit) integer. A pointer to a 16-bit integer. Developing UniBasic Applications 261 . Use for functions that do not return anything (for instance. A pointer to a string descriptor. A pointer to a 32-bit integer. A long integer. VOID). Data Types for CALLC Description E Type VOC Entries An E (executable) type VOC entry identifies the DLL for an external function being called using CALLC. A 32-bit signed long word.

Chapter 8 . You must specify E. or a name that can be located by way of the user’s path environment variable. Attributes of E Type VOC Entry The following screen shows the VOC entry for a function named callcpp_subr1: Attribute 3 Attribute 4 Attribute 5 Attributes 6 .dll callcpp_subr1 INT INT SHORT LONG CHAR STRING 262 Developing UniBasic Applications . The function name in the DLL. The data type for the return value. The location of the DLL. The VOC entry type. Attribute @ID Attribute 1 Attribute 2 Description The function name. a path relative to the current working directory.Linking Programs with UniData The following table defines the attributes required for an E type VOC entry. It must be a fully qualified path.n Screen Example :CT VOC callcpp_subr1 VOC: callcpp_subr1: E CALLC_DEMO\CALLC_CPP\callcpp_test. The data type for the first argument. The data types for the second through nth arguments.

The function is accessed from a dynamic linked library called callcpp_test. _cdecl calling convention. Note For C and C++. CALLC and UDT. You can use the Pascal convention in C or C++. The Pascal calling convention is the default for UniData. but can be critical because difficulties in the external functions can terminate udt sessions and potentially damage data. For Delphi. the default calling convention is _cdecl. the default calling convention is Pascal. Developing UniBasic Applications 263 . Separating environments is useful in any case.dll. and you can use the _cdecl convention in Delphi. see the documentation for your development environment. and returns an INT. Warning Informix recommends that you keep your development environment clearly separate from your production environment when developing a CALLC application. For information about choosing a calling convention.Linking C Programs (Windows NT or Windows 2000 Only) POINTER : Notice that this function expects six arguments.OPTIONS 88 One function can call another in a stack-based architecture by using one of the following conventions: • • Pascal calling convention.

or Delphi. The following table describes the behavior of CALLC commands with this option turned on or off. perform the following procedure. calling a function with the wrong UDT. terminating the UDT.OPTIONS 88 OFF (default) ON _cdecl Convention CALLC fails. Each argument is limited to 255 characters. terminating the udt. such as U_unit and U_errout. UniData uses U_ as an identifier for variable names and functions. 1. Write and Compile the External Function You can code the external function in C.Chapter 8 . • 264 Developing UniBasic Applications . UDT.OPTIONS 88 setting almost certainly terminates a udt session and could produce other undesirable results.OPTIONS 88 Warning As the preceding table indicates. Pascal Convention CALLC executes. Passing Arguments – You cannot pass more than 22 arguments. Guidelines for Writing C Functions You might find the following guidelines helpful when writing external functions in C: • Naming Variables – Avoid naming variables or functions with the prefix U and an underscore (U_). C++. CALLC executes. Using CALLC To call an external function from UniBasic.Linking Programs with UniData A new UDT option has been introduced into UniData for Windows NT or Windows 2000 to let CALLC function correctly with both _cdecl and Pascal calling conventions. UDT. CALLC fails.

arg1. or Borland Delphi. use U_done. U_errout() has the same syntax as U_preprint(). which performs various cleanup tasks."error message from the routine. Developing UniBasic Applications 265 . • Printing – To maintain screen integrity and I/O redirection. An EXPORTS statement. When ordinal values are specified.. use the UniData C function U_errout. they must be in the range 1 through n where n is the number of functions exported by the DLL.value). Code the function using C. Compile the function or functions and link the code into a DLL. Note The maximum number of bytes allowed in a function return is 256. Steps for Developing the Function A. Syntax: U_errout(0. except the variable U_unit is replaced by 0. The EXPORTS statement lists the names and optionally the ordinal values of the functions exported by the DLL. Instead.Linking C Programs (Windows NT or Windows 2000 Only) • Displaying Error Messages – To display error messages.. The U_preprint function refreshes the screen. • Ending the C Program – Do not use exit(). use the UniData C function U_preprint instead of the C function printf.arg2. U_errout() output goes to errout whereas U_preprint() output goes to stdout. Make certain that all the functions to be called from outside the program are exported in one of the following ways: • • A _declspec( dllexport ) statement. C++. Syntax: U_preprint pattern. and then causes the C program to terminate. B. This function follows syntax similar to printf(). enabling the C subroutine to properly manage screen I/O. value is %d".

cname. ptime.Chapter 8 . The UniData DLL is a 32-bit DLL. .OPTIONS 88 ON" PRINT "THE ID OF MY CURRENT UNIDATA PROCESS IS: ":@USERNO PRINT "PASSING THE ID TO THE C ROUTINE. 2. . The VOC entry contains information that enables UniData to locate and execute the called function. virt_mem) PRINT "THE C ROUTINE RETURNED: ":RESULT IF RESULT >= 0 THEN PRINT 266 Developing UniBasic Applications . You cannot call a 16-bit DLL from UniData. C. pname. After the DLL and the E type VOC entry are created. REQUIRED FOR C" PERFORM "UDT. PRINT "TURNING ON UDT. You will need to create an E type record in the VOC file in every UniData account where you will be calling the functions. and any DLLs you call by way of CALLC must also be 32-bit DLLs." pid = @USERNO pname = '' cname = '' ptime = '' virt_mem = 0 RESULT = CALLC ps(pid.Linking Programs with UniData Warning UniData for Windows NT or Windows 2000 takes full advantage of the Win32 environment. Create the VOC entry for every function that you can call from the DLL. the function can be accessed from UniBasic via CALLC.OPTIONS 88. Write and Compile the UniBasic Program The following example shows a portion of the sample UniBasic program that calls an external function named ps: Program Example .

your UniBasic routines are called from an external program. and UniBasic and UniData are invisible to the user. . Error handling is based on the RESULT from the C function rather than the STATUS of the CALLC statement. C++. Reminder The external function examples and UniBasic examples in this section are taken from the sample programs installed with the current release of UniData on Windows NT. For example. The statement can complete successfully (STATUS of 0) even if the C function has encountered an error. the calling convention for a C program is the _cdecl convention. and Delphi with the advantages offered by UniBasic subroutines." END PRINT "TURNING OFF UDT. When you use CallBasic.OPTIONS 88 must be turned on. END ELSE PRINT "AN ERROR HAS OCCURRED IN THE C ROUTINE. Therefore. CallBasic enables you to combine the power of programming languages such as C. UDT. you can write an application in C to access the UniData database. By default. or you can retrofit existing applications to incorporate UniBasic subroutines that let you access the database. Developing UniBasic Applications 267 . CallBasic Features and Components You can write programs that execute UniBasic subroutines by using the UniData CallBasic application programming interface (API). .Linking C Programs (Windows NT or Windows 2000 Only) .OPTIONS 88 OFF" STOP END Notice the following points: • • • The function name in the CALLC statement matches the name in the E type VOC entry.OPTIONS 88 BEFORE CLOSING" PERFORM "UDT.

see Administering UniData on Windows NT or Windows 2000.Chapter 8 . 268 Developing UniBasic Applications . int — value2. Warning You can call udtcallbasic_init only once in your program. The UniBasic subroutines are in the BP file in the UniData demo account. Syntax: udtcallbasic_init(value1. value2) int — value1. For more information. Functions of the CallBasic API udtcallbasic_init The C function udtcallbasic_init initializes the UniData environment. starting a udt process to execute the CallBasic subroutine call. your program could cause a core dump. The examples are in the CALLBASIC_DEMO folder located in the UniData demo account.Linking Programs with UniData Note UniData includes two CallBasic examples: both the external programs and the UniBasic subroutines. If you attempt to call it more than once. Note You must initialize the UniData environment with udtcallbasic_init before calling a UniBasic subroutine.

Valid parameters include the following: • 0 or 01 – U_PHANTOM – This parameter behaves like the ECL PHANTOM command.When UDT. returns control to the calling UniBasic program rather than aborting (same as UDT. argc. value2 Enter one of the following values to clear or not clear the screen when CALLBASIC is initialized: • 0 – Do not clear the screen • 1 – Clear the screen udtcallbasic_init Arguments U_callbas The C function U_callbas calls a UniBasic subroutine. progname. argv) Developing UniBasic Applications 269 . Syntax: int U_callbas (rtn. when a fatal error occurs. • 0100 – U_REDIRECT – Use this parameter to override the terminal attributes that UniData sets by default.OPTIONS 41). The default is 0. an error will be returned in EXECUTE instead of longjmp. passes arguments. except that it suppresses the “Phantom process started” and “Phantom process completed” messages. Parameters value1 Description Names the type of UniData process that will be started. it sends UniData output to a file instead of the terminal screen. and sets a pointer to the return value. • 010 – U_PHANTOMHUSH – This parameter behaves like U_PHANTOM. • 0400 – U_UDT_SERVER – Sets a flag that.Linking C Programs (Windows NT or Windows 2000 Only) The following table describes each parameter of the syntax. Note .OPTION 41 is used.

you are out of memory. The address of an array of pointers to arguments. However. • -2 – A fatal error occurred or a STOP was encountered in a UniBasic program.Chapter 8 . 270 Developing UniBasic Applications . • -1 – A UniBasic program error occurred in the RUN process.Linking Programs with UniData The following table describes each parameter of the syntax. U_callbas Function Arguments Note UniData allocates memory from the process heap every time you execute U_callbas. You must use the HeapFree API call to free the memory. Parameter rtn Data Type char Description The address of the buffer containing results from the UniBasic subroutine. you must free the memory pointed to by the first argument or the memory will be unavailable to the system. In the C program. you must free memory only if the function completes successfully. or the system is performing a CHAIN. progname argc argv char int char The pointer to the name of the subroutine. You cannot use this argument to pass anything to the subroutine. The number of arguments passed to the subroutine. You cannot use these arguments to pass anything to the subroutine. The return values include the following: • 0 – The function executed successfully.

• -1 – A UniBasic program error occurred in the RUN process. and returns a pointer to the results. arg[n] char int char The pointer to the name of the subroutine.. The number of arguments passed to the subroutine. argc. The user is responsible for allocating memory for the buffer to store results..Linking C Programs (Windows NT or Windows 2000 Only) udtcallbasic This function calls a UniBasic subroutine.. • -2 – A fatal error occurred or a STOP was encountered in a UniBasic program. arg[n]) The syntax of this function is required if the calling language is not C because the definition of the return buffer is consistent between the external program and the call with udtcallbasic. progname argc arg[0] . The following table describes each parameter of the syntax. progname. U_callbas Function Arguments Developing UniBasic Applications 271 . You can execute this function numerous times in your application when you want to call a UniBasic subroutine. passing arguments. The return values include the following: • 0 – The function executed successfully. You cannot use this argument to pass anything to the subroutine.. arg[0]. The pointers to arguments passed to the subroutine. you are out of memory. or the system is performing a CHAIN. Syntax: int udtcallbasic(rtn. Parameter rtn Data Type char Description The address of the pointer to the value returned from the UniBasic subroutine. ..

status is returned. Syntax: udtcallbasic_done(status) int status.LIB.Linking Programs with UniData udtcallbasic_done The UniData udtcallbasic_done C function clears all UniData-related temporary files and space.) UniData.LIB file – You must link your external program with the UniData.Chapter 8 . (A base compiler is not sufficient. and shuts down the UniData environment. Tip Consult your host operating system documentation and your hardware vendor if you have questions about your development environment. Interface information is contained in UniData. 272 Developing UniBasic Applications .LIB file when you build the executable. Using CallBasic You must have the following components to use the CallBasic API: • • Development environment – Your system should have a full software development kit. but it currently is not interpreted.

ARG1. Developing UniBasic Applications 273 .Linking C Programs (Windows NT or Windows 2000 Only) 1. ARG1 and ARG2. the following subroutine. pass data from the C program to the EXAMPLE subroutine. Write a UniBasic subroutine that includes a RETURN statement. see “Chapter 3 . Compile the UniBasic subroutine. Screen Example SUBROUTINE EXAMPLE(RETNVAL. For example. returns a value in RTNVAL.ARG2) PRINT "THE FIRST ARG IS ":ARG1 PRINT "THE SECOND ARG IS ":ARG2 RETNVAL="RETURN" RETURN END Note This subroutine is included in the BP file of the UniData demo account. The remaining arguments. For more information about this command. Compile. To compile the UniBasic subroutine. Write the UniBasic subroutine. and Catalog the UniBasic Subroutine Perform the following steps to create a UniBasic subroutine that will be called from an external program: A. B. use the ECL command BASIC. The subroutine must return control to the external program.Creating and Running a Program.” or the UniData Commands Reference. Write. EXAMPLE.

and Link the External Program For information about compiling the external program. Depending if you want to access the subroutine from one account or many. you can catalog it directly. In the following example. Catalog the UniBasic subroutine. do you want to overwrite?(y/n)Y : 2. we demonstrate globally cataloging the EXAMPLE subroutine: Screen Example :CATALOG BP EXAMPLE D:\UniData\sys\CTLG\e\EXAMPLE has been cataloged. Compile. locally. Make certain that: • • Your declarations for the UniBasic functions use the correct syntax for your programming language. Code. or globally.LIB file. use the ECL command CATALOG. 274 Developing UniBasic Applications . compilation finished : C.Linking Programs with UniData In the following example. see the documentation for your application development environment.Chapter 8 . To catalog the UniBasic subroutine. You link your code with the UniData. we compile the EXAMPLE subroutine: Screen Example :WHERE D:\UniData\demo :BASIC BP EXAMPLE Compiling Unibasic: BP\EXAMPLE in mode 'u'.

extern "C" int udtcallbasic(char *xbuf. You can execute this function numerous times in your program. extern "C" int U_callbas(char **xbuf. each time you want to call a UniBasic subroutine. udtcallbasic_done() – Your program must execute this function once. Use the CallBasic functions in the program as follows: • • udtcallbasic_init() – Your program must execute this function once and only once.). extern "C" int udtcallbasic_done(int k).h> #define NT #ifdef NT #include <windows. char *ybuf.Linking C Programs (Windows NT or Windows 2000 Only) Write the external program that calls your UniBasic subroutine. #endif /* CPP */ Developing UniBasic Applications 275 . extern int U_callbas()..c) shows a program that calls a UniBasic subroutine: Program Example #include <stdio.. You must also include this function in any error exits in your application that could be taken after udtcallbasic_init(). char *ybuf. char *arg. . each time you want to call a UniBasic subroutine. int i. extern int udtcallbasic_done(). int i. udtcallbasic() – Remember to allocate memory for the buffer to store results. char **zbuf). U_callbas() – You can execute this function numerous times in your program. The syntax for U_callbas is supported if the calling language is C.h> #endif /* NT */ /* Declare UniData callbasic functions */ #ifdef CPP /* for c++ */ extern "C" int udtcallbasic_init(int i. int j). • • The following example (callbasic_example1. #else /* for c */ extern int udtcallbasic_init().

#else free(rtn). rtn). if (sts == 0){ printf("Return value from UniBasic subroutine is %s\n". 2. "EXAMPLE"..0). char arg0[BUFSIZ]. 276 Developing UniBasic Applications .\n"). #ifdef NT /* Variable rtn returned by UniData come from the process heap. char *args[2]. */ HeapFree(GetProcessHeap(). /* Initialize the UniData environment */ udtcallbasic_init(0. args[1] = arg1. int sts.Linking Programs with UniData #ifdef NT extern int udtcallbasic(). #endif /* NT */ void main() { /* Declare variables */ char *rtn. rtn). strcpy(arg1.Chapter 8 .. 0. printf("\nExecuting UniBasic subroutine using udtcallbasic(). "Animals"). /* Call the UniBasic routine */ sts = U_callbas(&rtn.. char arg1[BUFSIZ]. "Plants"). args[0] = arg0.. /* Assign arguments for the UniBasic routine */ strcpy(arg0. printf("Executing UniBasic subroutine using U_callbas().\n"). not the C-Runtime They must be free'd with HeapFree(). args). #endif /* NT */ } #ifdef NT /* Allocate memory for return variable */ rtn = (char *)malloc(256).

lib /nologo /subsystem:console\ /incremental:no /pdb:"$(OUTDIR)/callbasic_example1.lib advapi\ 32.lib odbc32. "EXAMPLE". Developing UniBasic Applications 277 .lib oleaut32.lib comdlg32. */ sts = udtcallbasic(rtn. 2.lib\ odbccp32.lib\ /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib c:\u\ nidata\bin\unidata.lib /nologo /subsystem:console /machine:I386 LINK32_FLAGS=kernel32.lib a\ dvapi32.c shows linking with the UniData.lib odbc32.exe" : Reminder The sample program and makefile are included in the CALLBASIC_DEMO folder in your UniData demo account.lib c:\unidata\bin\unidata.Linking C Programs (Windows NT or Windows 2000 Only) /* Call the UniBasic subroutine using udtcallbasic.lib shell32. #endif /* NT */ /* Close everything properly */ udtcallbasic_done(sts).lib odbccp32.lib comdlg32.lib shell32. if (sts == 0){ printf("Return value from UniBasic subroutine is %s\n".lib\ advapi32. args[0]. } The following segment from the makefile for callbasic_example1.LIB file: Program Example LINK32=link.lib odbc32.exe # ADD BASE LINK32 kernel32.lib gdi32.lib user32.lib user32.pdb" /machine:I386\ /out:"$(OUTDIR)/callbasic_example1.lib uuid.lib winspool.lib shell32.lib gdi32.lib user32.lib ole32.lib ole32.lib gdi32.lib oleaut32. rtn).lib winspool.lib odbccp32.lib comdlg32.lib uuid.lib oleaut32. } free(rtn).lib winspool.lib ole32.lib uuid. args[1]).

THE FIRST ARG IS Plants THE SECOND ARG IS Animals Return value from UniBasic subroutine is RETURN Executing UniBasic subroutine using udtcallbasic(). 278 Developing UniBasic Applications ...Linking Programs with UniData 3. You do not need to be in the UniData account where the subroutine was written. Executing UniBasic subroutine using U_callbas(). your working directory must be a UniData account where the subroutine is cataloged. you can use CallBasic from any UniData account. THE FIRST ARG IS Plants THE SECOND ARG IS Animals Return value from UniBasic subroutine is RETURN : Reminder If your UniBasic subroutine is globally cataloged.. and you will need to be sure to specify the full path name of the executable.Chapter 8 . The following screen shows the results of executing the callbasic_example1 executable from the demo directory: Screen Example :!callbasic_example1 UniData is running under a temporary license! This license will expire in 6 days. or include its location in your PATH.. You can execute your routine from the MS-DOS Command prompt. Use the New Executable To run the new executable and call the UniBasic subroutine.

To learn more about creating new recoverable files or converting existing files. none of the operations within the transaction take place. After the transaction is initiated. TP works only with recoverable files or files associated with Journaling. Note RFS and Journaling are purchased separately from the bundled UniData RDBMS. you bind the operations by TRANSACTION START and TRANSACTION COMMIT statements.Chapter 9 . even in the event of a system failure. UniData ignores TP commands. For more information about these products. Developing UniBasic Applications 279 . see Using Journaling and Administering the Recoverable File System. UniData for Windows NT or Windows 2000 does not support transaction processing. Transaction processing (TP) combines a set of operations in a single logical function so that the database is maintained in a consistent state throughout an update. One of these products must be in use for transaction processing to work. If the transaction is unsuccessful.UniBasic Transaction Processing Note This chapter applies to UniData for UNIX systems only. To create a UniBasic transaction. Two UniData products support transaction processing: the Recoverable File System (RFS) and Journaling. UniData can recover the updated files. see Administering the Recoverable File System. In the absence of RFS or Journaling.

UniBasic Transaction Processing This chapter introduces the UniBasic transaction processing commands. see “Chapter 5 . “Appendix B .Chapter 9 .” 280 Developing UniBasic Applications . For information about using UniData locks to ensure database consistency.Using UniData Locks.UniBasic Transaction Processing Concepts” explains the basic concepts on which UniData transaction processing is based.

In This Chapter In This Chapter This chapter consists of the following sections: • • • “Transaction Processing Commands” “Creating or Converting to a Recoverable File” “Transaction Processing Programming Problems” Developing UniBasic Applications 281 .

UniBasic Transaction Processing Transaction Processing Commands The following UniBasic commands and the variable @TRANSACTION let you create UniBasic programs with transaction processing safeguards: • • • • TRANSACTION START TRANSACTION COMMIT TRANSACTION ABORT @TRANSACTION Note Transaction processing works only with recoverable files or the UniData Journaling product. processing continues. and the transaction commits inappropriately. see the Administering the Recoverable File System. indexes based on virtual fields might not be updated. To learn more about creating new recoverable files or converting existing files. If the transaction is not aborted by the ON ERROR clause. you must code an ON ERROR clause that takes appropriate action to notify the user and stop the transaction.Chapter 9 . 282 Developing UniBasic Applications . and the only notification you will receive will be a warning recorded in the sm.log file. Warning When including WRITE statements within a transaction. If both types of applications make updates to the same UniData file at the same time. Executing TP and Non-TP Transactions Informix recommends that you NOT execute at the same time applications that perform transactions and those that do not.

When UniData encounters a nested transaction. virtual fields are resolved and their index entries are created when a write is executed within a transaction. Note UniBasic does not support nested transactions. The TP transaction writes a new record to a recoverable file.Transaction Processing Commands The following demonstrates a scenario that results in indexes based on virtual fields not being updated because TP and non-TP applications are running simultaneously: 1. 2. Syntax: TRANSACTION START {THEN statement(s) | ELSE statement(s)} The UniBasic TRANSACTION START command initiates a new transaction and temporarily stores all updates until a the transaction is committed or aborted. Developing UniBasic Applications 283 . You must specify a THEN or an ELSE clause. (The write is held pending the transaction commit. The TP application initiates a transaction by executing the UniBasic TRANSACTION START command or by executing any UniData SQL transaction-initiating command. but can specify both. UniData discovers that the record now exists. so it changes its insert operation to an update.) 3. When the TP transaction commits. Because the operation has become an update rather than insert. no new alternate key index entry is made for the new record. The non-TP application executes a write. 4. creating a record with the same @ID as the one created in Step 2. However. not when the transaction is committed. Starting a Transaction Use the UniBasic TRANSACTION START command to initiate a transaction. the ELSE clause executes.

see the UniBasic Commands Reference. STATUS Values For information about the UniBasic STATUS function. Indicates a nested start. Indicates an error message. the STATUS function returns one of the values described in the following table. Example In the following example.UniBasic Transaction Processing STATUS Function Values After you execute TRANSACTION START." END END 284 Developing UniBasic Applications . which is taken from the sample program in “Appendix B .” the TRANSACTION START command starts the transaction process: Program Example TRANSACTION START ELSE IF STATUS() = 1 THEN DISPLAY "A Transaction had already been started.Chapter 9 . Value 0 1 errno Description Successful transaction start.UniBasic Transaction Processing Concepts. NESTED Transactions" DISPLAY "are NOT Allowed. (Contact System Administrator)" INPUT PAUSE.1_ END ELSE DISPLAY "The Recoverable File System is not enabled.

UniData writes all pending updates to the appropriate files. Unsuccessful Commit If the transaction cannot commit and the ELSE clause executes. UniData executes the ELSE clause. Releases all records locked by this process. Executes the THEN clause. 2. 5. Disables the break key. UniData performs the following steps: 1. Releases all records locked inside the transaction. Developing UniBasic Applications 285 . If a TRANSACTION COMMIT statement executes in the absence of an active transaction.Transaction Processing Commands Committing a Transaction Use the UniBasic TRANSACTION COMMIT command to commit a transaction. 3. 4. Enables the break key. Aborts the transaction without writing records. Syntax: TRANSACTION COMMIT {THEN statement(s) | ELSE statement(s)} The UniBasic TRANSACTION COMMIT command concludes the active transaction. Writes all updates. You must specify a THEN or an ELSE clause. if included. or both. Successful Commit UniData performs the following steps during a transaction commit: 1. 2.

Transaction cannot commit. STATUS Values Example In the following example. taken from the sample program in “Appendix B . Value 0 1 3 Description Transaction committed.Chapter 9 .UniBasic Transaction Processing STATUS Function Values After you execute TRANSACTION COMMIT.UniBasic Transaction Processing Concepts.” the TRANSACTION COMMIT command ends the transaction process and writes the new record to the database: Program Example TRANSACTION COMMIT IF STATUS() = 1 DISPLAY "The END ELSE DISPLAY "The END ELSE THEN TRANSACTION was not started" TRANSACTION could not be committed. Transaction not started. the STATUS function returns one of the values described in the following table." 286 Developing UniBasic Applications .

or the process is killed before a transaction commit is issued. Developing UniBasic Applications 287 .Transaction Processing Commands Aborting a Transaction Use the UniBasic TRANSACTION ABORT command to abort active transactions. including: • • • • A program finishes before a transaction commit is issued (STOP or END). The user running the program is logged out. • The system handles these abort conditions in the same way it does TRANSACTION ABORT. A user breaks out of the program before a transaction commit is issued. terminating the transaction. Note You should be aware of these various abort conditions and control the resulting action from within the program where possible and appropriate. a transaction could abort due to any of several conditions. An error terminates the program before a transaction commit is issued. Syntax: TRANSACTION ABORT The UniBasic TRANSACTION ABORT command cancels the active transaction. This can be prevented programmatically by disabling the interrupt key during the transaction by executing the ECL command PTERM -BREAK OFF. none of the updates associated with the transaction occur. the program aborts. discarding the pending writes. As a result. if no ON ERROR clause is included in a write statement and the write fails. The program CHAINs to another program. For example. In addition to encountering a TRANSACTION ABORT statement.

STATUS = ":STATUS(). The following table describes the possible values for @TRANSACTION. STATUS = ":STATUS(). Value 1 0 Description A transaction is active. the transaction process aborts if var is 10: Program Example TRANSACTION START THEN PRINT "Transaction started. STOP READU var FROM file." ELSE PRINT "Transaction Aborted. record1 TRANSACTION COMMIT THEN PRINT "Transaction committed. GOTO ERR: WRITE var TO file.var. @TRANSACTION Values 288 Developing UniBasic Applications .var.Chapter 9 ." ELSE PRINT "Transaction start failed. record1 var += 2 IF var = 10 THEN TRANSACTION ABORT.UniBasic Transaction Processing Example In the following example. STOP Testing for an Active Transaction The variable @TRANSACTION lets you test for an active transaction. A transaction is not active.

" Developing UniBasic Applications 289 . Make sure that if the RECOVERABLE * FILE System is operational that either BOTH records are updated.UniBasic Transaction Processing Concepts.” Note that the WRITE commands are enclosed in a transaction.REC ON CLIENT_FILE." END END WRITE CLIENT.CLIENT_NUMBER WRITE ORDER. NESTED Transactions" DISPLAY "are NOT Allowed.ORDER_NUMBER TRANSACTION COMMIT IF STATUS() = 1 DISPLAY "The END ELSE DISPLAY "The END END RETURN ELSE THEN TRANSACTION was not started" TRANSACTION could not be committed. Program Example WRITE_RECORD: * The record(s) have been updated.Transaction Processing Commands Transaction Processing Programming Example The following program segment is taken from the sample program in “Appendix B . (Contact System Administrator)" INPUT PAUSE. and that both or neither are committed. TRANSACTION START ELSE IF STATUS() = 1 THEN DISPLAY "A Transaction had already been started.1_ END ELSE DISPLAY "The Recoverable File System is not enabled. or that * None are (using Transaction processing commands).REC ON ORDERS_FILE.

290 Developing UniBasic Applications . Creating a Recoverable File Use the ECL CREATE.multiplier]] [TYPE hashtype] [DYNAMIC [KEYONLY | KEYDATA] [PARTTBL part_tbl]] [RECOVERABLE] [OVERFLOW] For more information about the ECL CREATE.FILE command. You cannot specify the DIR or MULTIDIR options with the recoverable options. which restores accounts in CPIO format. Syntax: CREATE. For more information about RFS. UniData supports recovery of the following file types: • • • • DATA DICT MULTIFILE DYNAMIC Note The recoverable file system does not protect DIR and MULTIDIR type files. Warning The operating system–level acctrestore command. or you can convert a nonrecoverable file to be recoverable. does not work with the UniData Recoverable File System (RFS).FILE command with the RECOVERABLE option to create a file for use with RFS.block. see the UniData Commands Reference.FILE [DICT | DATA] [DIR | MULTIFILE | MULTIDIR] filename [.size.Chapter 9 . see Administering the Recoverable File System.subfile] [modulo [.UniBasic Transaction Processing Creating or Converting to a Recoverable File You can make a file recoverable when you create it.

see Administering UniData on UNIX. with a modulo of 4.blocksize/1024 Hash type = 0 Create file MASTER. You cannot convert a file using udfile while UniData is running. recoverable or nonrecoverable). Developing UniBasic Applications 291 . UniData changes the modulo to the next highest prime number. use the UniData udfile command.blocksize/1024 Hash type = 0 Added "@ID". modulo/1. Because 4 is not a prime number. If you do not specify an option. modulo/5. which is 5: Screen Example :CREATE.UniData returns the type of file (that is. Syntax: udfile [-r | -s] file. You must have root privileges to convert a file using this command.FILE command creates the recoverable file MASTER. Converting to a Recoverable File To convert an existing file to a recoverable file. To learn more about creating new recoverable files or converting existing files.name Permissions The UniData operating system–level udfile command converts a nonrecoverable UniData file to a recoverable file or a recoverable file to a nonrecoverable UniData file. modulo changed to 5. the CREATE. Create file D_MASTER.Creating or Converting to a Recoverable File Example In the following example. the default record for UniData to DICT MASTER.FILE MASTER 4 RECOVERABLE 4 is not a prime number.

using the ECL RESIZE or system-level memresize command.UniBasic Transaction Processing Parameters The following table describes the valid udfile options. Option -r -s Description Converts a nonrecoverable file to a recoverable file. UniData issues an error message indicating that the file cannot be converted. If you try to do so. see the UniData Commands Reference. udfile Options Note The udfile command does not convert files that were created in one-half kilobyte blocks. Converts a recoverable file to a nonrecoverable file.Chapter 9 . For information about ECL commands. You must resize the file to at least a 1K block size. 292 Developing UniBasic Applications .

in other cases. This section points out some of these problems and suggests ways of overcoming them. • Upgrading Locks If two users share a lock on a record. if specified. For more information. in some cases.Using UniData Locks. You can reduce the likelihood of deadlocks occurring by imposing a protocol on the order data items can be updated. see “Testing for an Active Transaction” earlier in this chapter. A TRANSACTION START within another active transaction executes the ELSE clause. For more information about @TRANSACTION. and UniData aborts the other transaction. see “Chapter 5 . one user receives the upgraded lock.” Transaction Abort The following problems cause UniData to abort transactions: • Deadlocks When two or more programs are waiting for each other to release records. and one or both tries to upgrade to a U lock. degrade performance and. cause UniData to abort transactions. and aborts the transaction if none is specified. Execute the LOCKED clause in the locking statement to abort the transaction. • Nested Transactions UniData does not support nested transactions. but not the program. If all programs on the system follow this protocol. For example. Use the @TRANSACTION variable to find out if a transaction is active before calling an external subroutine. Many problems are caused or compounded by improper use of UniData locks. Developing UniBasic Applications 293 .Transaction Processing Programming Problems Transaction Processing Programming Problems Programming problems could. UniData aborts one of the transactions to unlock its records and remove the deadlock. the protocol might let programs lock record B only after locking record A. deadlocks will be avoided.

OPTIONS If UDT. • Transaction Processing Limitations UniData does not support transaction processing outside of UniBasic and UniData SQL. and the subroutine stops abnormally. BUILD. you cannot execute any of the following types of operations with the EXECUTE: • • • UniData SQL (use EXECUTESQL) UEntry/UReport File-level operations on recoverable files (for example. To avoid this.INDEX. causing unpredictable results in TP. the UniBasic CLEARFILE commands and the following ECL commands: CLEAR.FILE.FILE. UDT.Chapter 9 . 294 Developing UniBasic Applications .INDEX. RESIZE. Although you can include EXECUTE statements within a transaction. UniData creates a new user and processes it independently from the original UniBasic program. DELETE.OPTION 35 is off when using TP.OPTION 35 is on when you issue an EXECUTE statement. include the ON.ABORT clause in the subroutine to stop program execution in the event of a problem affecting a subroutine.INDEX. CREATE. CREATE.UniBasic Transaction Processing • Called Programs and Subroutines If a you start a transaction within a called program or subroutine.FILE. CNAME). Make sure UDT. DELETE. UniData could return control to the calling program with the transaction still active.

Transaction Processing Programming Problems

Examples
Recovering from a deadlock – In this example, a deadlock results because two programs are waiting for each other to release the same record (steps 3 and 4). UniBasic aborts Transaction 2 to break the deadlock when this transaction tries to upgrade to an exclusive lock. However, the LOCKED clause (LOCKED TRANSACTION ABORT) in the RECORDLOCKU statement tells UniBasic to abort the transaction only, thus preventing the program from aborting. Step 1 Transaction 1
TRAN1: TRANSACTION START THEN PRINT "Transaction started." READL var1 FROM file.var, record1 ELSE PRINT "File not found."

Transaction 2
TRAN2: TRANSACTION START THEN PRINT "Transaction started."

2 3
RECORDLOCKU var1 LOCKED TRANSACTION ABORT; GOSUB TRAN1 var += 2 WRITE var TO file.var, record1 TRANSACTION COMMIT THEN PRINT "Transaction committed."

READL var1 FROM file.var, record1 ELSE PRINT "File not found."

4

RECORDLOCKU var1 LOCKED TRANSACTION ABORT; GOTO TRAN2 var += 2 WRITE var TO file.var, record1 TRANSACTION COMMIT THEN PRINT "Transaction committed."

Avoiding Program Abort on Deadlock

Developing UniBasic Applications

295

Chapter 9 - UniBasic Transaction Processing

Nested transactions – The next three examples demonstrate creating and avoiding nested transactions. In this first program segment, the main routine starts a transaction, and then calls a subroutine that contains a TRANSACTION START. This always results in an aborted transaction because transactions cannot be nested.

Program Example
TRANSACTION START ELSE PRINT "Transaction error.";STOP READU var FROM file.var, record1 ELSE PRINT "File not found." IF var = "" THEN CALL SUBRZ WRITE var TO file.var, record1 TRANSACTION COMMIT ELSE PRINT "Transaction aborted." SUBROUTINE SUBRZ TRANSACTION START ELSE PRINT "Transaction error.";STOP READU var1 FROM file.var, record2 ELSE PRINT "File not found." var1 += 2 WRITE var1 TO file.var, record2 TRANSACTION COMMIT ELSE PRINT "Transaction aborted."

The next program segment avoids the problem demonstrated in the previous example. The subroutine tests @TRANSACTION for an active transaction before starting its own transaction.

Program Example
TRANSACTION START ELSE PRINT "Transaction error.";STOP READU var FROM file.var, record1 IF var = "" THEN CALL SUBRZ WRITE var TO file.var, record1 TRANSACTION COMMIT ELSE PRINT "Transaction aborted." SUBROUTINE SUBRZ IF @TRANSACTION = 1 THEN RETURN TRANSACTION START ELSE PRINT "Transaction error.";STOP READU var1 FROM file.var, record2 var1 += 2 WRITE var1 TO file.var, record2 TRANSACTION COMMIT ELSE PRINT "Transaction aborted."

296

Developing UniBasic Applications

Transaction Processing Programming Problems

In the following program, the subroutine tests for an active transaction with @TRANSACTION before an EXECUTE statement:

Program Example
TRANSACTION START ELSE PRINT "Transaction not started."; STOP READU var FROM file.var, record1 IF var = "" THEN CALL SUBRZ WRITE var TO file.var, record1 TRANSACTION COMMIT ELSE PRINT "Transaction aborted." SUBROUTINE SUBRZ IF @TRANSACTION = 0 THEN EXECUTE "CLEAR.FILE file.var" ELSE RETURN RETURN

Degraded Performance
This section discussed causes and solutions of degraded performance. • Locked Records If you lock records within a transaction, those records remain locked until you commit or abort the transaction. If your program performs a number of operations, especially requesting user input, you increase the waiting period for other users trying to access these records. To avoid this problem, put input statements before the TRANSACTION START. If you must include requests for user interaction within a transaction, include the WAITING clause in the INPUT statement to time out if the user does not respond in a reasonable amount of time. • Long Transactions Performing a number of operations inside a transaction also contributes to performance degradation. By minimizing the number of operations in the transaction, you can improve performance.

Developing UniBasic Applications

297

Chapter 9 - UniBasic Transaction Processing

Note
Protecting data by locking records and using transaction processing can contribute to reduced efficiency and system performance.

Example
In the following example, the INPUT times out after five minutes if the user does not respond:

Program Example
READU var FROM file.var, record1 ELSE PRINT "File not found." INPUT var WAITING 300 TRANSACTION START ELSE PRINT "Transaction not started." STOP WRITE var TO file.var, record1 TRANSACTION COMMIT ELSE PRINT "Transaction aborted."

298

Developing UniBasic Applications

Chapter 10 - Null Value Handling

This chapter introduces the null value handling in UniBasic. UniData supports null value handling on both UNIX and Windows NT or Windows 2000 systems. You can turn on null value handling, which makes the UniData RDBMS more compliant with the standards defined by ANSI SQL ‘92. Compliance improves compatibility with client and desktop tools.

Developing UniBasic Applications

299

Chapter 10 - Null Value Handling

Representing Unknown Values
If you turn null value handling on, and you have accepted the default language group when installing UniData, the null value is represented by the ASCII character 129. If you change language groups, a different character could be assigned to represent the null value. For this reason, Informix recommends that you use the @NULL variable to represent the null value in UniBasic.

Tip
To determine which ASCII value represents the null value on your system, use the UniBasic command SEQ(@NULL).

Turning Null Value Handling Off
When you install UniData, null value handling is turned off by default (the udtconfig parameter NULL_FLAG = 0). With null value handling turned off, an empty string represents unknown or missing values, and UniBasic programs that contain the variable @NULL will not compile. If you try to execute object code containing @NULL, the program terminates with a fatal error. After turning null value handling on, Informix recommends that you not turn it off, as the null character could have been introduced to your data. If you must turn null value handling off, be sure to check your data and convert the null value to another string (using a UniBasic program or virtual attribute) before trying to execute queries, virtual attributes, or UniBasic programs. You will also need to regenerate any indexes that could contain null values; if you do not, records with null alternate key values cannot be retrieved.

300

Developing UniBasic Applications

Null Value Handling in UniBasic

Null Value Handling in UniBasic
The presence of the null value in data or function/command arguments profoundly affects the results of UniBasic commands, functions, and arithmetic operators. These effects differ according to whether null value handling is turned on or off, and range from UniBasic ignoring the character to generating a runtime error.

Printing and Displaying
The ASCII character that represents the null value is nonprinting, and the environment variable NVLMARK, which specifies an alternative character to represent the null value for display or printing in UniData and UniQuery, has no effect in UniBasic. Although no comparable function exists in UniBasic, you can use the UniBasic conversion commands, such as SWAP and CONVERT, or the UniData SQL command NVL to convert the null value to another string before printing.

Sorting and Indexing
Null Value Handling On – The null character is always sorted as the lowest value, lower than all negative numbers.

Tip
Use the UniBasic command SETINDEX with the rop operator NULL_VAL_ALT_KEY to set the alternate key index pointer to the null value (the beginning of the index). The rop operator FIRST_ALT_KEY sets the pointer to the first non-null key. Null Value Handling off – The character that would represent the null value is sorted normally, by ASCII value.

Developing UniBasic Applications

301

Chapter 10 - Null Value Handling

Summary of Effects on Commands and Functions
The following table summarizes the effects of the null value in data and function or command arguments. Details are provided in the sections that follow. Type of Operation Numeric calculations Null Value Handling On Result is the null value. Null Value Handling Off Original value is returned. UniBasic returns the message “Non-numeric found when numeric required.” No special handling of the null value. Follow the ANSI SQL 2way logic rules. No special handling of the null value; invalid for format code. No special handling of the null value. In a parameter, if numeric is required, generates runtime error. No special handling of the null value. Sorting is based on ASCII values.

Relational operations Conversions String functions

Follow the ANSI SQL 3-way logic rules. Result is the null value; invalid for format code. No special handling of the null value. In a parameter, if numeric is required, displays a warning message and uses 0. Null value is lowest (smaller than all negative numbers).

Sorting and indexing

Null Value Handling Summary

302

Developing UniBasic Applications

UniBasic prints a warning message and uses 0 as the function argument. Numeric Operators and Functions + ^ ATAN BITXOR INT POWER SCMP SQRT ABS BITAND COS LN PWR SDIV SSUB * ACOS BITNOT DROUND MOD RND SIN TAN / ASIN BITOR EXP NEG SADD SMUL Numeric Operators and Functions Affected by the Null Value Null Value Handling On In Data – The result of any numeric function on data containing the null value is the null value. UniBasic issues a warning message: Non-numeric found when numeric required. the command or function processes. Developing UniBasic Applications 303 . Reminder When a UniBasic numeric function encounters a non-null.Null Value Handling in UniBasic The Null Value in Numeric Functions The presence of the null character in data affects numeric functions whether nulls are turned on or off. The following table lists the UniBasic numeric operators and functions. In Arguments – Any time UniBasic encounters a null value as a command or function argument when a number is required. nonnumeric character. using 0 in place of the invalid character.

Chapter 10 .Null Value Handling Examples The following program demonstrates the principle that any arithmetic operation on data that contains the null value results in the null value: Program Example A = 100 + @NULL GOSUB PRINTNULL PRINT "100 + @NULL = ":A A = 0 A = SIN(@NULL) GOSUB PRINTNULL PRINT "SIN(@NULL) = ":A A = 0 A = 99/@NULL GOSUB PRINTNULL PRINT "99/@NULL = ":A A = 0 A = 33/99 GOSUB PRINTNULL PRINT "33/99 = ":A STOP PRINTNULL: IF ISNV(A) THEN SWAP @NULL WITH "null value" IN A RETURN 304 Developing UniBasic Applications .

3333 Null Value Handling Off The null value is invalid. you can nest additional conditions using the following keywords: • • WHILE UNTIL Developing UniBasic Applications 305 . Note UniBasic programs containing @NULL will not compile when null value handling is turned off. then it is evaluated to false (0). When a numeric function encounters the null value as data or an argument. UniBasic displays a warning message and uses 0.Null Value Handling in UniBasic The preceding program prints the following: Screen Example 100 + @NULL = null value SIN(@NULL) = null value 99/@NULL = null value 33/99 = 0. You perform conditional tests in UniBasic with the following statements: • • IF/THEN/ELSE CASE Within these statements. The Null Value in Conditional Tests The presence of the null value in data affects conditional tests only if null value handling is turned on.

Program Example X = @NULL BEGIN CASE CASE X = 1 GOSUB ADD_RECORD CASE X = 2 GOSUB UPDATE_RECORD CASE X = 3 FINISHED = 1 CASE 1 GOSUB DELETE_RECORD 306 Developing UniBasic Applications .COUNT STOP COUNT.Null Value Handling Examples The following examples demonstrate the effect of the null value in IF/THEN/ELSE and CASE statements. the program prints @NULL evaluates to 'false'. The program segment prints Deleting corrupt record. In this first example.TO. Program Example X=@NULL IF X THEN GOSUB COUNT. COUNT.TEN ELSE GOSUB NO. CASE 1 executes because X is the null value.TO.Chapter 10 .TEN: FOR X = 1 TO 10 PRINT X NEXT X RETURN NO. Instead. @ID is null.COUNT: PRINT "@NULL evaluates to 'false'" RETURN In the following program segment.TEN does not execute because X is the null value.TO.

#. Developing UniBasic Applications 307 . => OR NOTS EQ. @ID is null. <=. >=. = GES #> LE. which produces a result of false in a conditional test." RETURN Comparison Operators Used in Conditional Tests The following table lists the UniBasic comparison operators. >< GTS LT. =< EQS GT. < NES AND Note The logical operators NULL and NOT @NULL are both evaluated to the null value." RETURN DELETE_RECORD: PRINT "Deleting corrupt record. Comparison Operators NOT LTS GE.Null Value Handling in UniBasic END CASE STOP ADD_RECORD: PRINT "Adding a record." RETURN UPDATE_RECORD: PRINT "Updating a record. <>. > #< Comparison Operators LES NE.

To use the program to test the logical operator AND. substitute AND for OR in this program.Null Value Handling Null Value Handling On The results of comparisons using the logical operator AND are provided in the following truth table (T. T T F N T T T T F N F T N N N Null in Conditional Statements with OR You can use the following sample program to test comparisons of the logical operator OR. F.one=value 308 Developing UniBasic Applications . or null: ": INPUT answer answer = UPCASE(answer) GOSUB SET. respectively). FALSE. F.Chapter 10 . and @NULL. Program Example PROMPT @(-1) PROMPT'' PRINT "First value: Enter true. false. T T F N T F N F F F F N F N N Null in Conditional Statements with AND The results of comparisons using the logical operator OR are provided in the following table (T. FALSE. and N represent TRUE. and @NULL. respectively). and N represent TRUE.VAL val.

It demonstrates that the comparison ‘true OR null’ produces a result of ‘true’.VAL: IF answer = "NULL" THEN value = @NULL IF answer = "TRUE" THEN value = 1 IF answer = "FALSE" THEN value = 0 RETURN The following example shows a sample run of this program." END CASE SET. or null: true Second value: Enter true. false. Developing UniBasic Applications 309 .one OR val.two ) = 1 PRINT "Condition is true. false.Null Value Handling in UniBasic PRINT "Second value: Enter true.two=value BEGIN CASE CASE (val. Screen Example :RUN BP null." CASE ISNV(val.two) = 1 PRINT "Condition is null" CASE 1 PRINT "Condition is false. or null: ": INPUT answer answer = UPCASE(answer) GOSUB SET.VAL val.one OR val. false.compare First value: Enter true. or null: null Condition is true.

the null value is interpreted by UniBasic as false. NOT(NULL) is TRUE" END ELSE Y = NOT(X) PRINT "1b.Chapter 10 . A comparison with the null value produces a result of null: Program Example X = @NULL IF NOT(X) THEN PRINT "1a.Null Value Handling Examples The following program segments demonstrate the effect of the null value on comparisons. 100 LE NULL is TRUE" END ELSE PRINT "2b. NOT(NULL) IS FALSE" END This program segment prints the following: Screen Example 1b. 100 LE NULL IS FALSE" 310 Developing UniBasic Applications . NOT(NULL) IS FALSE Any number is greater than the null value: Program Example X = @NULL IF (100 LE X) THEN PRINT "2a. Reminder In a comparison test.

NULL EQ NULL IS FALSE" END PRINT " NULL EQ NULL evaluates to ":(@NULL EQ @NULL) This program segment prints: Screen Example 3b.Null Value Handling in UniBasic END PRINT " 100 LE NULL evaluates to ":(100 LE @NULL) This program segment prints: Screen Example 2b. NULL EQ NULL IS TRUE" END ELSE PRINT "3b. 100 LE NULL IS FALSE 100 LE NULL evaluates to 0 The null value compared to the null value yields a result of false: Program Example X = @NULL IF (X EQ X) THEN PRINT "3a. NULL EQ NULL IS FALSE NULL EQ NULL evaluates to 0 Anything AND the null value yields a result of false: Program Example X = @NULL IF (1 AND X) THEN Developing UniBasic Applications 311 .

1 AND NULL IS FALSE 1 AND NULL evaluates to Anything OR the null value yields a result of true: Program Example X = @NULL IF (1 OR X) THEN PRINT "5a.Null Value Handling PRINT "4a. 1 OR NULL IS TRUE 1 OR NULL evaluates to 1 312 Developing UniBasic Applications . 1 AND NULL IS TRUE" END ELSE PRINT "4b.Chapter 10 . 1 OR NULL IS TRUE" END ELSE PRINT "5b. 1 AND NULL IS FALSE" END PRINT " 1 AND NULL evaluates to ":(1 AND @NULL) This program segment prints: Screen Example 4b. 1 OR NULL IS FALSE" END PRINT ' 1 OR NULL evaluates to ":(1 OR @NULL) This program segment prints: Screen Example 5a.

Conversion Functions ICONV ICONVS OCONV OCONVS FMT FMTS Conversion Functions Affected by the Null Value Null Value Handling On In Data – For conversion functions ICONV/S.Null Value Handling in UniBasic Null Value Handling Off The UniBasic comparison operations follow ANSI 2-way logic. indicating an invalid conversion specification. use the string functions to convert between the null value and some other string. Developing UniBasic Applications 313 . UniBasic generates a runtime error and returns the input string. The STATUS function then returns 2. Tip Some string functions also perform conversions of various kinds while ignoring the null value. with the null value being compared as its ASCII value (ASCII character 129 in the English language group). In Parameters – If a UniBasic program tries to use the null value as a conversion specification. OCONV/S. and FMT/S. the presence of the null value in data produces a result of the null value. Use the conversion functions in the preceding table when you want to produce a null value when a null value is input. and the STATUS function return value is set to 5. The Null Value in Conversion Functions The following table lists the UniBasic conversion functions.

the UniBasic STATUS function return value is set to 5." This program produces the following results: Screen Example STATUS FOR ICONV IS 5 ICONV on the null value produces the null value. This example demonstrates that @NULL in an argument produces no result.Null Value Handling Examples The following example demonstrates that an ICONV conversion on data containing the null value produces a result of the null value: Program Example X = ICONV(@NULL."D2/") PRINT "STATUS FOR ICONV IS ":STATUS() IF ISNV(X) THEN PRINT "ICONV on the null value produces the null value.Chapter 10 ."@NULL") PRINT "STATUS FOR ICONV IS ":STATUS() 314 Developing UniBasic Applications . Note If the null value is found in a string to be converted. but sets the STATUS return code to 2: Program Example PRINT = ICONV(1234.

Null Value Handling in UniBasic This program produces the following results: Screen Example STATUS FOR ICONV IS 2 Null Value Handling Off In Data – The ASCII character that would represent the null value in data has no effect on conversion functions. You cannot use NOT(@NULL) to test for the absence of the null value because NOT(@NULL) evaluates to the null value. You can assign the null value to a variable in the following way: X=@NULL • • Developing UniBasic Applications 315 . Therefore. You must instead test for a return value of 0 from ISNV or ISNVS. invalid format code. SEQ(@NULL) returns the ASCII code representing @NULL on your system. You cannot use an expression like “IF CUSTOMER = @NULL” to search for the null value. You must instead test for a return value of 1 from ISNV or ISNVS to determine if a variable or element is the null value. Exceptions to this rule are listed in the following sections. In Parameters – The result is the null value. The Null Value in String Functions The following general guidelines apply to all string functions: Null Value Handling On In Data – The UniBasic string commands and functions are not affected by the null value in data. The following list highlights some points to remember about the null value in string functions: • • • ISNV and ISNVS test for the null value as a string or dynamic array element. you can use them to manipulate the null character just as you would any other character.

Testing for data type ALPHA (alphabetic) NUM. UniBasic displays the warning message “Null value found when numeric required”. SEQ. SOUNDEX Note . EBCDIC. CHANGE. REPLACE. Summary The null value receives no special handling in string functions. are not alphabetic or numeric.Null Value Handling In Parameters – Whenever a numeric parameter is required.Special characters. UniBasic displays the warning message “Non-numeric found when numeric required”. UniBasic then continues processing using 0 as the parameter. In Parameters – Whenever a numeric parameter is required. ISNVS (null value) Note . SEQS DOWNCASE. Null Value Handling Off In Data – The ASCII character that would represent the null value has no effect on conversion functions when encountered in data. NUMS (numeric) ISNV. UniBasic String Function Types 316 Developing UniBasic Applications . including the null value. are ignored. UniBasic continues processing using 0 as the function parameter. including the null value. They remain unchanged in function output. including nulls. You can use these functions to locate and change any ASCII value.Special characters. Type String conversion Commands/Functions ASCII. UPCASE. CONVERT. and the null value is encountered. CHARS. CHAR.Chapter 10 . it displays a warning message and uses 0. and the null value is encountered. It is processed as any other character. If UniBasic encounters the null value in a command parameter when a number is expected.

Null Value Handling in UniBasic Type Conditional tests Commands/Functions IF/THEN/ELSE. MATCHFIELD. MATCHES Extraction Counting Returning System. FINDSTR.These functions produce a string or array elements made up of spaces. GETPTR. STRS SPACE. GETUSERNAME LEN. INS. CATS. GROUPSTORE. XLATE FIND. GETUSERGROUP. WHILE. CAT. Printer. STR. EXTRACT. UniBasic String Function Types (continued) Developing UniBasic Applications 317 . UNTIL Note . and User Information Measuring Length Repeating [ ]. SPLICE [].For more information see “The Null Value in Conditional Tests” earlier in this chapter. TRIMF. SUBSTRINGS. DCOUNT DIR. TRIM. MATCH.The null value has a length of 1 byte. FIELD. FIELDSTORE. TRIMS COUNT. SPACES Note . CASE. Concatenation Insertion Deletion Location : (colon). LOCATE. REMOVE. INSERT DEL. TRIMB. FIELDS. GETPU. File. DELETE GROUP. SYSTEM. COUNTS. LENS Note .

a ISNV(0) = ":ISNV(A) PRINT "2.c ISNV(@NULL) = ":ISNV(A) PRINT "2.Null Value Handling Examples The following subroutine converts UniData delimiters and the null value to printable characters: Program Example * externally cataloged subroutine to convert the null value * and UniData delimiters for printing SUBROUTINE null.b NOT(ISNV('abc':@NULL:'def')) = ":NOT(ISNV(A)) A = @NULL PRINT "1.b ISNV('abc':@NULL:'def') = ":ISNV(A) PRINT "2.c NOT(ISNV(@NULL)) = ":NOT(ISNV(A)) 318 Developing UniBasic Applications .swap(A) SWAP @NULL WITH "null value" IN A SWAP @AM WITH "AM" IN A SWAP @VM WITH "VM" IN A SWAP @SM WITH "SM" IN A RETURN Testing for Data Type The following program uses the function ISNV to test a string to see if it consists of the null value: Program Example A = 0 PRINT "1.a NOT(ISNV(0)) = ":NOT(ISNV(0)) A = "abc":@NULL:"def" PRINT "1.Chapter 10 .

" END ELSE Developing UniBasic Applications 319 .@NULL.X> NEXT X WRITE REC_ARRAY TO INV_FILE." DEL REC_ARRAY<6.POINT> PRINT "@NULL deleted from the array at position ":POINT PRT_ARRAY = CHANGE(REC_ARRAY.b 2.1.0> SETTING POINT THEN PRINT "The null value already exists in the array at position ": PRINT POINT PRINT "Deleting the null value.b 1. Notice that ISNV executed on a string that contains the null value and other characters produces a negative result (0).a 2." LOCATE @NULL IN REC_ARRAY<6." ELSE PRINT "Record not found. Screen Example 1."@NULL") FOR X = 1 TO POINT PRINT PRT_ARRAY<6.Null Value Handling in UniBasic This program produces the following results.c 2.c ISNV(0) = 0 NOT(ISNV(0)) = 1 ISNV('abc':@NULL:'def') = 0 NOT(ISNV('abc':@NULL:'def')) = 1 ISNV(@NULL) = 1 NOT(ISNV(@NULL)) = 0 The following program segment inserts the null value into or deletes the null value from a multivalue in the QUANTITY attribute for a selected record in the INVENTORY demo database file: Program Example OPEN 'INVENTORY' TO INV_FILE ELSE PRINT "OPEN error" STOP END PRINT "Enter record to be modified: ": INPUT rec READU REC_ARRAY FROM INV_FILE.rec ON ERROR PRINT "WRITEerror.rec LOCKED PRINT "Record locked.a 1.

POINT> = @NULL PRINT "@NULL placed in the array at position ":POINT PRT_ARRAY = CHANGE(REC_ARRAY.del. @NULL deleted from the array at position 5 400 500 394 399 320 Developing UniBasic Applications ."@NULL") FOR X = 1 TO POINT PRINT PRT_ARRAY<6.del.ins Enter record to be modified: ?56070 @NULL placed in the array at position 5 400 500 394 399 @NULL A second execution of this program produces the following results: Screen Example :RUN BP null.rec ON ERROR PRINT "WRITEerror.ins Enter record to be modified: ?56070 The null value already exists in the array at position 5 Deleting the null value.Chapter 10 .X> NEXT X WRITE REC_ARRAY TO INV_FILE.Null Value Handling REC_ARRAY<6.@NULL." END STOP The following example shows a a sample run of the preceding program: Screen Example :RUN BP null.

Null Value Handling in UniBasic Reminder When a numeric parameter is required. Sorting and Indexing The following series of examples demonstrates the use of SETINDEX to set the record pointer to the first null key in the PROD_NAME alternate key index: Program Example OPEN 'INVENTORY' TO inventory ELSE PRINT "Open error" SETINDEX 'PROD_NAME'.idx 10020. Adapter. Bass Boost Developing UniBasic Applications 321 . ":rec<3>:". Portable Model 10104. CD Player. CD Player. Ethernet LC Card 10092. NULLVAL_ALT_KEY inventory FOR X = 1 TO 5 READFWD rec FROM inventory THEN PRINT rec<0>:". Adapter. A/C Adapter for notebook computers 10086. ":rec<4> END ELSE NULL NEXT X STOP This program produces the following result when no null values exist in the PROD_NAME index: Screen Example :RUN BP set. Adapter. UniBasic displays the warning message “Null value found when numeric required”. Personal Model. and the null value is encountered. UniBasic continues processing using 0 as the function parameter. Workgroup Hub 10082.

Adapter. Ethernet LC Card 10092. 6 ppm 10238. Super Deluxe Model 10020.Chapter 10 . . Adapter. Portable. Workgroup Hub 322 Developing UniBasic Applications . Adapter. the same program produces the following results: Screen Example :RUN BP set. A/C Adapter for notebook computers 10086.Null Value Handling After the null value is inserted into the PROD_NAME attribute for records 10008 and 56060. .idx 10015. B/W.

Note You cannot use the READSEQ command to read a named pipe. OSBREAD. Three factors affect the operation of these commands: • • Is the target of the command a named pipe or a file? For a named pipe – Is it open for a complementary operation on the other end? (When read access is requested. or other non-UniData processes. and OSBWRITE commands enable UniBasic programs to interface. You must use OSBREAD and OSBWRITE to perform these tasks.Chapter 11 . is the pipe open for reading on the other end?) For a named pipe – Is data stored in the pipe. and is it of the length specified in the command? • Processing can be modified to accommodate different circumstances. is the pipe open for writing on the other end? Conversely. a process can force the requested access by executing the NODELAY option. and then coordinate access programmatically. through named pipes. when write access is requested. other UniBasic programs. a single process can open the pipe for read-write access. Also.Managing Named Pipes The UniBasic OSOPEN. For example. with RedBack (UniData’s web application development software). nor can you use the WRITESEQ or WRITESEQF command to write to a named pipe. Developing UniBasic Applications 323 .

Screen Example :!mkfifo pipe_file :ls -l pipe_file prw-rw-rw1 carolw unisrc 0 Jul 28 09:55 pipe_file For Windows NT or Windows 2000. ConnectNamedPipe() – Establishes a connection between the server pipe instance and the client side. use the following Win32 APIs to create a named pipe: • CreateNamedPipe() – Creates an instance of a named pipe on the local machine. It does not destroy the pipe. Use this API if your server uses multiple pipe instances. which the UniBasic OSOPEN command uses to wait for an available instance. For open mode. use the UNIX mkfifo command to create a named pipe. as in the following example: Reminder To execute a UNIX command from the ECL prompt. • • • 324 Developing UniBasic Applications . You also can specify a timeout value. specify PIPE_ACCESS_DUPLEX. DisconnectNamedPipe() – Returns the server pipe instance to a listening state. CloseHandle() – Destroys the pipe when the last pipe instance closes.Managing Named Pipes For UNIX.Chapter 11 . precede it with the UniData bang (!) command. Use this API when you no longer need the pipe.

and a process tries to access (open. Therefore. • • • The sections that follow describe the syntax and processing for OSOPEN. Maximum length for PIPE_BUF is determined by the operating system. This differs from a process reading from a file. but also remains in the file. For a write (OSBWRITE) to be atomic. Developing UniBasic Applications 325 . OSBREAD. the length of data to be written must be less than or equal to the value of the PIPE_BUF. it also must be open for reading on the other end. in which case the data is copied into a variable. read. For UniData for UNIX only. and OSBWRITE for use with named pipes. If the NODELAY keyword is not specified. If you try to open a pipe for writing. it also must be open for writing on the other end. the process waits for the pipe to be accessed in the opposite mode before proceeding. opening a large number of named pipes at the same time can cause a process to try to open more than the maximum number of files allowed by the operating system.) UniData cannot temporarily close named pipes to manage the operating system’s limitation on the maximum number of files allowed to be opened at a time.Points to Remember Keep in mind the following points when accessing named pipes: • When a process reads from a pipe. the PIPE_BUF system variable determines the length of the named pipe. (Opposite mode means that if you try to open a pipe for reading. For information about system variables. This can give the appearance of a hung process. or write) a pipe that is not already open in the opposite mode. see Administering UniData on UNIX. the data is removed from the pipe.

omit the READONLY and WRITEONLY keywords from the OSOPEN statement. On UniData for UNIX. WRITEONLY.). Note To specify that a pipe be open for both read and write access. WRITEONLY opens the pipe or file for write access only. On UniData for Windows NT or Windows 2000. This lets a process continue even when the pipe is not open in the opposite access mode. and pipename is the name of a pipe. The application then must manage access to the pipe to ensure that it is opened for the opposite process before reading from or writing to it. 326 Developing UniBasic Applications . use the filename format \\computername\PIPE\pipename where computername is a valid computer name or a period (. filename in the UniBasic OSOPEN command must include the entire path unless the pipe or file resides in the current directory. • NODELAY forces a pipe to be opened immediately. and NODELAY are used with named pipes: • • READONLY opens the pipe or file for read access only.Chapter 11 . the NODELAY keyword has no effect. The keywords READONLY.var [NODELAY] [ON ERROR statements] {THEN statements [END] | ELSE statements [END]} Note If filename is not a named pipe. which specifies the local machine.Managing Named Pipes OSOPEN Syntax: OSOPEN filename [READONLY | WRITEONLY] TO file.

OSOPEN Reminder If OSOPEN against a named pipe is successful. • OS does not support read-write mode – executes ON ERROR or aborts. Opens. Opening Named Pipes The following table. The process waits until the pipe is opened in read-only mode or read-write mode on the other end. summarizes the actions UniBasic takes when OSOPEN is executed against a named pipe. which applies to UniData for UNIX only. Opens. ELSE clause executes. The process waits until the pipe is opened in write-only mode or read-write mode on the other end. the file pointer is set to the beginning of the file. Mode read-write Open1 no effect NODELAY no effect Action Depends on whether the operating system supports read-write access mode: • OS supports read-write mode – opens. read-only yes no no effect no Opens. 0 2 0 0 after open 0 0 0 after open 3 STATUS2 no write-only yes no yes no effect no no yes Summary of OSOPEN Functionality with Named Pipes (UniData for UNIX Only) 1Is the pipe open in the opposite mode? is the UniBasic STATUS function setting after this operation? 2What Developing UniBasic Applications 327 .

328 Developing UniBasic Applications . NODELAY not specified – The process waits until the pipe is opened in write-only mode on the other end.Chapter 11 .Managing Named Pipes Opening a Pipe in Read-Write Access Mode Processing depends on whether the operating system supports this access mode. NODELAY not specified – The process waits until the pipe is opened in read-only mode on the other end. UniBasic opens the pipe for read-only access. STATUS is set to 3. Opening a Pipe in Read-Only Access Mode Processing depends on whether the pipe is open for writing on the other end: • • If the pipe is open for writing on the other end. • • OS supports read-write access mode – UniBasic forces the pipe to open immediately. the UniBasic STATUS function is set to 2. If the pipe is NOT open for reading on the other end: • • NODELAY specified – The ELSE clause executes. UniBasic opens the pipe for write-only access. or the program aborts. Opening a Pipe in Write-Only Access Mode Processing depends on whether the pipe is open for reading on the other end: • • If the pipe is open for reading on the other end. If the pipe is NOT open for writing on the other end: • • NODELAY specified – UniBasic forces the pipe open immediately in the requested mode. OS does not support read-write access mode – The ON ERROR clause executes if specified.

the ELSE clause executes. the following behavior occurs when you attempt to open a named pipe: • • • If the named pipe exists. and then the pipe opens.OSOPEN More about Opening Named Pipes (Windows NT or Windows 2000) On UniData for Windows NT or Windows 2000. the ELSE statement executes and the UniBasic STATUS function is set to 4. and STATUS is set to 4. • Developing UniBasic Applications 329 . and if an instance is available. the process waits until an instance is available. If the timeout period expires. the process waits for five minutes before the ELSE statement executes. If NODELAY is not specified: • If all instances are busy. If the named pipe does not exist. If NODELAY is specified. the OSOPEN command opens the pipe immediately. and if the named pipe does not exist or no instance is available.

reading a named pipe removes the data. Reading from a Named Pipe Keep these points in mind when writing programs that read from named pipes: • • • • Unlike a typical read. which lets a reading process continue even when the pipe is not open for writing or no data exists in the pipe. 330 Developing UniBasic Applications . the process trying to read waits until the pipe is opened for writing. The reader must specify a length and have some kind of protocol with the server to interpret it correctly.expr to a value greater than -1.expr. before reading from the pipe. and data is written to it. Data in byte mode has no boundary.expr [NODELAY] [ON ERROR statements] The UniBasic OSBREAD command accommodates reading from named pipes: • • The AT clause is not allowed.expr. The value returned could be shorter than length. Data is truncated if it is longer than length. Data in message mode always has a boundary. Note If you do not specify NODELAY on an OSBREAD against a named pipe. Your application should check the length of var after reading a pipe. To set a named pipe to byte-read mode.var [AT byte.expr] LENGTH length.Managing Named Pipes OSBREAD OSBREAD var FROM file.Chapter 11 . The NODELAY keyword forces UniData to read the pipe immediately. and it can be obtained in its entirety. you can set a named pipe to messageread mode by indicating -1 for length. On UniData for Windows NT or Windows 2000. set length.expr. AT is not appropriate for use with named pipes because they are always read with no offset.

no no yes no no effect no no effect no effect UniBasic returns data.OSBREAD Summary for Reading Named Pipes The combination of the following conditions and command options determine the action taken by UniBasic when OSBREAD is executed against a named pipe: • • • Presence or absence of data in the pipe. returns an empty string. or for the pipe to be closed. if closed with no data written. The following table.ON ERROR executes regardless of other conditions (presence of data. open/closed status. UniBasic returns actual content of the pipe regardless of its length. Can be an empty string. Presence or absence of the AT and NODELAY command options. if no ON ERROR clause. AT yes Data1 no effect Open2 no effect NODELAY no effect Action ON ERROR executes. which applies to UniData for UNIX only. Note . from the pipe. Open/closed status of the pipe. the program aborts. summarizes actions taken by UniBasic for each possible combination of these factors. NODELAY). of the length requested. UniBasic returns actual content of the pipe regardless of its length. Can be an empty string. 0 0 STATUS3 2 no no yes no 0 after read no no yes yes 0 Summary of OSBREAD Functionality with Named Pipes (UniData for UNIX Only) 1Does the pipe contain data of the length requested? Developing UniBasic Applications 331 . The process waits for data to be written to the pipe.

The STATUS function return value is set to 0 in either case. If the pipe is not open for writing. It can be an empty string. UniBasic returns the actual contents of the pipe. If the pipe is closed with no data or insufficient data written to it. If the pipe is open for writing on the other end: • • NODELAY specified – UniBasic returns actual content of the pipe regardless of its length. even if the pipe contains more data than that requested.Managing Named Pipes 2 3 Is the pipe open in the opposite mode? What is the UniBasic STATUS function setting after this operation? Reading from a Named Pipe When a process executes a read against a named pipe. NODELAY not specified – The process waits for data of the length requested to be written to the pipe or for the pipe to be closed. NODELAY has no effect in this case. Data of the Required Length When the named pipe contains data of at least the length requested. Data of Insufficient Length When the named pipe contains insufficient data (the pipe is empty or the length of the data is less than specified in the OSBREAD statement). The STATUS function return value is set to 0. processing depends on whether the pipe is open for writing on the other end. the actions UniBasic takes depend on whether the pipe contains data of the length requested in the read statement. NODELAY has no effect. UniBasic returns the actual contents of the pipe.Chapter 11 . UniBasic returns the actual content of the pipe regardless of its length. 332 Developing UniBasic Applications . Can be an empty string.

UniBasic returns the contents of the pipe according to the length requested. Message-Type Pipes • If NODELAY is specified. UniData returns an empty string and the STATUS function return value is set to 5.expr. either the process waits until it receives data with length length. and if a message exists in the pipe.expr.expr. UniBasic returns the actual contents of the pipe (even with zero length) and the STATUS function return value is set to 5.expr. If NODELAY is not specified. UniBasic returns the contents of the pipe perhaps with length less than length. the process waits until a complete message is sent to the pipe. and if the data has a length greater than or equal to length.OSBREAD More about Reading from a Named Pipe (Windows NT or Windows 2000) For UniData for Windows NT or Windows 2000.expr. the following behavior occurs when you attempt to read message-type or byte-type named pipes. and if a message exists in the pipe. If a message does not exist in the pipe. If the data has a length less than length. or a server end closes the pipe.expr. UniBasic returns the actual contents of the pipe regardless of its length. UniBasic returns the actual contents of the pipe regardless of its length. • Developing UniBasic Applications 333 . If the data has a length less than length. and the STATUS function return value is set to 5. If a message does not exist in the pipe. In the case of a server end close. If NODELAY is not specified. and if the data has a length greater than or equal to length. UniBasic returns the contents of the pipe according to the length requested. • Byte-Type Pipes • If NODELAY is specified.

if no ON ERROR clause. The keyword NODELAY forces UniData to write when a pipe is full.expr] [NODELAY] [ON ERROR statements] The UniBasic OSBWRITE command accommodates writing to a named pipe: • • The AT clause is not allowed because named pipes are always read with no offset. Summary of OSBWRITE Functionality with Named Pipes STATUS3 2 334 Developing UniBasic Applications . open/closed status. AT yes Empty1 no effect Open2 no effect NODELAY no effect Action ON ERROR executes.Managing Named Pipes OSBWRITE Syntax: OSBWRITE expr [ON | TO] file. Writing to Named Pipes The combination of the following conditions and command options determine the action taken by UniBasic when OSBWRITE is executed against a named pipe: • • • Presence and length of data in the pipe Open/closed status of the pipe Presence or absence of the AT and NODELAY command options The following table summarizes the actions taken by UniBasic when OSBWRITE is executed against a named pipe. the writing process waits until the pipe is opened for reading. NODELAY).Chapter 11 . the program aborts.var [AT byte. Note . Note If you do not specify NODELAY.ON ERROR executes regardless of other conditions (presence of data.

the ON ERROR clause executes. UniBasic first tries to write to the pipe.The INMAT function returns the length of data written to the pipe.OSBWRITE AT no no no Empty1 no effect yes no Open2 no yes yes NODELAY no effect no effect no Action ON ERROR executes. the ON ERROR clause executes. Tip . The program fails if ON ERROR is not specified. The process waits for sufficient space to become available in the pipe to contain the data being written. Developing UniBasic Applications 335 . when it runs out of space. the program aborts. STATUS3 6 0 0 after writing 3 no no yes yes Summary of OSBWRITE Functionality with Named Pipes 1Is enough space available in the pipe to receive the data? is the UniBasic STATUS function return value after this operation? 2What Writing to a Closed Named Pipe If the pipe is not open for reading. if no ON ERROR clause. UniBasic writes to the pipe. The program fails if ON ERROR is not specified. Writing to an Open Named Pipe Processing depends on whether the pipe contains sufficient space to accommodate the data being written: • Sufficient space available UniBasic writes to the pipe regardless of whether NODELAY is specified.

Managing Named Pipes • Sufficient space NOT available Processing depends on whether NODELAY is specified: • NODELAY specified – UniBasic first tries to write to the pipe. the INMAT function returns the length of data written to the pipe. PIPE_BUF determines the length of the named pipe. the length of data in expr must be less than or equal to the value of the PIPE_BUF system variable for the write to be atomic. NODELAY not specified – The process waits for sufficient space to become available in the pipe to receive the data. If the ON ERROR clause is not coded.Chapter 11 . the ON ERROR clause executes. The UniBasic STATUS function is set to 3. and the INMAT function returns the length of data written to the pipe. When all the data is written successfully. Maximum length is determined by the operating system. 336 Developing UniBasic Applications . the program aborts. when it runs out of space. • Warning On UniData for UNIX only.

If you do not specify the ON ERROR clause and a fatal error occurs. OSCLOSE Parameters Developing UniBasic Applications 337 .var ON ERROR statements Description Specifies the file to close.OSCLOSE OSCLOSE Syntax OSCLOSE file. an I/O error occurs. Parameter file. Specifies statements to execute if the OSCLOSE statement fails with a fatal error because the file is not open. or UniData cannot find the file.var [ON ERROR statements] Description The UniBasic OSCLOSE command closes a sequential file that was opened with the OSOPEN statement. Parameters The following table describes each parameter of the syntax. the program terminates.

STATUS Function Values Examples In the following example. the program statement closes the file UNDEF: Program Example OSCLOSE UNDEF Related Topics OSOPEN The UniBasic OSOPEN command opens an operating system–level sequential file. The file did not close. Return Value 0 5 Meaning The file is closed successfully. 338 Developing UniBasic Applications . the STATUS function returns one of the values described in the following table.Chapter 11 .Managing Named Pipes STATUS Function Return Values After you execute OSCLOSE.

• OSOPEN with the WRITEONLY option was executed against a pipe that was not open for reading. 4 5 6 The file does not exist. OSCLOSE. UniBasic STATUS Function Return Values Description Developing UniBasic Applications 339 . OSBREAD. Invalid file name or file variable. Undefined error.STATUS Function Return Values STATUS Function Return Values After you execute OSOPEN. NODELAY was specified. OSBWRITE was executed against a named pipe that is not open for reading. the STATUS function returns one of the values described in the following table. Execution against a named pipe: • OSBWRITE was executed against a pipe that is open for reading. or OSBWRITE. Return Value 0 1 2 3 Execution was successful. User lacks permission to access the file or pipe (at operating system level). but is full.

Managing Named Pipes INMAT Syntax INMAT() Description After you write to a named pipe.Chapter 11 . see INMAT in the UniBasic Commands Reference. the INMAT function return value contains the number of bytes written. 340 Developing UniBasic Applications . This information can help you determine how much space was available in a pipe at the time of an unsuccessful write. Note For additional syntax and return values for INMAT.

A process executes the ELSE clause of OSOPEN executed against a named pipe. opening a large number of named pipes at the same time can cause a process to try to open more than the maximum number of files allowed by the operating system. the process waits for it to be accessed in the opposite mode before proceeding. Data is only partially written to a named pipe. Developing UniBasic Applications 341 . Therefore. The pipe already contained some data when this process executed OSBWRITE. and a process tries to access (open. and the ON ERROR clause executes. Read operations work differently on named pipes versus other file types. UniData cannot temporarily close named pipes to manage the operating system’s limitation on the maximum number of files allowed to be opened at a time.The UniBasic INMAT function returns the number of bytes written. and NODELAY was specified in the write statement. a process has tried to write data to a named pipe whose length is greater than PIPE_BUF. or the program aborts. If NODELAY is not specified. Probable Cause On UniData for UNIX only. When UniBasic runs out of room in the pipe. Data read from a named pipe is removed from the pipe. the ON ERROR clause executes. Data read from other types of files is copied from the file. A process that manages named pipes appears to be hung. or the program aborts.Troubleshooting Troubleshooting The following information could be helpful in troubleshooting processes that manage named pipes: Symptom Data is only partially written to a file or a named pipe. read or write) a pipe that is not already open in the opposite mode. Tip . Troubleshooting Named Pipe Processes A named pipe is empty after a read.

.PIPE.@AM) PRIORITY = PRIORITY.PIPE.NAME TO PIPE(PRIORITY) ELSE MSG.Managing Named Pipes Example The following example demonstrates opening a named pipe.NAME GOSUB 9999 STOP END REPEAT .PIPES: *********** FOR I = 1 TO DCOUNT(PRIORITY..LIST<-1>=PRIORITY PIPE.ID TO PIPE(PRIORITY) RETURN .":PRIORITY NEXT I 342 Developing UniBasic Applications . writing record IDs to it..NAME = 'SF..LENGTH) OSBWRITE PIPE. *********** CLOSE.ID) PIPE.LIST. and closing it: Screen Example **************** OPEN.MAP LOOP READNEXT PRIORITY ELSE EOF = 1 UNTIL EOF PRIORITY.ID:STR(' '.PIPES: **************** EOF = '' SELECT FILE.ID = OUT.NAMED.TXT = 'Unable to open ':PIPE.PRIORITY.Chapter 11 .LENGTH = LEN(OUT.WIDTH-ID. ************************ 2110 * Write ID to pipe ************************ ID.PIPE.LIST<I> OSBWRITE SHUTDOWN TO PIPE(PRIORITY) PRINT "'SHUTDOWN' ISSUED TO SF.':PRIORITY OSOPEN PIPE.

.PIPE.ID FROM PIPE LENGTH PIPE.NAME = 'SF.ID IF IN.ID = "SHUTDOWN" THEN OSCLOSE PIPE @USER.' Developing UniBasic Applications 343 .Example This next example reads the IDs from the other end of the pipe: Screen Example PIPE.NAMED.PH.TXT = '"SHUTDOWN" received from SF.FILE.NAME GOSUB 9999 @USER. ************ PROCESS. GOSUB 9999.ID THEN IF INBOX.CODE=0 STOP END .REC<MB$COMPL_FLAG> = 0 THEN GOSUB 2005. * Print Message RETURN Ending program.RETURN.REC END END REPEAT MSG.TXT = 'Unable to open ':PIPE..PRIORITY OSOPEN PIPE.NAME TO PIPE ELSE MSG.READ.LOOP: ************ LOOP OSBREAD IN. * Process INBOX.WIDTH = 32 *************** OPEN.CODE = 1 EXIT END READ INBOX.WIDTH CONVERT ' ' TO '' IN IN.':P.RETURN.REC FROM IN. IN.PIPE: *************** PIPE.

Chapter 11 .Managing Named Pipes 344 Developing UniBasic Applications .

When an account number is given. CallHTTP is implemented with the Socket Interface as its network transport. you may want to integrate a general ledger application with a third party application that has already been webenabled. The web application then returns a confirmation to the UniBasic application. Many companies desire the capability to “call out” to the web from UniBasic so that their now standalone applications can be integrated with other applications through the web. the general ledger application has to send it to the web application through an HTTP request for validation.Using CallHTTP CallHTTP provides customers with the capability of interacting with a web server from UniBasic through the standard HTTP protocol. There are many scenarios where this capability can be beneficial. For example. you should have a working knowledge of the HTTP standard. and this lower level API is also available for direct access by the user. Developing UniBasic Applications 345 . The goal for CallHTTP is to provide a basic yet general implementation that enables UniBasic to act as an HTTP client so that data can be exchanged between a UniBasic application and a web server. not make UniBasic a browser of its own. E-commerce is increasingly becoming an essential part of any business. CallHTTP provides the “plumbing” for users to build a specific client. In order to effectively use the CallHTTP functions. Internet and web technologies have rapidly changed the way business is conducted by enterprises of all categories. HTTP is a complex standard with a large number of components and methods.Chapter 12 .

Parameter option value Description A string containing an option name. Parameters The following table describes each parameter of the syntax. These settings will be used with every HTTP request that follows.Chapter 12 .Using CallHTTP Configuring the Default HTTP Settings The setHTTPDefault function will configure the default HTTP settings. setHTTPDefault Parameters The following table describes the available options for setHTTPDefault. The port number to be used on the proxy server. including proxy server and port. HTTP version. buffer size. setHTTPDefault() should be called with value containing the proxy server name or IP address as well as the port (if other than the default of 80). and request header values. See the table below for the options currently defined. Option PROXY_NAME PROXY_PORT Description Name or IP address of the proxy server. Syntax setHTTPDefault(option. value) If you require all outgoing network traffic to go through a proxy server. A string containing the appropriate option value. authentication credential. This only needs to be specified if the port is other than the default of 80. setHTTPDefault Options 346 Developing UniBasic Applications .

Status Developing UniBasic Applications 347 . Per RFC 2616. Default Basic authentication can also be set. then any current user-specified default header will be cleared. Invalid Value. The default is 4096 however. UniBasic will search for the default credential to automatically re-submit the request. The size of the buffer for HTTP data transfer between UniData and the web server.1”. It should be entered as an integer greater than or equal to 4096. The header to be sent with the HTTP request.2”.Configuring the Default HTTP Settings Option VERSION Description The version of HTTP to be used. the only default header UniBasic sets automatically is “User-Agent” UniData 5.1 for web servers that understand the newer protocol. the buffer size can be increased to improve performance. The string should be “username:password”. for “net politeness”. A header should be entered as a dynamic array in the form of <HeaderName>@VM<HeaderValue>@Fm<HeaderName>@VM<HeaderValue>. The string should be ”1. setHTTPDefault Options BUFSIZE AUTHENTICATE HEADERS The following table describes the status of each return code. If you do not want to send out this header you should overwrite it with setHTTPDefault(). According to RFC 2616. the stamp will represent time in Universal Time (UT) format. but it can be set to 1. Return Code 0 1 2 Success. If default_headers contains an empty string. The default version is 1. The user name and password to gain access. Currently.0. Invalid option.0” or “1. If a request is denied (HTTP staus 401/407). an HTTP client should always send out this header. UniBasic will also send a date/time stamp with every HTTP request.

and 0 for PROXY_PORT and BUFSIZE. see the description under setRequestHeader(). To clear the default settings. 348 Developing UniBasic Applications . AUTHENTICATE and HEADERS.Chapter 12 . pass an empty string with PROXY_NAME. If you do not want the setting to affect subsequent programs. If the user wishes to set the “Authorization” or “Proxy-Authorization” header as defualts. you will need to clear it before exiting the current program.Using CallHTTP Note All defaults set by setHTTPDefault() will be in effect until the end of the current UniData session.

the following options are defined: PROXY_NAME PROXY_PORT VERSION BUFSIZE AUTHENTICATE HEADERS A string containing the appropriate option value. getHTTPDefault Parameters The following table describes the status of each return code. value) Parameters The following table describes each parameter of the syntax: Parameter option Desription Currently. Syntax getHTTPDefault(option. Return Code Status Status value Developing UniBasic Applications 349 .Getting the Current HTTP Default Settings Getting the Current HTTP Default Settings The getHTTPDefault function will return the default values of the HTTP settings. Return Code 0 1 Success. Invalid option. See the section under setHTTPDefault for additional information.

which usually defaults to 80 and is often omitted. request_handle) Parameters The following table describes each parameter of the syntax. if omitted. The path tells the web server which file you want.Using CallHTTP Creating an HTTP Request The createRequest function creates an HTTP request and returns a handle to the request.Chapter 12 . Syntax createRequest(URL. Method GET createRequest Methods Description http_method request_handle 350 Developing UniBasic Applications . The searchpart can be used to send additional information to a web server. A string which indicates the method to be performed on the resource. A handle to the request object. createRequest Parameters The following table describes the available methods for http_method. The port is the port number to connect to. The host can be either a name string or IP address. means “home page” for the system. The general format is: http://<host>:<port>/<path>?<searchpart>. and. along with the preceding colon. An accepted URL must follow the specified syntax defined in RFC 1738. See the table below for the available (case-sensitive) methods. http_method. Parameter URL Option A string containing the URL for a resource on a web server.

0. See addRequestParameter() Developing UniBasic Applications 351 . it must be in its encoded format (space is converted into +.1 and later but not supported */ /* HTTP/1.Creating an HTTP Request Method POST Description [:<MIME-type>] For this method. as described in function addRequestParameter() and submitRequest(). only “multipart/form-data” is internally supported.1 and later*/ /* HTTP/1. and other non-alphanumeric characters are converted into %HH format. the default content type will be “application/x-wwwform-urlencoded”. Currently. HEAD OPTIONS DELETE TRACE PUT CONNECT /* HTTP/1. Return Code 0 1 2 Success. it can also have an optional MIME-type to indicate the content type of the data the request intends to send.1 and later*/ /* HTTP/1.1 and later*/ /* HTTP/1. If no MIME-type is given. although other “multipart/* data can also be sent if the user can assemble it on his/her own. Invalid URL (Syntactically). (The multipart/form-data format itself is thoroughly described in RFC 2388).1 and later but not supported */ createRequest Methods The following table describes the status of each return code. Invalid method (For HTTP 1. only GET/POST/HEAD) Status Note If URL does include a searchpart.

352 Developing UniBasic Applications . Note This function can also be used later to support other protocols (like FTP. UniBasic will encode them before communicating with the web server./cwdN>/<name>.. host and path are allowed to have these “unsafe” characters.. The http_method option would be ignored for an FTP request.Using CallHTTP for more details).Chapter 12 . However.type=<typecode> . in which case the URL supplied would be in the form of: ftp://<user>:<pswd>@<host>:<port>/cwd1/.

Invalid request handle. Parameter request_handle header_name header_value Description The handle to the request returned by createRequest(). The value of the header. Return Code 0 1 2 3 Success. header_value) Parameters The following table describes each parameter of the syntax. Status Note Since a user defined header or header value can be transferred. it is difficult to check the validity of parameters passed to the function. Syntax setRequestHeader(request_handle. Invalid header (Incompatible with method). although it will reject setting a response header to a request. UniBasic currently will not perform syntax checking on the parameters.Setting Additional Headers for a Req uest Setting Additional Headers for a Request The setRequestHeader function allows the user to set additional headers for a request. The name of the header. setRequestHeader Parameters The following table describes the status of each return code. header_name. Invalid header value. Refer to RFC 2616 for Developing UniBasic Applications 353 .

Digest authentication may be supported in the future. 354 Developing UniBasic Applications .Using CallHTTP valid request headers. Note Only Basic authentication is supported. This function will then encode the text based on Base64 encoding.Chapter 12 . The header set by this function will overwrite settings by setHTTPDefault(). the header_value should then contain ASCII text user credential information in the format of “userid:password”. as specified by RFC 2617. If header_name contains either “Authorization” or “Proxy-Authorization”. Note This function supports Base64 encoding for Basic authentication. Basic authentication is not safe and is not recommended for use with transferring secured data.

Status Description Developing UniBasic Applications 355 . Parameter request_handle parameter_name parameter_value content_handling The handle to the request. parameter_name. content_handling) Parameters The following table describes each parameter of the syntax. Bad content type. addRequestParameter Parameters The following table describes the status of each return code. Return Code 0 1 2 3 Success. The dynamic MIME type for the parameter value. Invalid parameter.Adding a Parameter to the Request Adding a Parameter to the Request The addRequestParameter function adds a parameter to the request. The value of the parameter. The name of the parameter. Invalid request handle. Syntax addRequestParameter(request_handle. parameter_value.

the default for content_handling is “ContentType:text/plain” if content_handling is not specified. etc. ‘#’ is replaced by %23. spaces (‘ ‘) are converted into ‘+’. URL encoding is performed on data in parameter_value automatically. For a POST request with “Multipart/*” content-type. 356 Developing UniBasic Applications .dat” @FM Content-Length: 1923 Specifically. in the case of Content-Dispostion already in content_handling. for a POST request with content type “multipart/form-data”.Chapter 12 . content_handling is ignored. as described in createRequest(). file=”C:\drive\test. “form-data” will be added to it). For a POST method with other MIME-type specified.Using CallHTTP Note For a GET request.. For example. and ‘/’ is replaced by %2F. For both a GET and a POST request with either no content type specified or specified as “application/x-www-form-urlencoded”. One exception is that by convention. a “Content-Dispostion: form-data” header will be created (or. no encoding is done on data contained in parameter_value. content_handling is a dynamic array containing Content-* strings separated by field marks (@FM). any character other than alpha-numeric is considered “unsafe” and will be replaced by %HH where HH is the ASCII value of the character in question. For a POST request with default content type. Basically. An example of content_handling: Content-Type: application/XML @FM Content-Dispostion: attachment. They will be included in the multipart message before the data contained in parameter_value is sent.

If the user provides authentication information through “Authorization” or “Proxy-Authorization” header. For a POST request with non-empty post_data. Specifically. the status contained in the response is analyzed. and any parameters added through addRequestParameter() will be totally ignored. The request is then sent to the Web server identified by the URL supplied with the request and created through createRequest() (maybe via a proxy server). If later. If no Basic authentication request is found. The request is formed on the basis of default HTTP settings and previous setRequestHeader() and addRequestParameter() values. Developing UniBasic Applications 357 . no default authentication is found. followed by optional Content-* headers. the encoded information is cached. the function will return with an error. a Basic authentication request is raised. suggested by RFC 2616). it will be performed automatically. the data is attached to the request message as is. the response headers will be examined to see if the server requires (or accepts) Basic authentication.Submitting a Request Submitting a Request The submitRequest function will submit a request and get a response. No encoding is performed. the function will return with an error. For a POST request with multipart/* content type. If the response status is 401 or 407 (access denied). For a POST request with default content type. The total lentgth is calculated and a Content-Length header is added to the message header. If the response status indicates that redirection is needed (status 301. the parameter string will be assembled. up to five consecutive redirections (the limit is set to prevent looping. 302. Otherwise default Authentication (set by setHTTPDefault) will be used to re-send the request. and no other cached user authentication is found. 305 or 307). Once the response message is received. and data part. for a GET method with parameters added. Each will have a unique boundary. a ContentLength header created. UniBasic is then waiting for the web server to respond. and only one user/password encoding is cached. a prameter string (properly encoded) will be created and attached to the URL string after the ‘?’ character. a unique boundary string is created and then multiple parts will be generated in the sequence they were added through calling addRequestParameter(). then it will be used to re-send the request. and then the string is attached as the last part of the request message. Otherwise the following processing will be performed. If no default authentication is set.

response_headers. Return Code 0 1 Success. if a response contains header “Content-type: multipart/*”.) are supposed to be handled by the user. Invalid request handle. content-encoding (gzip. all the data (multiple bodies enclosed in “boundary delimiters”. A dynamic array to stre header/value pairs. Also. Syntax submitRequest(request_handle. In other words.Chapter 12 . http_status) Parameters The following table describes each parameter of the syntax. A dynamic array containing the status code and explanatory text. The timeout value (in milliseconds) before the wait response is abandoned. It is the user’s responsibility to parse the headers and data. see RFC 2046) will be stored in response_data. submitRequest Parameters The following table describes the status of each return code. UniBasic only performs transfer encoding (chunked encoding). Parameter request_handle time_out post_data response_headers response_data http_status The handle to the request. compress.Using CallHTTP The response from the HTTP server is disposed into response_header and response_data. etc. as with all MIME types. The data sent with the POST request. deflate. time_out. post_data. Status Description 358 Developing UniBasic Applications . and nothing else is done on the data. response_data. The resultant data (may be in binary format). It is the user’s responsibility to parse it according to “boundary” parameter.

Network Error. Other Errors. Status Developing UniBasic Applications 359 .Submitting a Request Return Code 2 3 4 Timed out.

A string containing a response header name. Return Code 0 1 2 Success. Parameter request_handle header_name header_value The handle to the request.Using CallHTTP Getting a Response Header This function gets a specific response header value from response headers returned by submitRequest(). Invalid request handle. getResponseHeader Parameters The following table describes the status of each return code. It can be used to query if a specific header. Status Description 360 Developing UniBasic Applications . is present in the response. header_value) Parameters The following table describes each parameter of the syntax. Header not found. The value of the header. for example. if present. an empty string. Content-encoding. Syntax getResponseHeader(request_handle.Chapter 12 . header_name. Otherwise.

log_action. protocolLogging Parameters The following table describes each log level and Detail. More detailed status data to assist debugging. Level 0 1 2 3 4-10 No logging. The default log file name is httplog and will be created under the current directory. Syntax protocolLogging(log_file. etc. The detail level of logging from 0 . Parameter log_file log_action log_level Description The name of the file the logs will be recorded to. log_level Details Detail Developing UniBasic Applications 361 . The default is “OFF”. Either “ON” or “OFF”. Level 2 logging plus all data actually transferred.10.). Socket open/read/write/close action (no real data) HTTP request: host info(URL) Level 1 logging plus socket data statistics (size. log_level) Parameters The following table describes each parameter of the syntax.Protocol Logging Protocol Logging This function will start or stop logging. See table below.

Return Code Status Status 362 Developing UniBasic Applications . Return Code 0 1 Success.Chapter 12 . Failed to start logging.Using CallHTTP The following table describes the status of each return code.

Using the Socket Interface The UniBasic Socket API provides the user with the capability of interacting with an application running on another machine via the sockets interface. For example. The server and the clients can cooperate on tasks through socket communication. one application. Developing UniBasic Applications 363 .Chapter 13 . This is an efficient way for UniBasic applications to communicate. written in the server side socket interface. can function as the server while others can function as clients. and is easy to implement. The Socket API enables you to write distributed UniBasic applications.

(NT: through WSACancelBlockignCall). an unknown flag was specified. The listen function was not invoked prior to accept. or the service provider is still processing a callback function. Error Code 0 . (NT) A successful WSAStartup() call must occur before using this function.SCK_ENOINITIALISED 2 .1 call is in progress. The socket is not connected.SCK_ENOBUFS 10 .SCK_EINTR 6 .SCK_EINVAL No error.Using the Socket Interface Socket Function Error Return Codes These error return codes are used for all socket-related functions described below.SCK_EFAULT 4 .SCK_EINPROGRESS 7 . The table below describes each error code and its meaning.SCK_EMFILE 9 . This can be caused by several conditions. or MSG_OOB was specified for a socket with SO_OOBINLINE enabled or (for byte stream sockets only) len was zero or negative.SCK_ENOERROR 1 .SCK_ENOTSOCK 364 Developing UniBasic Applications .SCK_ENOTCONN 5 . The (blocking) call was cancelled. The addrlen parameter is too small or addr is not a valid part of the user address space.SCK_ENETDOWN 3 . The network subsystem has failed. The descriptor is not a socket.Chapter 13 . Error Code Definitions Definition 8 . Note that only numeric code should be used in Basic programs. the socket has not been bound with bind. The queue is nonempty upon entry to accept and there are no descriptors available. No buffer space is available. A blocking Windows Sockets 1.

SCK_ESYSNOTREADY The option is unknown or unsupported for the specified provider or socket Indicates that the underlying network subsystem is not ready for network communication. or (for send()) the socket is message oriented.SCK_EACCES The requested address is a broadcast address. 19 . and the message is larger than the maximum supported by the underlying transport.SCK_ENOPROTOOPT 22 .SCK_EHOSTUNREACH 21 .SCK_ECONNRESET The connection has been dropped. The connection has been broken due to the keep-alive activity detecting a failure while the operation was in progress. The remote host cannot be reached from this host at this time. Call setsockopt with the SO_BROADCAST parameter to allow the use of the broadcast address. The virtual circuit was reset by the remote side executing a hard or abortive close. The socket is marked as nonblocking and the requested operation would block. 15 . The socket has been shut down. It is not possible to receive on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH. because of a network failure or because the system on the other end went down without notice.SCK_ECONNABORTED 18 . The application should close the socket as it is no longer usable. 20 . The virtual circuit was terminated due to a time-out or other failure.SCK_EWOULDBLOCK 13 .SCK_ENETRESET 14 . 16 .SCK_EOPNOTSUPP 12 .SCK_ESHUTDOWN Definition The referenced socket is not a type that supports connection-oriented service.Socket Function Error Return Codes Error Code 11 . The application should close the socket as it is no longer usable. but the appropriate flag was not set.SCK_ETIMEDOUT 17 . For UPD sockets.SCK_EMSGSIZE (For recv()) The message was too large to fit into the specified buffer and was truncated. Error Code Definitions Developing UniBasic Applications 365 . the remote host was unable to deliver a previously sent UDP datagram and responded with a “Port Unreachable” ICMP packet.

Memory allocation error. Valid name.SCK_EISCONN 38 . Nonauthoritative Host not found. The attempt to connect was forcefully rejected.SCK_EADDRINUSE Definition The version of Windows Sockets support requested is not provided by this particular Windows Sockets implementation.SCK_ENO_RECOVERY 34 . A process on the machine is already bound to the same fully-qualified address and the socket has not been marked to allow address re-use with SO_REUSEADDR. The specified protocol is the wrong type for this socket.SCK_EMALLOC 366 Developing UniBasic Applications .) The specified address is not a valid address for this machine.Chapter 13 . A nonblocking connect call is in progress on the specified socket.SCK_ECONNREFUSED 40 .SCK_EHOST_NOT_FOUND 31 .SCK_EACCESS 35 .SCK_EPROCLIM 25 .SCK_EPROTOTYPE 28 . no data record of requested type. A nonrecoverable error occurred. Authoritative Answer Host not found. For Windows CE AF_IRDA sockets only: the shared serial port is busy. (See the SO_REUSEADDR socket option under setsockopt. The specified address family is not supported.SCK_EBADF 30 .SCK_ETRY_AGAIN 32 .SCK_EALREADY 39 . The specified socket type is not supported in this address family. For example.Using the Socket Interface Error Code 23 SCK_EVERNOTSUPPORTED 24 . Limit on the number of tasks supported by the Windows Sockets implementation has been reached. Attempt to connect datagram socket to broadcast address failed because setsockopt option SO_BROADCAST is not enabled.SCK_EADDRNOTAVAIL 37 . The specifed protocol is not supported. The socket is already connected.SCK_EPROTONOSUPPORT 27 . or server failure. Error Code Definitions 36 . the IP address and port are bound in the af_inet case.SCK_EAFNOSUPPORT 26 .SCK_ESOCKTNOSUPPORT 29 .SCK_ENO_RECOVERY 33 .

SCK_EUNKNOWN Other unknown errors. Error Code Definitions Definition Developing UniBasic Applications 367 .Socket Function Error Return Codes Error Code 41 .

com) or IP address of a server. 0:non-blocking mode 1:blocking mode The timeout value expressed in milliseconds.Using the Socket Interface Opening a Socket Use the openSocket function to open a socket connection in a specified mode and return the status. A handle to the open socket. Syntax openSocket(name_or_IP. If you specify mode as 0. Parameter name_or_IP port mode timeout socket_handle Description DNS name (x.Chapter 13 . openSocket Parameters 368 Developing UniBasic Applications . If the port number is specified as a value <= 0. mode. Port number. CallHTTP defaults to a port number of 40001. timeout. timeout will be ignored. port. socket_handle) Parameters The following table describes each parameter of the syntax.

The timeout value is ignored. the function will either return with a valid socket handle or will time out after the specified timeout period. If the timeout value is 0. Mode Return Status The following table describes the status of each return code.Blocking Developing UniBasic Applications 369 . Status 1 . Mode 0 . Return Code 0 Non-zero Success. the function will block until either the socket is successfully opened. the underlying TCP/IP connection times out or some other error prevents the socket from opening. If a positive timeout is specified.Non-blocking Return Status The function will return immediately regardless of whether or not the socket is successfully opened. The return code inidcates if the operation is successful.Opening a Socket The following table describes the return status of each mode. See Socket Function Error Return Codes.

The following table describes the status of each return code. Return Code 0 Non-zero Success.Using the Socket Interface Closing a Socket Use the closeSocket function to close a socket connection.Chapter 13 . Syntax closeSocket(socket_handle) Where socket_handle is the handle to the socket you want to close. Status 370 Developing UniBasic Applications . See Socket Function Error Return Codes.

Getting Information From a Socket Getting Information From a Socket Use the getSocketInformation function to obtain information about a socket connection. Get information on the self end or the peer end of the socket. socket_info The following table describes each element of the socket_info dynamic array. self_ or_ peer. see the following table. Element 1 2 3 4 Open or closed Name or IP Port number Secure or Non-secure getSocketInformation Parameters Description Developing UniBasic Applications 371 . Specify 0 to return information from the peer end and non-zero for information from the self end. Dynamic Array containing information about the socket connection. For information about the elements of this dynamic array. Parameter socket_handle self_ or_ peer Description The handle to the open socket. Syntax getSocketInformation(socket_handle. socket_info) Parameters The following table describes each parameter of the syntax.

Return Code 0 Non-zero Success.Chapter 13 . Status 372 Developing UniBasic Applications .Using the Socket Interface Element 5 Blocking mode Description getSocketInformation Parameters The following table describes the status of each return code. See Socket Function Error Return Codes.

time_out. readSocket Parameters actual_read_size Developing UniBasic Applications 373 . 0:using current mode 1:blocking 2:non-blocking The number of characters actually read. The time (in milliseconds) before a return in blocking mode. blocking_mode. If this is 0. actual_read_size) Parameters The following table describes each parameter of the syntax. Syntax readSocket(socket_handle. The data to be read from the socket. socket_data. -1 if error. This is ignored for non-blocking read. then the entire buffer should be returned. Parameter socket_handle socket_data max_read_size time_out blocking_mode Description The handle to the open socket. max_read_size. The maximum mumber of characters to return.Reading From a Socket Reading From a Socket Use the readSocket function to read data in the socket buffer up to max_read_size characters.

Status 1 . Mode 0 . If there is no data in the socket. Return Code 0 Non-zero Success. the function will block until data is put into the socket on the other end. See Socket Function Error Return Codes.Non-Blocking Return Status The function will return immediately if there is no data in the socket.Blocking 374 Developing UniBasic Applications . If the max_read_size parameter is greater than the socket buffer then just the socket buffer will be returned.Chapter 13 . It will return up to the max_read_size character setting.Using the Socket Interface The following table describes the return status of each mode. Mode Return Status The following table describes the status of each return code.

Mode 0 . actual_write_size) Parameters The following table describes each parameter of the syntax.Blocking Return Status The function will return only after all characters in socket_data are written to the socket. socket_data. Mode Return Status actual_write_size Developing UniBasic Applications 375 . This is ignored for a non-blocking write. time_out. Parameter socket_handle socket_data time_out blocking_mode Description The handle to the open socket. The allowable time (in milliseconds) for blocking. The data to be written to the socket. writeSocket Parameters The following table describes the return status of each mode. 0:using current mode 1:blocking 2:non-blocking The number of characters actually written.Writing to a Socket Writing to a Socket Use the writeSocket function to write data to a socket connection. Syntax writeSocket(socket_handle. blocking_mode.

Chapter 13 .Non-Blocking Return Status The function may return with fewer character written than the actual length (in the case that the socket is full).Using the Socket Interface Mode 1 . See Socket Function Error Return Codes. Mode Return Status The following table describes the status of each return code. Status 376 Developing UniBasic Applications . Return Code 0 Non-zero Success.

The first optValue specifies if the option is ON or OFF and must be one of two possible values: “1” for ON or “2” for OFF. it should not be specified as it will be ignored.Setting the Value for a Socket Option Setting the Value for a Socket Option The setSocketOptions function sets the current value for a socket option associated with a socket of any type. for the “LINGER” option it contains the delayed time (in milliseconds)before closing the socket. Parameter socket_handle options Description The socket handle from openSocket().. The second optValue is optional and may hold additional data for a specific option. setSocketOptions Parameters Developing UniBasic Applications 377 . or initServerSocket(). acceptSocket(). The dynamic array is configured as: optName1<VM>optValue1a[<VM>optValue1b]<FM> optName2<VM>optValue2a[<VM>optValue2b]<FM> optName3. Dynamic Array containing information about the socket options and their current settings. Currently. options) Parameters The following table describes each parameter of the syntax. For all other options. Where optName is specified by the caller and must be an option name string listed below.. Syntax setSocketOptions(socket_handle.

Status 378 Developing UniBasic Applications . Enable/disable reception of out-of-band data in band. See Socket Function Error Return Codes. setSocketOptions Options The following table describes the status of each return code. Return Code 0 Non-zero Success. Set buffer size for input (default 4KB).Chapter 13 . Linger on close if data is present. Enable/disable permission to transmit broadcast messages. Enable/disable the reuse of a location address (default) Enable/disable keeping connections alive. Enable/disable routing bypass for outgoing messages. Option DEBUG REUSEADDR KEEPALIVE DONTROUTE LINGER BROADCAST OOBINLINE SNDBUF RCVBUF Description Enable/disable recording of debug information.Using the Socket Interface The following table describes the available options (case-sensitive) for setSocketOptions. Set buffer size for output (default 4KB).

Syntax getSocketOptions(socket_handle.Getting the Value of a Socket Option Getting the Value of a Socket Option The getSocketOptions function gets the current value for a socket option associated with a socket of any type. Options) Parameters The following table describes each parameter of the syntax.. Parameter socket_handle Description The socket handle from openSocket(). Developing UniBasic Applications 379 . acceptSocket(). or initServerSocket().

it contains the delayed time (in milliseconds) before closing the socket. The first optValue describes if the option is ON or Off and must be one of two possible values: “1” for ON or “2” for OFF. Where optName contains an option name string listed below.. Linger on close if data is present. The second optValue is optional and may hold additional data for a specific option. Enable/disable routing bypass for outgoing messages. Option DEBUG REUSEADDR KEEPALIVE DONTROUTE LINGER BROADCAST OOBINLINE Description Enable/disable recording of debug information. 380 Developing UniBasic Applications . When the options are returned... Enable/disable keeping connections alive.Chapter 13 . Enable/disable permission to transmit broadcast messages. getSocketOptions Parameters The following table describes the available options (case-sensitive) for getSocketOptions(). for option “LINGER”. Currently. Enable/disable the reuse of a location address (default).. the dynamic array is configured as: optName1<VM>optValue1a[<VM>optValue1b]<FM> optName2<VM>optValue2a[<VM>optValue2b]<FM> optName3.. the dynamic array is configured as: optName1<FM> optName2<FM> optName.Using the Socket Interface Parameter options Description A Dynamic Array containing information about the socket options and their current settings. When querying for options. Enable/disable reception of out-of-band data in band.

getSocketOptions Parameters The following table describes the status of each return code. Get and clear error on the socket. Get the type of the socket. Get buffer size for input (default 4KB). Return Code 0 Non-zero Success.Getting the Value of a Socket Option Option SNDBUF RCVBUF TYPE ERROR Description Get buffer size for output (default 4KB). See Socket Function Error Return Codes. Status Developing UniBasic Applications 381 .

Status port backlog svr_socket 382 Developing UniBasic Applications . See Socket Function Error Return Codes. Generally. If the port number is specified as a value <= 0. this parameter should be left empty. The handle to the server side socket. concurrent client-side connections).com) or IP address of a server or empty. Syntax initServerSocket(name_or_IP. svr_socket) Parameters The following table describes each parameter of the syntax. backlog. The maximum length of the queue of pending connections (i. CallHTTP defaults to a port number of 40001. Port number. Parameter name_or_IP Description DNS name (x. port.Chapter 13 . Associate this socket with an address (name_or_IP) and port number (port). initServerSocket Parameters The following table describes the status of each return code.Using the Socket Interface Initializing a Server Side Socket Connection Use the initServerSocket function to create a connection-oriented (stream) socket. Return Code 0 Non-zero Success. and specify the maximum length the queue of pending connections may grow to.e. Empty is equivalent to INADDR_ANY which means the system will choose one for you.

Timeout in milliseconds. The variable that receives the name of the incoming connection. acceptConnection() returns an error status code. acceptConnection Parameters time_out in_addr in_name Developing UniBasic Applications 383 . in_addr. 2 . Parameter svr_socket blocking_mode Description The handle to the server side socket which is returned by initServerSocket(). it will return nothing. If NULL. In this mode and the current blocking mode of svr_socket is set to blocking. timeout. in_name) Parameters The following table describes each parameter of the syntax. Syntax acceptConnection(svr_socket. In this mode if there are no pending connections present on the queue. acceptConnection() blocks the caller until a connection request is received or the specfied time_out has expired.Accepting an Incoming Connection Attempt on the Server Side Accepting an Incoming Connection Attempt on the Server Side Use the acceptConnection function to accept an incoming connection attempt on the server side socket.default (blocking) 1 . In this mode. The buffer that receives the address of the incoming connection. blocking_mode. time_out is ignored. it will return nothing.blocking. 0 .non-blocking. If NULL.

The server will use readSocket(). Status 384 Developing UniBasic Applications .Chapter 13 . See Socket Function Error Return Codes. acceptConnection Parameters The following table describes the status of each return code.Using the Socket Interface Parameter socket_handle Description The handle to the newly created socket on which the actual connection will be made. writeSocket(). etc. Return Code 0 Non-zero Success. with this handle to commuinicate with the client.

protocolLogging Parameters Level 0 1 2 3 4-10 No logging Detail Socket open/read/write/close action (no real data) HTTP request: host info(URL) Level 1 logging plus socket data statistics (size. log_level Details Developing UniBasic Applications 385 . log_level) Parameters The following table describes each parameter of the syntax. log_action. Level 2 logging plus all data actually transferred. The default log file name is httplog and will be created under the current directory. Either “ON” or “OFF”. Syntax protocolLogging(log_file.Protocol Logging Protocol Logging This function will start or stop logging.10. More detailed status data to assist debugging. etc. Parameter log_file log_action log_level Description The name of the file the logs will be recorded to.). The detail level of logging from 0 . The default is “OFF”. See table below.

Using the Socket Interface The following table describes the status of each return code. Status 386 Developing UniBasic Applications . Return Code 0 1 Success. Failed to start logging.Chapter 13 .

UPDATE_ORDER. This program uses the demonstration database files that are included with UniData. which is included at the end of this appendix. DISPLAY_MESSAGE. The program calls an external subroutine. Developing UniBasic Applications 387 .Sample Program The following sample program.Appendix A . demonstrates the use of some UniBasic commands in a simple application.

Delete.Include/Commons -----------------------* * Normally OPEN commands.Main Logic ----------------------------GOSUB INITIALIZE LOOP GOSUB DISPLAY_SCREEN GOSUB GET_ORDER_NUMBER UNTIL ORDER_NUMBER[1. EQUATEs.Appendix A .1] = 'Q' GOSUB DISPLAY_DATA IF RECORD_FOUND THEN GOSUB GET_RECORD_COMMAND RELEASE REPEAT GOSUB EXIT 388 Developing UniBasic Applications .Sample Program UPDATE_ORDER Program Example ** ** ** ** ** ** ** ** ** ** Program : Programmer : Created : Description: : : : : : : UPDATE_ORDERS Todd Roemmich 04/02/1996 Check and/or alter Order records Display Screen and ask for Order # Read record (if it exists) and display fields Prompt for a command (Alter. --TER EQU CLS TO @(-1) GOSUB OPEN_FILES *-------------. and DIMensions done with INCLUDE files. or Quit) A) Allow the user to change price or address D) Delete the record Q) Exit the program *-------------.

14):STREET2 IF STREET2 = '' THEN STREET2 = CLIENT.PRICE = "" DISPLAY @(10. and allow PRICE and ADDRESS to be changed.UPDATE_ORDER *-----------.REC<5> INPUT @(40."MR2$.17):"Zip:":@(40.TO.15):CITY IF CITY = '' THEN CITY = CLIENT.WRITE = 1 END NEXT ENTRY * Display DISPLAY DISPLAY DISPLAY DISPLAY DISPLAY DISPLAY the current ADDRESS information @(21.TO.REC<8> Developing UniBasic Applications 389 .13):STREET1 IF STREET1 = '' THEN STREET1 = CLIENT.PRICE NEW.REC<8> * Accept INPUT to change values of address INPUT @(40.17):CLIENT.REC<6> @(21.13):ADDRESS<2> @(21.14):ADDRESS<3>:@(21.16):CLIENT."MCN") IF NEW.9+ENTRY):OCONV(ORDER.REC<7> INPUT @(40.9):"New Price (Enter 2 decimal places)" * Change the PRICE field (if desired) FOR ENTRY = 1 TO NUM_ENTRIES NEW.8):"(Press RETURN to leave unchanged)" DISPLAY @(8. * Initialize variables and draw the screen NEED.13):"Street Line1: ":@(40.16):STATE IF STATE = '' THEN STATE = CLIENT.17):ZIP IF ZIP = '' THEN ZIP = CLIENT.12):"Change Address to: ": @(21.15):"City:":@(40.REC<6> INPUT @(40.14):"Street Line2:" @(40.PRICE NEED.WRITE = 0 DISPLAY CLS:@(15.REC<7.PRICE.15):CLIENT."): INPUT @(45.5):"Alter ORDER": DISPLAY @(10.ENTRY> = NEW.PRICE) THEN ORDER.16):"State:": @(40.REC<7>:@(21.PRICE # '' AND NUM(NEW.REC<4> INPUT @(40.ENTRY>.Subroutines -------------------------ALTER_RECORD: * Create a new screen.PRICE = OCONV(NEW.9):"Old Price":@(42.REC<7.9+ENTRY):NEW.

WRITE THEN to CLIENT. This is * determined by the number the user entered (ORDER_NUMBER).REC<2>."MT") CLIENT_NUMBER = ORDER. READU ORDER.REC<4> CLIENT.REC<7> CLIENT. ORDER_NUMBER RELEASE CLIENT_FILE.CLIENT_NUMBER.REC<5> CLIENT.REC<3> 390 Developing UniBasic Applications . RECORD_FOUND = 1 ORDER_DATE = OCONV(ORDER.Sample Program * Compare Old and New values (Write out new record if needed) NEW_CLIENT = STREET1:STREET2:CITY:STATE:ZIP OLD_CLIENT = CLIENT.REC<4>:CLIENT.REC<6> CLIENT.REC<6>:CLIENT.REC = STREET1 = STREET2 = CITY = STATE = ZIP GOSUB WRITE_RECORD END RETURN DELETE_RECORD: * (Assuming the order #'s are on line 12) READVU ORDER_LINE FROM CLIENT_FILE.TO.POSITION> END WRITEV ORDER_LINE ON CLIENT_FILE.REC<8> OLD_CLIENT) OR NEED.REC<7>:CLIENT.12 THEN LOCATE ORDER_NUMBER IN ORDER_LINE<1> SETTING POSITION THEN DEL ORDER_LINE<1.REC<8> IF (NEW_CLIENT # * Re-assign values CLIENT.CLIENT_NUMBER RETURN DISPLAY_DATA: * Display the current information in the desired record."D4/") ORDER_TIME = OCONV(ORDER. CLIENT_NUMBER.ORDER_NUMBER THEN * Read with a lock so that no one else can modify it at the same time. 12 END * DELETE ORDERS_FILE.Appendix A .REC<5>:CLIENT.REC<1>.REC FROM ORDERS_FILE.

UPDATE_ORDER ADDRESS = '' READU CLIENT.11):ADDRESS<5> PRODUCT_LINE = '' COLOR_LINE = '' QUANTITY_LINE = '' PRICE_LINE = '' NUM_ENTRIES = DCOUNT(ORDER. ":CLIENT.ENTRY> PRICE = OCONV(ORDER.ENTRY> QUANTITY = ORDER.8):ADDRESS<2> DISPLAY @(45.9):ADDRESS<3> DISPLAY @(45.7):ADDRESS<1> DISPLAY @(45.REC<7."MD2$.REC<3> ADDRESS<2> = CLIENT.15):PRICE_LINE DISPLAY ORDER_DATA END ELSE MESSAGE ="**(Record Does Not Exist)**" RECORD_FOUND = 0 Developing UniBasic Applications 391 .11):PRODUCT_LINE:@(13.14):QUANTITY_LINE:@(13.REC<7>:" ":CLIENT.REC<6>:".10):ADDRESS<4> DISPLAY @(45.ENTRY> COLOR = ORDER.REC<6.REC<4> ADDRESS<3> = CLIENT.CLIENT_NUMBER THEN ADDRESS<1> = CLIENT.REC<4.REC<4>.13):COLOR_LINE ORDER_DATA := @(13.@VM) FOR ENTRY = 1 TO NUM_ENTRIES PRODUCT_NUMBER = ORDER.REC<5> ADDRESS<4> = CLIENT.10):CLIENT_NUMBER "R#5" ORDER_DATA := @(13.") IF PRODUCT_LINE = '' THEN PRODUCT_LINE = PRODUCT_NUMBER "R#10" COLOR_LINE = COLOR "R#10" QUANTITY_LINE = QUANTITY "R#10" PRICE_LINE = PRICE "R#10" END ELSE PRODUCT_LINE := " ":PRODUCT_NUMBER "R#10" COLOR_LINE := " ":COLOR "R#10" QUANTITY_LINE := " ":QUANTITY "R#10" PRICE_LINE := " ":PRICE "R#10" END NEXT ENTRY ORDER_DATA = @(13.7):ORDER_DATE:@(13.REC FROM CLIENT_FILE.ENTRY>.REC<5.8):ORDER_TIME ORDER_DATA := @(13.REC<8> END DISPLAY @(45.

6): INPUT ORDER_NUMBER ORDER_NUMBER = OCONV(ORDER_NUMBER.15):"Price: " DISPLAY SCREEN RETURN GET_ORDER_NUMBER: * Have the user enter a valid key to a record in the ORDERS file."MCU") BEGIN CASE 392 Developing UniBasic Applications .1].6):"Order #: " := @(5.1):"ORDER MAINTENANCE":@(16. or the letter 'Q'" CALL DISPLAY_MESSAGE(MESSAGE) END UNTIL VALID_ORDER_NUMBER REPEAT RETURN GET_RECORD_COMMAND: * Enter a valid command to act upon (the Desired record is already shown).Sample Program CALL DISPLAY_MESSAGE(MESSAGE) END RETURN DISPLAY_SCREEN: * Display the starting screen SCREEN SCREEN SCREEN SCREEN SCREEN = CLS:@(25."MCU") IF NUM(ORDER_NUMBER) OR ORDER_NUMBER[1. or Q)uit: ": INPUT COMMAND. DISPLAY @(7.10):"Client #:" := @(5.22):"Enter A)lter.13):"Color: ":@(5. D)elete.1 COMMAND = OCONV(COMMAND[1.8):"Time: ":@(5.Appendix A .7):"Date: ":@(5.5):"(Enter Q to quit)" := @(5.14):"Qty: " := @(5. LOOP DISPLAY @(15.11):"Product #: ":@(5.1] = "Q" THEN VALID_ORDER_NUMBER = 1 END ELSE VALID_ORDER_NUMBER = 0 MESSAGE = "Order # must be a Number.

CLIENT_NUMBER WRITE ORDER." Developing UniBasic Applications 393 .REC ON CLIENT_FILE. Please try again" CALL DISPLAY_MESSAGE(MESSAGE) END CASE RETURN WRITE_RECORD: * The record(s) have been updated." OPEN_FILES: OPEN "CLIENTS" TO CLIENT_FILE ELSE MESSAGE = "The CLIENT file could not be opened.REC ON ORDERS_FILE. NESTED Transactions" DISPLAY "are NOT Allowed. TRANSACTION START ELSE IF STATUS() = 1 THEN DISPLAY "A Transaction had already been started. Make sure that if the RECOVERABLE * FILE System is operational that either BOTH records are updated. or that * None are (using Transaction processing commands). or Q.1_ END ELSE NULL END END WRITE CLIENT. (Contact System Administrator)" INPUT PAUSE.UPDATE_ORDER CASE COMMAND = "A" GOSUB ALTER_RECORD CASE COMMAND = "D" GOSUB DELETE_RECORD CASE COMMAND = "Q" FINISHED = 1 CASE 1 MESSAGE = "Valid options are A. D.ORDER_NUMBER TRANSACTION COMMIT IF STATUS() = 1 DISPLAY "The END ELSE DISPLAY "The END END RETURN ELSE THEN TRANSACTION was not started" TRANSACTION could not be committed.

Sample Program CALL DISPLAY_MESSAGE(MESSAGE) STOP END OPEN "ORDERS" TO ORDERS_FILE ELSE MESSAGE = "The ORDERS file could not be opened.Appendix A ." CALL DISPLAY_MESSAGE(MESSAGE) STOP END RETURN INITIALIZE: DISPLAY CLS PROMPT '' RETURN EXIT: DISPLAY CLS STOP RETURN 394 Developing UniBasic Applications .

21):"Press the (Return) key.20):MESSAGE DISPLAY @(5.DISPLAY_MESSAGE DISPLAY_MESSAGE The following example shows the external subroutine that is called by UPDATE_ORDERS: Program Example SUBROUTINE DISPLAY_MESSAGE(MESSAGE) DISPLAY @(5.1_ RETURN Developing UniBasic Applications 395 .": INPUT PAUSE.

Sample Program 396 Developing UniBasic Applications .Appendix A .

UniBasic Transaction Processing Concepts Note This appendix applies to UniData for UNIX only. When the transaction commits. If a transaction is aborted.Appendix B . see Administering UniData on UNIX. you must bind the operations by TRANSACTION START and TRANSACTION COMMIT statements. Developing UniBasic Applications 397 . “Chapter 9 . including how to create and convert to files. none of the operations within the transaction take place. all of the operations take place as one. To create a transaction. This chapter describes some basic concepts on which UniData transaction processing (TP) is based. the database maintains that consistent state when the transaction completes. and UniData can recover the updated file in the event of any failure.UniBasic Transaction Processing” introduces the UniData TP commands. UniData for Windows NT or Windows 2000 does not support transaction processing. This ensures that if a database is in a consistent state before a transaction starts. To learn more about recoverable files. and describes some TP programming problems and proposes solutions for those problems. TP executes a set of statements as a single logical function.

The following sections are included: • • “Transaction Processing Rules: The ACID Properties” “Transaction Isolation” • • • • “Transaction Processing Errors” “What Are Isolation Levels?” “Programming to Isolation Levels” “Updating Nonrecoverable Files in Transactions” 398 Developing UniBasic Applications .UniBasic Transaction Processing Concepts In This Appendix This appendix explains some of the concepts on which UniData Transaction Processing is based.Appendix B .

In UniData SQL. all transactions are properly isolated. If locks are properly set and checked. a desired isolation level is set by specifying the isolation level with the set transaction command. writing a new record will guarantee that the record and the indexes are both written. it will be in a consistent state afterwards. They will all succeed or all fail. a default isolation level is handled by the database engine. The record will not be written without its associated indexes. For example. Isolation is controlled within UniBasic applications. Developing UniBasic Applications 399 . If a database is in a consistent state before you apply a logical operation. If no isolation level is specified. Consistency The components of a logical operation all succeed or all fail.Transaction Processing Rules: The ACID Properties Transaction Processing Rules: The ACID Properties The ACID properties in the following list distinguish transactions from non-TP database updates: • • • • Atomicity Consistency Isolation Durability Atomicity Logical operations grouped by transaction semantics are treated as one unit. Isolation Isolation means that operations are based on a consistent database rather than on intermediate results from other operations.

400 Developing UniBasic Applications .Appendix B . If UniData stops running. the database recovers to the last committed transaction when you restart UniData. Recovery techniques are available to provide durability in the case of media failure.UniBasic Transaction Processing Concepts Durability Durability means that completed transactions are preserved in the database despite failures.

Reminder UniData SQL protects against lost updates in all transactions.Transaction Isolation Transaction Isolation Even though transactions appear to process sequentially and atomically. as in the examples provided later in this chapter. For this reason. they actually occur serially. and provides templates for programming to each isolation level. The following sections describe these errors: • • • “Lost Updates” “Dirty Reads” “Unrepeatable Reads” Lost updates. but UniBasic does not. but could allow phantoms. Transaction Processing Errors You can get unexpected results when transactions process concurrently. but could allow lost updates. UniBasic and UniSQL TP differ in the following ways: • UniData SQL always protects against lost updates and dirty reads. dirty reads. and unrepeatable reads can be prevented by designing applications appropriately. • UniBasic always protects against dirty reads and phantoms. the updates from one transaction are overwritten by those of another. Developing UniBasic Applications 401 . Note UniData SQL follows ANSI '92 standards. the types of transaction errors that can occur and the isolation levels that can be achieved differ between the two products. This section identifies transaction errors. Lost Updates In a lost update. isolation levels. Isolation is determined by the degree to which transaction errors are prevented.

var. record1 WRITE var TO file. Within a transaction. changing the record to a different value.var. In two separate write operations. record1 ELSE PRINT “Record not found. Transaction Segment 2 changes Record1’s value to 2.” READ var FROM file. this read is considered dirty. Program Segment 1 Transaction Segment 2 TRANSACTION START THEN PRINT “Transaction started. Dirty Reads A dirty read occurs when one of two scenarios takes place: • Within a transaction.” Program Segment 1 and Transaction Segment 2 are run concurrently.UniBasic Transaction Processing Concepts Consider the following example: Reminder UniData SQL protects against lost updates in all transactions. is lost. a record is changed. record1 TRANSACTION COMMIT THEN PRINT “Transaction committed. The update in Program Segment 1. Because the second transaction changes the value after the read. record1 ELSE PRINT “Record not found” var += 1 var += 2 WRITE var TO file.var. then to 3.” READ var FROM file. a second transaction process reads the record. • 402 Developing UniBasic Applications . Program Segment 1 could lose updates because the record is not locked between its READ and WRITE. then the first transaction process aborts and rolls back.var. The value obtained by the second transaction is dirty.Appendix B . a process reads an attribute value between two updates made by a second transaction. made between the two writes.

finally. As a result. Consider the following example: Program Segment 1 Transaction Segment 2 TRANSACTION START THEN PRINT “Transaction started.var. record1 TRANSACTION COMMIT THEN PRINT “Transaction committed.var. Transaction Segment 2 writes a record. another transaction updates the record.” var += 2 WRITE var TO file.Transaction Isolation Reminder UniBasic protects against dirty reads in all transactions. The record value obtained by Program Segment 1 is no longer current. This is an unrepeatable read. record1 ELSE PRINT “Record not found. Unrepeatable Reads Between two reads of a record in a transaction.var. Transaction Segment 2 makes additional changes to the record. record1 READ var FROM file. then Program Segment 1 reads it. the first transaction obtains a different value for the same attribute on the second read.” Program Segment 1 and Transaction Segment 2 are run concurrently. Developing UniBasic Applications 403 .” ELSE STOP var = 1 WRITE var TO file.

UniData SQL automatically initiates and commits transactions and provides the level of isolation appropriate for the type of operation being executed. record1 ELSE PRINT “Record not found.” var = 2 WRITE var TO file.” TRANSACTION COMMIT THEN PRINT “Transaction committed. To achieve atomicity at this level. The following list describes four theoretical isolation levels: • Isolation level 0 exposes transactions to any type of TP error.” READ var FROM file. UniBasic TP does provide the following protection: records are automatically locked during write operations.UniBasic Transaction Processing Concepts Consider the following example: Program Segment 1 Transaction Segment 2 TRANSACTION START THEN PRINT “Transaction started. record1 ELSE PRINT “Record not found. and all locks set during a transaction are retained until the transaction is committed or aborted. Program Segment 1 reads a record twice before and after Transaction Segment 2 updates it. see Using UniData SQL.var. The application program must provide protection from transaction errors by setting shared locks on records being read and by setting exclusive locks on records being updated. but cannot overwrite the updates from transactions at isolation level 1 or higher. UniBasic TP does not implicitly enforce isolation levels.var. dirty reads.var. 404 Developing UniBasic Applications . Unlike UniBasic. For more information. The two read operations return different values for the record. record1 READ var FROM file. and unrepeatable reads) that are allowed or not allowed. What Are Isolation Levels? The isolation level determines the type of transaction errors (including lost updates.” Program Segment 1 and Transaction Segment 2 run concurrently.Appendix B . the application must set exclusive locks on records being updated.

Transaction Isolation

Isolation level 1 protects transactions against lost updates but allows dirty reads and unrepeatable reads. When you execute a read operation, the system automatically locks records being updated. Isolation level 2 protects transactions against lost updates and dirty reads, but allows unrepeatable reads. Note: UniBasic automatically protects against dirty reads; therefore, if you program to protect against lost updates, you achieve isolation level 2. Isolation level 3 protects transactions against all three types of TP errors: lost updates, dirty reads, and unrepeatable reads.

Note
The ANSI-standard isolation levels available through UniData SQL differ from these because of the differences in product design described at the beginning of this section.

Programming to Isolation Levels
This section provides program templates that demonstrate how to program in UniBasic to achieve different levels of isolation.

Example: Programming to Isolation Level 0
The following program template provides no protection against TP errors. It is programmed for isolation level 0. Unlike the theoretical situation depicted by this example, UniBasic and UniData SQL provide some protection against TP errors.

Program Example
TRANSACTION START THEN PRINT "Transaction started." ELSE PRINT "Transaction start failed, STATUS = ":STATUS() READ var FROM file.var, record1 ELSE PRINT "Record not found." var += 2 WRITE var TO file.var, record1 TRANSACTION COMMIT THEN PRINT "Transaction committed." ELSE PRINT "Transaction aborted, STATUS = ":STATUS()

Developing UniBasic Applications

405

Appendix B - UniBasic Transaction Processing Concepts

Example: Programming to Isolation Level 2
The following program template illustrates programming for isolation level 2, which protects against lost updates and dirty reads. After the record is locked by the second read (READU), the transaction is protected against lost updates.

Program Example
TRANSACTION START THEN PRINT "Transaction started." ELSE PRINT "Transaction start failed, STATUS = ":STATUS() READ var FROM file.var, record1 . . . REM "If another transaction changes record1 here, its updates are lost" . . . READU var FROM file.var, record1 ELSE PRINT "Record not found." var += 2 WRITE var TO file.var, record1 TRANSACTION COMMIT THEN PRINT "Transaction committed." ELSE PRINT "Transaction aborted, STATUS = ":STATUS()

406

Developing UniBasic Applications

Transaction Isolation

Example: Programming to Isolation Level 3
The following program template illustrates programming for isolation level 3. All three types of transaction error are prevented because the record is locked by READU the first time it is read.

Program Example
TRANSACTION START THEN PRINT "Transaction started." ELSE PRINT "Transaction start failed, STATUS = ":STATUS() READU var FROM file.var, record1 ELSE PRINT "Record not found." var += 2 WRITE var TO file.var, record1 TRANSACTION COMMIT THEN PRINT "Transaction committed." ELSE PRINT "Transaction aborted, STATUS = ":STATUS()

Developing UniBasic Applications

407

Appendix B - UniBasic Transaction Processing Concepts

Updating Nonrecoverable Files in Transactions
UniData TP is effective only on recoverable files. An update to a nonrecoverable file is never part of a transaction, even when executed within a transaction. UniBasic updates the file, but with the following conditions: • • The write operation takes place immediately, even before the transaction commits. The write is not rolled back in the event of a transaction abort or restart after a system crash.

Warning
UniData records only updates made while a file is recoverable. Remember this when you change a file to or from the recoverable state.

408

Developing UniBasic Applications

Index

Symbols
!, 70 -, 159 , 46, 303 #, 47, 307 #<, 45, 307 #>, 45, 307 $, 70 $$FUN heading, cfuncdef file, 224 $$LIB heading, cfuncdef file, 226 $$OBJ heading, cfuncdef file, 226 $BASICTYPE, 62, 196 $DEFINE, 62 $ELSE, 63 $IFDEF, 63 $IFNDEF, 63 $INCLUDE, 63 $INSERT, 63 $UNDEFINE, 62 * commenting a program, 18 multiplication, 159 null value and, 303 **

exponentiation, 46, 159 *=, multiplication, 160 +, 159, 303 +=, increment variable, 160 /, division, 46, 159 /=, division, 160 : concatenation, 159 null value and, 317 :=, concatenation, 160 <, 45, 307 <=, 45, 307 <> EXTRACT function, 158 not equal to, 45 null value and, 307 = equal to, 45, 47 in cross reference report, 70 null value and, 307 –=, decrement variable, 160 =<, 45, 47, 307 =>, 45, 47, 307 >, 45, 47, 307 ><, 45, 47

Developing UniBasic Applications

409

Index

>=, 45, 47, 307 @ in cross reference report, 70 @AM, 24 @FM, 24 @NULL, 24 @RM, 24 @SM, 24 @TM, 24 @TRANSACTION, 288 @USERNO, 84, 84 @variable @TRANSACTION, 288 introduction to UniBasic, 27 @VM, 24 [] EXTRACT, 157 null value and, 317 replace, 168 ^ exponentiation, 46, 159 null value and, 303 {, delimiter, 150 {}, calculate, 195 |, delimiter, 150 }, delimiter, 150 ~ converting nonprinting characters, 169 delimiter, 150

A
ABORT program control commands, 49 ABS, 164, 303 absolute value, 164 ACID properties, 399 ACOS, 164, 303

active transaction, testing for, 288 add see also WRITE addition, 46, 159 advisory lock, 136 AE compiling in, 59 creating a program with, 53 help, 56 introduction, 59 running a program from, 82 unable to find file, 54 ALPHA, 156 null value and, 316 alphabetic character in array, 158 alternate index creating and managing, 109 alternative editor compiling in, 59 introduction, 53 AND, 47 arc cosine, 164 arc sine, 164 arc tangent, 164 argument command or function and the null value, 303 arithmetic operation introduction, 159 on dates, 176 arithmetic operations and data type , 161 array converting data in, 168 dimensioned, 149 dynamic, 149 finding elements in, 156 left-justifying elements, 169

410

Developing UniBasic Applications

Index

summary of commands, 151, 154 types, 26, 149 array element testing for null value, 316, 318 ASCII character, converting, 168, 172 converting from numeric to, 170 function, 168 null value and, 316 ASIN, 164, 303 assigning null value, 315 value to variables, 25 AT, 330, 334 ATAN, 164, 303 atomicity, 399 attribute virtual, 195 attribute mark in UniBasic, 24

bottleneck, 142 BP file, 53 branching, 48 BREAK, 206 break key in transaction processing, 287 BUILD.INDEX transaction processing and, 294 business rules, 96

C
C program calling UniBasic subroutine, 235 writing, 219 CALCULATE, 195 calculations and data type, 161 CALL executing programs, 193 extending statements over multiple lines , 20 introduced, 33 program control commands, 49 callbas.mk, 218, 236 CallBasic compiling and linking the C program, 235, 243 U_callbas function, 275 udtcallbasic function, 271, 275 udtcallbasic_done function, 275 udtcallbasic_done( ) function , 238 udtcallbasic_init function, 275 writing the UniBasic subroutine, 235, 236, 273 CALLC _cdecl calling convention, 264 data types, 261 PASCAL calling convention, 264 program control commands, 49

B
base logarithm, 164 BASIC compiling programs, 59 options, 60 BASICTYPE, 61, 196 binary data, converting, 172 data, maintaining, 112 BITAND, 303 BITNOT, 303 BITOR, 303 BITXOR, 303 Boolean operator, 44 null value in, 307

Developing UniBasic Applications

411

Index

syntax, 260 called program starting a transaction in, 294 calling C functions from UniBasic, 219 external functions from UniBasic , 264 UniBasic subroutines from C , 235 UniBasic subroutines from external program , 272 CASE conditional tests, 38 introduced, 41 null value in, 305 program control commands, 49 CAT, 317 CATALOG examples, 79 options, 77 cataloged program determining version, 74 cataloging direct, 74 global, 75 local, 75 programs, 73 CATS, 317 cfuncdef, 224 CHAIN in transaction processing, 287 program call commands, 194 program control commands, 49 CHANGE, 181, 316 CHAR, 168, 181, 316 character conversion, 168 lower case, 169 nonprinting, 169 upper case, 169

CHARS, 181, 316 CLEAR.FILE transaction processing and, 294 CLEAR.LOCKS, 136 CLEARDATA, 193 clearing data stacks, 193 select lists, 118 CLEARINPUT, 204 CLEARSQL, 197 CLOSE, 128 CLOSESEQ, 113 closing files in programs, 128 non-UniData files, 114 sequential files, 337 CNAME transaction processing and, 294 code interpretive/object, 59 COL1, 157, 181 COL2, 157, 181 colon null value and, 317 command udtcallbasic_done, 272 udtcallbasic_init, 268 command argument and the null value, 303 commands, UniBasic, 17 comments, adding to a program, 18 COMMIT, 285 committing transactions inappropriately, 282 COMMON, 189, 189 comparison null value in, 302, 307 compiler directive commands, 62

412

Developing UniBasic Applications

36 program control commands. 123 DATA stack. 156. 164 COUNT. 290 transaction processing and. 164. updating. 169 null values. 169. 154 recoverable file.Index directive. 16 UniBasic. 399 constant representing data. 29 conversion functions. 181. 294 CREATE. 176 Developing UniBasic Applications 413 . 317 CPIO format in transaction processing. 156. 49 control statement. 105 CONTINUE loop commands. 313 CONVERT. 172 determining type. 166 in UniBasic programs. 170 copying array elements to variable. 203 data type calculations and. 68 CRT. 161 character. 23 formatting. 93 relational. 279. 16 controlling looping. 46 operators. 305 order of precedence. 16 compiling programs. 303 cosine. 47 types. 317 COUNTS. 98. 316 command.INDEX transaction processing and. 44 representing in programs. 182. 181 converting characters. 290 CREATE. defined. 155 file types. 279 nonprinting characters.FILE transaction processing. 166 files to transaction processing. 168 data. 25 constraint violation. 168 date and time. 16 null value in. 159 operator precendence. defined. 61 concatenation introduction. 44 conditional test see also logical operator defined. 158 COS. 20 data binary. 112 converting numbers. 290 UniBasic program. 302 numbers. null value in . 147 stack. 160 conditional operator. 38 consistency. 49 program execution. 294 creating dimensioned array. 191 writing to a file. 205 D DATA. 59. 51 cross reference report.

395 displaying null value in UniBasic. 316 DROUND. 126 delimiter defining. DIMENSION.ACTION BELL. 175 internal and display format. 259 double spacing. 160 default file. 177 DCOUNT. 153 DIR. 175 rules for entering. 69 division arithmetic operators. 317 deadlock avoiding. 203 DIM. 59 directory file (BP).LOCKED. 115 DEFAULT. 150 demonstration database UniBasic program using. 78 direct catalog. 172 UNIX C definitions. 142 triggers. 154 dimensioned array defined. 259 CALLC implementation. 259 UniData NT and DLL. 317 DIRECT. 205 display format. 158 in dynamic arrays. 387 device. 26 using. 114 trigger subroutine. 102 DELETE. 98 deleting records. 294 DELETE. 210 DOWNCASE. 176 display terminal commands.Index numeric.INDEX transaction processing and. 303 durability. data and time. 402 DISPLAY. 317 DELETE. 400 dynamic array 414 Developing UniBasic Applications . 317 invoking triggers with. 150 representing in UniBasic. 160 operator precedence. 172 decrement value in variable.FILE transaction processing and. 74 directing the compiler. 297 DEL. 24 UniBasic. 225 database maintaining consistency. 53 dirty read. 68 decimal converting data. 294 DELETEU triggers. 142 debugger cross referencing in UniBasic. 98 non-UniData files. 46 DLL CallBasic implementation. suppressing. 142. 182. 205 DISPLAY_MESSAGE sample program. 156. output. 301 statements and variables in the debugger . 96 date converting and formatting. 169. 293 causes. 159 combined operators. 135 degraded performance.

49 exit. 317 field length. 157 F FI. 47 EQS. 316 ECHO. 84 EXIT loop commands.OPTIONS and. 56 FIB. 49 ENTER. 221 exiting CallBasic. 168 defined. 298 ELSE transaction processing. 133 EXECUTE program control commands. 36 program control commands. 176 interaction. 203 in C function. 265 EX. 49 EXECUTE SELECT. 33 external interaction getting system information. 194 EQ comparison operator.Index converting data in. 307 conditional tests. 303 exponentiation. 243. 211 UDT. 82 execution time reporting. 168. 158. 317 Developing UniBasic Applications 415 . 149 dynamic link library (DLL). 395 EXTRACT. 57. 206 ED (editor). 46. 159 external date and time format. 272 EXP. 27 external program calling UniBasic subroutine. 53 efficiency transaction processing. 317 extracting commands. 266 EBCDIC. 205 FIELDS. 182. 211 END program control commands. 264 external subroutine sample program. 195 subroutines. 26 using. exceeding during data entry . 56 exclusive lock. 49 executing UniBasic programs. 272 writing. 197 program control commands. 317 FIELDSTORE. 307 error message. 164. 265 exit( ). 59 FIBR. 155 data from arrays. 60. 82 FIELD. 117 EXECUTESQL example. 283 empty strings selected attributes in a file. 158. 220 in external function. 262. 259 E E type VOC entry.

57 FLOAT. 337 type. 317 GT conditional tests. 160 floating point. 171. 182. 274 writing to. 123 FILEINFO writing programs. 78 formatting arrays and strings. 317 GLOBAL. 168 FOOTING. 49 greater than conditional tests. 75 GOSUB executing subroutines. 77 global catalog. 56 FIND. UniData. 137 GETUSERGROUP. 275 udtcallbasic. 110 file-level operation. 166 numbers. closing. 47 null value and. 107 opening. 259. 182 GETPTR. 152. 275 udtcallbasic_init. 36 program control commands. 294 filing programs. creating or converting . 49 FORCE. 166 defined. 168 dates. 275 G GE conditional tests. 279 recoverable. 171 FUNCTION writing trigger. 128 default. 317 GETUSERNAM. 313 FMTS. 129 closing. 307 GES. 307 GET. 176 functions for.PRECISION. 133 maintaining binary. 157. 290 sequential. 160 FMT. 307 416 Developing UniBasic Applications . 112 maintaining through programs. 115 recoverable. 303 U_callbas. 317 FIR. 47 GROUPSTORE. 209 FOR/NEXT example. 31 program control commands. 20 loop commands. 164 null value in.Index file accessing unopened. 317 FINDSTR. 17 mathematic. 112 maintaining non-UniData. 115 deleting records from. 317 GETPU. 275 udtcallbasic_done. 317 GETREADU. 126 locks. 45 null value and. 23 UniData. 99 function conversion.LIB.

205 ICONV. 49 INCLUDE. 164. 243 UniBasic program. 272 udtcallbasic_init function. 204 INPUTNULL. 205 I I/O function. 245 makefile command. 166 null value and. 204 INS. 209 HELP for AE. 302 initial caps converting to. 164 value.Index GTS. 109 indexing null values. 313 IF/THEN/ELSE conditional tests. 317 INSERT compiler directive. 171 obtaining a random. 157. 182 index alternate. 236. 20 null value and. 341 HUSH. 169 INMAT dimentioned arrays and. 228 interfacing with external program U_callbas function. 182 INPUT@. 57 hexadecimal converting data. 340 INPUT. 203 INPUTIF. 173 hung process named pipes and. 63 increment variable. 25 INPUT @. 307 H hashed file maintaining through programs. 241 udtcallbasic_done function. 203 INPUTTRAP. 176 interpretive code. 269 udtcallbasic_done function. 305 program control commands. 204 INPUTERR. 38 formatting long statements. 268 internal format date and time. 243 U_callbas function. 175 international format for dates. 301. 182 input device. 203 into variables. 164 interfacing with C invoking C programs. 63 null value and. 107 HEADING. 57 INT. 182 converting and formatting. 303 integer converting. 160 INDEX. 154 named pipes and. 59 Developing UniBasic Applications 417 . 317 insert mode in AE. 203 INPUTCLEAR.

401 programming to level 0. 307 conditional tests. 134 label in program subroutines. 164 ISNV. 317 LES comparison operator. 182. 157. 44 see also conditional test logical operator null value and. 137 released by TRANSACTION COMMIT. 319 isolation defined. 399 dirty reads. 137 using UniData. 47 limitation file-level operations. 155. 294 UniData SQL. 317 length string or array. 133 UniBasic commands. 137 LIST. 403 K key break. 297 418 Developing UniBasic Applications . 196 LN null value and. 215 LIST. 164 logical condition. 294 screen generator. 287 introduction to UniBasic. 401 preventing errors. 131 LOCKED clause. 156 LENS. 405 programming to level 2. 152. 164 LOCAL. 317 locating data in array. 140 obtaining user number.READU. tangent . 294 report generator. 297 types. 406 programming to level 3. 137 commands. 404 lost update. 19 LE comparison operator. 157 lock checking status. 53 Linking programs with UniData. 402 levels. 137. 307 less than conditional tests. sine. ISNVS.Index interrupt key in transaction processing. 287 L L lock. 13 inverse cosine. 156. 77 local catalog. 285 transaction processing. 407 unrepeatable reads. 303 numeric function.QUEUE. 138 logarithm. 182. statement. 32 layout. when to use. 294 line editor. 69 LIST. 75 LOCATE. 47 LEN. in transaction processing . 307 long transaction performance.

283 transaction in transaction processing. 218. 156 McDonnell Douglas. 219 variables in external function. 164 modify see also WRITE modifying data. 164 MATPARSE. converting . 303 numeric function. 159 operator precedence. 43 Developing UniBasic Applications 419 . 150 files. 326. 334 naming variables in C function. 168 N named pipes introduction. 154 MATBUILD. 307 conditional tests. 327 troubleshooting. 169 LT. 107 make command. 323 opening. 166 numbers. 401 lost updates. 334 nonprinting character. 330. 196 MINIMUM. 236. 307 M maintaining dimensioned arrays. 160 arithmetic operators. 293 NEWPCODE. 341 write access. 46 MOD null value and. 264 NE conditional tests. 171 multiplication. 182. 45 MATCHFIELD. 307 LTS. 155 MATCH. 78 NODELAY. 227 MAT. 62 MDPERFORM. 317 conditional tests. 182. 45 null value and. 45 MATCHES. 21 transaction. 317 in conditional tests. 154 dynamic arrays. 245 makefile. 326 writing to. 36 lost update. 182. 326. 142 lowercase converting to. 317 math functions.Index LOOP/REPEAT program control commands. 46 multivalued attribute formatting for output. 169 NOT. 243 makeudapi. 50 looping commands. 307 nested statement. 74 NEWVERSION. 228 makeudt. 156 minus operator precedence. 307 NES. 155 MAXIMUM.

159 converting and formatting. 316 in IF/THEN/ELSE. 47 not less than conditional tests. 182. 299 NOT. 113. 46 OR. 156 number arithmetic operations. 307 null value ASCII value for. 171 numbering system. 113 output device. 98 ON/GOSUB program control. 316 testing for data type. converting . 113. 330 OSBWRITE. 47 not greater than conditional tests. 166. 315 CASE. 113 OSOPEN. 323. 155. 38 introduction to UniBasic. 334 OSCLOSE. 301 NUM null value and. 158 random. 226 OCONV. 337 OSDELETE. 316 determining ASCII code. 113. 203 420 Developing UniBasic Applications .Index not equal to conditional tests. 308 found when numeric required. 326 OSREAD. 59. 158. 294 operator arithmetic. 113. 315 NULL_VAL_ALT_KEY. 323. 307 OSBREAD. 159 Boolean. 303 NUMS null value and. 44 precedence. 36. 315 effects on conditional tests . 170 numeric calculation null value in. 316 O object code. 164 rounding. 313 octal converting data. 47 NOTS. 113 OSWRITE. 50 opeining a named pipe. 171 scaling. 115 non-UniData files. 300 assigning to a variable. 17. 113 operation file-level. 323 writing to a named pipe. 302 numeric data conditional tests of. 24 testing for. 173 ON ERROR triggers. 41 converting. 43 numeric calculations. 169. 326 OPEN file commands. 44 numeric functions and the null value. 161 representing in UniBasic. 170 locating data in array. 114 OPENSEQ.

265 page feeds. 191 PCPERFORM program control commands. converting to. 209 PRINTER OFF. 59 executing a transaction start within. 341 position. 110 READFWDU. 155 POWER null value and. 169 Pick® Basic. 84 program call interface. 147 program control. 205 passing arguments to C functions. AE command. 110 READBCKL. 209 printing in a C function. 220 arguments to external functions . 49 programming in UniBasic. 111 Developing UniBasic Applications 421 . locating data in array. 209 printer output. 209 PRINT @. 209 terminal control commands. returning. 208. 264 data through a stack. 84 stopping with ABORT. determining in array. 220 in an external function. 110 READFWD. 50 PERFORM program control commands. 210 right-justified data. 223 cataloging. 161 PRINT. 110 READFWDL. 56 R random integer. 110 READBCKU. 294 profile. 57 packed decimal. quitting AE. 201 profile program. 205 PRINT ON.Index P P. 206 PWR null value and. 297 phonetic code. 171 PAGE printer control. 209 PRINTER ON. 114 READBCK. 235 writing. 164 Q Q. 164 range. 325. 49 UniBasic called from C. 73 compiling. 303 numeric function. 158 READ. 29. 62 PIPE_BUF. 205. 211 Proc user exit. 51 PROMPT. 50 performance improving in transaction processing. 210 report with break line. 209 PRINTER CLOSE. 303 precision setting in UniBasic.

36 REPLACE. 33 program control commands. 82 running UniBasic programs. 171 RUN from ECL. 116 record mark. 290 introduction. 111. 116 reading records from. 164 REMOVE. 227 S SADD. 129 READSEQ. 290 RedBack. 183 REPEAT. 116 scaling numbers. 116 record ID list. 119 unopened files. 27 REWIND. 290 creating or converting a file . 158. 137 selecting. 133. 302 remainder. 118 creating. 50 return code from STATUS function. 157 SELECT. 171 SCMP null value and. commands for. 303 numeric function. 117 select list clearing. 303 searching dynamic array or string. 212 Reality® Basic. 279 operation limitations. 387 saving select list. 82 runtime version of UniData. 119 saving and retrieving. 31 introduced.Index reading named pipe. 294 RESIZET. 164 rounding numbers. 116 SELECTINDEX. 316 replacing characters in a string. 158 for data in a string or array. 117 422 Developing UniBasic Applications . 330 records. 303 SDIV null value and. 323 relational operator. 303 sample program UniBasic. 212 RND null value and. 24 RECORDLOCKED. 183. 212 RETURN in internal subroutines. 62 record lock. 168 RESIZE transaction processing and. 317 command. 45 relational operators null value and. 113 READT. 169 string value. 137 recoverable file system see also transaction processing CPIO format. 294 RECOVERABLE keyword.

111. 303 stack clearing. 134 significance. 84 shared lock. 183 null value and. 284 values returned from triggers. 58 SQRT. 339 RECORDLOCKED. 116 SEQ. 169 locating in array. 316 SPACE. 168 value as constant. 25 string function null value and. 156 extracting a substring. 157 left justifying. 21 STATUS named pipes and. 303 SMUL null value and. 313 TRANSACTION COMMIT. 169 null value and. 19 nested. 212 setting uninitialized variables. 168 counting substrings in. 169 SPACES. 137 return value for nulls. 164 SSUB null value and. 191 starting transaction within a subroutine. 105 STOP program control commands. 183 and null value. 294 statement conditional. 315 character conversion. 160 SIN. 158 replacing value. 337 commands for maintaining. 50 STR. 317 SPOOLHELP. 317 space removing from a string. 316 sequential file closing. 112 SETINDEX. 286 TRANSACTION START. 20 multiple. 303 sorting null value. 164 null value and. 321 SETTAPE. 19 multiline. 317 structured programming style. 317 string converting. 303 square root. 315 STRS null value and.Index selecting records. 32 layout. 301 null value and. 38 label. 168 converting data in. 168 SEQS. 164 null value and. 302. 156 determining length. 317 SPLICE null value and. 301 SOUNDEX. 29 Developing UniBasic Applications 423 . 157. 193 data.

294 TRANSACTION ABORT. 315 text mark. 183.Index subroutine CallBasic. 317 system information. 99 substring converting. 293 TRANSACTION ABORT introduction. 317 subtraction. 283. 287 locks. 164 SUPERCLEAR. 288 testing for null value. 150 SUM. 156 SUBSTRINGS. 241. 291 UDT. 175 reporting program execution. 294 consistency. 293 report generator.ATT. 150 THEN TRANSACTION COMMIT.LOCKS. 294 424 Developing UniBasic Applications . 31 writing trigger. 49 types. 169 locating in array. 399 defining isolation levels. 282 locks. 287 called programs and subroutines. 171 SWAP. 269 executing a transaction start within. converting nonprinting characters to. 135 display commands. 157 occurrence in array elements. 303 tape drive commands. 294 program control commands.OPTIONS 35. 399 break key in. 27 system time and date. 159 operator precedence. 294 file-level operations. 397 atomicity. 294 introduction. 212 terminal beeping for locked record. 401 programming example. 136 suppressing double spacing. 205 testing for active transaction. in transaction processing. 183 SYSTEM. 210 zero. 294 lost update. 294 screen generator. 404 dirty reads. 289 programming problems. 285 tilde. 84 transaction nested. 135 STATUS values. 169 time converting and formatting. 294 UniData SQL. 402 durability. 282 isolation. 165 null value and. 135 TRANSACTION COMMIT inappropriate. 176 T T. 24 delimiters. 212 TAN. 286 transaction processing. 399 limitations. 24. 46 subvalue mark. 287 udfile. 400 EXECUTE and.

182 MATCH. 169. 269 SUBSTRINGS. 183 subroutine. 182 OCONV. 269 U_preprint. 183 SEQS. 317 TRIMF. 182 ICONV. 294 UDT. 182 LEN. 243.OPTIONS 65. 182 GET. 182 INDEX. 227 UniData SQL Developing UniBasic Applications 425 . date format. 268. 241. 275 U_done. 241. 105 troubleshooting.OPTIONS 12. 317 troubleshooting processing named pipes. 27 CHANGE. 341 transaction processing. 96 return value. 176 U_callbas.OPTIONS 35. 196 Uni. 317 TRIMB.OPTIONS 88. 275 udtcallbasic_init. 263 udtcallbasic. 182 UniBasic. 275 udtcallbasic_done. 15 FIELD. 204 UDT. 183 UniData locking system. 169. 220. 181 CONVERT command.Index unrepeatable reads. 182 INPUT.OPTIONS 4.S. 181. 408 TRANSACTION START within a subroutine. 182 DCOUNT. 100 STATUS return values.OPTIONS 7. 183 @variables. 265 U_REDIRECT. 182 LENS. 169. 182 FINDSTR. 133 runtime version. 204 UDT. 182 INPUT @. 99. 221. 182 features and program components. 241. 269 udfile. 265 U_PHANTOM. 272. 403 with nonrecoverable files. 181 CHARS. 181 CHAR. 182 MATCHFIELD. 271. 181 COL1. 291 UDT. 204 UDT. 210 UDT. 220. 294 trigger defined.OPTIONS 5. 182 SEQ. 210 UDT. 317 TRIMS. 275 UDTEXECUTE. 210 UDT.OPTIONS 18. 241. 181 COUNT. 181 COUNTS. 293 U U lock. 106 writing UniBasic subroutines. 183 SWAP. 265 U_errout. 133 U. 102 TRIM. 269. U_callbas function.

294 UniData. 199 V validating database changes. 164 mark. 212 writing C program from UniBasic. 99 update see also WRITE UPDATE_ORDER.LIB. 113 WRITET. 316 UPDATE trigger. UniBasic program. 387 naming in C function. sample program for. 98 WRITEONLY. 403 unrepeatable reads. 136 unrepeatable read. 195 VOC file CALLC requirements. 44 testing for null value. 169 user exit writing. 236. 96 value integer. 150 value mark.Index executing from UniBasic. 113 WRITE commands. 69 426 Developing UniBasic Applications . 266 E type entry. 274 UniQuery user exits. 24 variable @variables in UniBasic. setting. 219 naming in external function. 300 UNLOCK. 114 triggers. 323 WEOF. 212 WEOFSEQ. 317 XREF. 266 W web application development. 197 executing in transaction processing . 228 data to files. 387 upper case converting to. 84 VCATALOG. 25 X XLATE. 318 uninitialized. 199 user number for locked records. representing. 169 null value and. 113 WRITESEQF. 326 WRITESEQ. 27 converting. 168 defined. 259. 142 UPCASE. 200 unknown values. 273 user exits. 264 naming in UniBasic. 102 UniBasic subroutine in CallBasic. 137 using UniBasic. 119 non-UniData files. 25 numeric. 123 trigger subroutines. 316. 74 virtual attribute.

171 Developing UniBasic Applications 427 .Index Z zero. suppressing.

Index 428 Developing UniBasic Applications .

Sign up to vote on this title
UsefulNot useful