Copyright: UltraLite  Version 7.0.2 Copyright © 2000 Sybase, Inc. All rights reserved.


Developer's Guide
UltraLite

Version 7.0.2

Document ID:  MC0060

November 2000

 Copyright page

 About This Manual

 PART 1. Introduction to UltraLite

 PART 2. Developing UltraLite Applications in C/C++

 PART 3. Developing UltraLite Applications in Java

 PART 4. Reference


Copyright page
  UltraLite  Developer's Guide

 Copyright page

Copyright © 2000 Sybase, Inc. All rights reserved.

No part of this publication may be reproduced, transmitted, or translated in any form or by any means, electronic, mechanical, manual, optical, or otherwise, without the prior written permission of Sybase, Inc.

Sybase, SYBASE (logo), ADA Workbench, Adaptable Windowing Environment, Adaptive Component Architecture, Adaptive Server, Adaptive Server Anywhere, Adaptive Server Enterprise, Adaptive Server Enterprise Monitor, Adaptive Server Enterprise Replication, Adaptive Server Everywhere, Adaptive Server IQ, Adaptive Warehouse, AnswerBase, Anywhere Studio, Application Manager, AppModeler, APT-Build, APT-Edit, APT-Execute, APT-FORMS, APT-Library, APT-Translator, APT Workbench, ASEP, Backup Server, BayCam, Bit-Wise, Certified PowerBuilder Developer, Certified SYBASE Professional, Certified SYBASE Professional (logo), ClearConnect, Client Services, Client-Library, CodeBank, Cohesion, Column Design, ComponentPack, Connection Manager, CSP, Data Pipeline, Data Workbench, DataArchitect, Database Analyzer, DataExpress, DataServer, DataWindow, DB-Library, dbQueue, Developers Workbench, Direct Connect Anywhere, DirectConnect, Distribution Director, Dynamo, E-Anywhere, E-Whatever, Electronic Case Management, Embedded SQL, EMS, Enterprise Application Server, Enterprise Application Studio, Enterprise Client/Server, Enterprise Connect, Enterprise Data Studio, Enterprise Manager, Enterprise SQL Server Manager, Enterprise Work Architecture, Enterprise Work Designer, Enterprise Work Modeler, EWA, Financial Fusion, First Impression, Formula One, Gateway Manager, GeoPoint, ImpactNow, InfoMaker, Information Anywhere, Information Everywhere, InformationConnect, InstaHelp, Intellidex, InternetBuilder, iScript, Jaguar CTS, jConnect for JDBC, KnowledgeBase, Logical Memory Manager, MainframeConnect, Maintenance Express, MAP, MDI Access Server, MDI Database Gateway, media.splash, MetaWorks, MethodSet, MobiCATS, MySupport, Net-Gateway, Net-Library, NetImpact, Next Generation Learning, Next Generation Learning Studio, O DEVICE, OASiS, OASiS (logo), ObjectConnect, ObjectCycle, OmniConnect, OmniSQL Access Module, OmniSQL Toolkit, Open Client, Open Client/Server, Open Client/Server Interfaces, Open ClientConnect, Open Gateway, Open Server, Open ServerConnect, Open Solutions, Optima++, Partnerships that Work, PB-Gen, PC APT Execute, PC DB-Net, PC Net Library, PhysicalArchitect, Power Through Knowledge, Power++, power.stop, PowerAMC, PowerBuilder, PowerBuilder Foundation Class Library, PowerDesigner, PowerDimensions, PowerDynamo, PowerJ, PowerScript, PowerSite, PowerSocket, Powersoft, Powersoft Portfolio, Powersoft Professional, PowerStage, PowerStudio, PowerTips, PowerWare Desktop, PowerWare Enterprise, ProcessAnalyst, Relational Beans, Replication Agent, Replication Driver, Replication Server, Replication Server Manager, Replication Toolkit, Report Workbench, Report-Execute, Resource Manager, RW-DisplayLib, RW-Library, S-Designor, S Designor, SAFE, SAFE/PRO, SDF, Secure SQL Server, Secure SQL Toolset, Security Guardian, SKILS, smart.partners, smart.parts, smart.script, SQL Advantage, SQL Anywhere, SQL Anywhere Studio, SQL Code Checker, SQL Debug, SQL Edit, SQL Edit/TPU, SQL Everywhere, SQL Modeler, SQL Remote, SQL Server, SQL Server Manager, SQL Server SNMP SubAgent, SQL Server/CFT, SQL Server/DBM, SQL SMART, SQL Station, SQL Toolset, SQLJ, Startup.Com, STEP, SupportNow, Sybase Central, Sybase Client/Server Interfaces, Sybase Development Framework, Sybase Financial Server, Sybase Gateways, Sybase Learning Connection, Sybase SQL Desktop, Sybase SQL Lifecycle, Sybase SQL Workgroup, Sybase Synergy Program, Sybase User Workbench, Sybase Virtual Server Architecture, Sybase MPP, SybaseWare, Syber Financial, SyberAssist, SyBooks, System XI (logo), System 10, System 11, SystemTools, Tabular Data Stream, The Enterprise Client/Server Company, The Extensible Software Platform, The Future Is Wide Open, The Learning Connection, The Model For Client/Server Solutions, The Online Information Center, Transact-SQL, Translation Toolkit, Turning Imagination Into Reality, UltraLite, UNIBOM, Unilib, Uninull, Unisep, Unistring, URK Runtime Kit for UniCode, Viewer, Visual Components, VisualSpeller, VisualWriter, VQL, Warehouse Control Center, Warehouse Studio, Warehouse WORKS, WarehouseArchitect, Watcom, Watcom SQL Server, Watcom SQL, Web.PB, Web.SQL, Web Deployment Kit, WebSights, WebViewer, WorkGroup SQL Server, XA-Library, XA-Server, and XP Server are trademarks of Sybase, Inc. or its subsidiaries.

Certicom and SSL Plus are trademarks and Security Builder is a registered trademark of Certicom Corp. Copyright © 1997-2000 Certicom Corp. Portions are Copyright © 1997-1998, Consensus Development Corporation, a wholly owned subsidiary of Certicom Corp. All rights reserved. Contains an implementation of NR signatures, licensed under U.S. patent 5,600,725. Protected by U.S. patents 5,787,028; 4,745,568; 5,761,305. Patents pending.

All other trademarks are property of their respective owners.

Last modified: June 2000. Part Number: MC0060.

 Copyright page

 About This Manual

 PART 1. Introduction to UltraLite

 PART 2. Developing UltraLite Applications in C/C++

 PART 3. Developing UltraLite Applications in Java

 PART 4. Reference


About This Manual
  UltraLite  Developer's Guide

 About This Manual

 About This Manual

 Related documentation

 Documentation conventions

 The UltraLite sample application

 Finding out more and providing feedback


About This Manual
  UltraLite  Developer's Guide

    About This Manual

 About This Manual

Subject

This manual describes the UltraLite deployment technology for Adaptive Server Anywhere. With UltraLite, you can develop and deploy database applications to handheld, mobile, or embedded devices, such as devices running the Palm Computing Platform, Windows CE, VxWorks, DOS, or Java.

Audience

This manual is intended for all application developers writing programs that use UltraLite deployment. Familiarity with relational databases and Adaptive Server Anywhere is assumed.


Related documentation
  UltraLite  Developer's Guide

    About This Manual

 Related documentation

Online documentation is most current and complete
Online documentation is updated with each maintenance release, and is up to date. Printed documentation is not necessarily updated with each maintenance release. Not all books are provided with the software.

This book describes how to design, build, and deploy UltraLite applications. Several other books in the SQL Anywhere Studio documentation set provide information that is useful for UltraLite developers.

Adaptive Server Anywhere documentation

UltraLite deployment technology is based on the Adaptive Server Anywhere relational database. The Adaptive Server Anywhere documentation describes how to create and maintain databases, how to use SQL, and many other aspects of database use for application developers and database administrators.

The Adaptive Server Anywhere documentation includes the following books:

•	Adaptive Server Anywhere Getting Started    Intended for all users of Adaptive Server Anywhere, this book describes the following:

•	New features and behavior changes in Adaptive Server Anywhere 7.0 and its maintenance releases.

•	An introduction to Adaptive Server Anywhere and relational databases.

•	Adaptive Server Anywhere User's Guide    Intended for all users of Adaptive Server Anywhere, including database administrators and application developers, this book describes in depth all aspects of how to use Adaptive Server Anywhere.

•	Adaptive Server Anywhere Programming Interfaces Guide    Intended for application developers writing programs that directly access the ODBC, Embedded SQL, or Open Client interfaces, this book describes how to develop applications for Adaptive Server Anywhere.

This book is not required for users of Application Development tools with built-in ODBC support, such as Sybase PowerBuilder or Power++.

•	Adaptive Server Anywhere Reference     A full reference to Adaptive Server Anywhere. This book describes the database server, the administration utilities, the SQL language, and error messages.

Synchronization

Synchronization is a key component of most UltraLite applications. MobiLink synchronization is described in the Replication and Synchronization Guide.

SQL Anywhere Studio

UltraLite is part of SQL Anywhere Studio, a complete database management system and deployment package for mobile, workgroup, and embedded applications. For information on the other pieces that make up SQL Anywhere Studio, see Introducing SQL Anywhere Studio.


Documentation conventions
  UltraLite  Developer's Guide

    About This Manual

 Documentation conventions

The following icons are used in this documentation:

Icon	Meaning
	A client application.
	A database server, such as Sybase Adaptive Server Anywhere or Adaptive Server Enterprise.
	An UltraLite application and database server. In UltraLite, the database server and the application are part of the same process.
	A database. In some high-level diagrams, the icon may be used to represent both the database and the database server that manages it.
	Replication or synchronization middleware. These pieces of software assist in sharing data among databases. Examples are the MobiLink Synchronization Server, the SQL Remote Message Agent, and the Replication Agent (Log Transfer Manager) for use with Replication Server.


The UltraLite sample application
  UltraLite  Developer's Guide

    About This Manual

 The UltraLite sample application

UltraLite includes a sample application to illustrate design and programming techniques, and for use in the documentation examples.

It is located in the UltraLite samples directory of your installation. Generic files are located in the CustDB directory. Files specific to the Palm Computing Platform are located in the palm subdirectory of CustDB, those specific to Windows CE are in the vc6\CECustDB directory, and those for a Windows version are stored in vc6\NTCustDB.

The application is a sales-status application for a hardware supplier. It is based on a database that holds customer, product, and sales force information for the supplier. This database is named CustDB. The application allows users to approve and deny sales orders.

The following figure shows the tables in the CustDB database and how they are related to each other.

The database schema is described in the file CustDB.sql, also located in the CustDB directory.

  For a walk-through of the sample application, see A Sample UltraLite Application.

  For information on building the sample application, see Platform-Specific Development.


Finding out more and providing feedback
  UltraLite  Developer's Guide

    About This Manual

 Finding out more and providing feedback

We would like to receive your opinions, suggestions, and feedback on this documentation.

You can provide feedback on this documentation and on the software through newsgroups set up to discuss SQL Anywhere technologies. These newsgroups can be found on the forums.sybase.com news server.

For UltraLite issues, see the sybase.public.sqlanywhere.ultralite newsgroup.

Newsgroup disclaimer
Sybase has no obligation to provide solutions, information or ideas on its newsgroups, nor is Sybase obliged to provide anything other than a systems operator to monitor the service and insure its operation and availability.

Sybase Technical Advisors as well as other staff assist on the newsgroup service when they have time available. They offer their help on a volunteer basis and may not be available on a regular basis to provide solutions and information. Their ability to help is based on their workload.

 Copyright page

 About This Manual

 PART 1. Introduction to UltraLite

 PART 2. Developing UltraLite Applications in C/C++

 PART 3. Developing UltraLite Applications in Java

 PART 4. Reference


PART 1. Introduction to UltraLite
  UltraLite  Developer's Guide

 PART 1. Introduction to UltraLite

This part introduces UltraLite, presents a sample UltraLite application, and provides general information on how to build your own UltraLite application.

 CHAPTER 1.  Introduction to UltraLite

 CHAPTER 2.  Tutorial: A Sample UltraLite Application

 CHAPTER 3.  UltraLite Overview

 CHAPTER 4.  Developing UltraLite Applications


CHAPTER 1.  Introduction to UltraLite
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

 CHAPTER 1.  Introduction to UltraLite

About this chapter

This chapter introduces the UltraLite database deployment technology, describing the purpose and defining characteristics of UltraLite.

 UltraLite features

 Supported platforms

 UltraLite architecture

 MobiLink synchronization

 Enterprise productivity

 What's new in version 7.0.1

 What's new in version 7.0

 What's new in 6.0.3


UltraLite features
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

 UltraLite features

UltraLite is a deployment technology for Adaptive Server Anywhere databases, aimed at small, mobile, and embedded devices. Intended platforms include cell phones, pagers, and personal organizers.

UltraLite provides the following benefits for users of small devices:

•	The functionality and reliability of a transaction-processing SQL database.

•	The ability to synchronize data with your central database management system.

•	An extremely small memory footprint.

•	C/C++ or Java development.

Full-featured SQL

UltraLite allows applications on small devices to use full-featured SQL to accomplish data storage, retrieval, and manipulation. UltraLite supports referential integrity, transaction processing, and multi-table joins of all varieties. In fact, UltraLite supports most of the same data types, runtime functions, and SQL data manipulation features as Sybase Adaptive Server Anywhere.

Synchronization to industry-standard RDBMS

UltraLite uses Sybase MobiLink synchronization technology to synchronize with industry-standard database management systems. MobiLink synchronization works with ODBC-compliant data sources such as Sybase Adaptive Server Anywhere, Sybase Adaptive Server Enterprise, IBM DB2, Microsoft SQL Server, and Oracle.

Small footprint custom database

UltraLite provides an ultra-small footprint by generating a custom database engine for your application. This custom engine includes only the features required by your application.

Each UltraLite application has its own database, modeled after a reference Adaptive Server Anywhere database.

C/C++ UltraLite custom database engines for your application can be as small as 50 kb, depending on your deployment platform and the number of SQL statements in the application and the SQL features used.

In-memory database    UltraLite target devices may have no hard disk and tend to have relatively slow processors. The UltraLite runtime employs algorithms and data structures that provide high performance and low memory use.

Supported development models

You can develop UltraLite applications in the following ways:

•	C/C++ using the UltraLite C++ API    The C++ interface exposes tables and SQL statements as objects, with methods to move through the rows of the table or a result set and to execute statements.

•	C/C++ using embedded SQL    Embedded SQL is an easy way of including SQL statements directly in C or C++ source code.

•	Java using JDBC    UltraLite Java applications support standard JDBC data access methods.


Supported platforms
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

 Supported platforms

Platform support for UltraLite is of the following kinds:

•	Target platforms    The target platform is the device and operating system on which you deploy your finished UltraLite application.

•	Host platforms    For each target platform, you develop your applications using a particular development tool and operating system. The tool and operating system comprise the host platform. Target platform manufacturers may supply emulators to ease development tasks. Emulators simulate the target platform, while running on the host platform.

You may be able to use other tools to develop your UltraLite applications, but supporting documentation and technical assistance are provided only for the supported development platforms.

The supported target platforms for UltraLite applications fall into two categories: those supporting C/C++ UltraLite applications and those supporting Java UltraLite applications.

 Supported platforms for C/C++ applications

 Supported platforms for Java applications


Supported platforms for C/C++ applications
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

        Supported platforms

 Supported platforms for C/C++ applications

This version of UltraLite supports the following platforms for C/C++ applications using Embedded SQL or the UltraLite C++ API:

•	Palm Computing Platform    UltraLite applications can be built for Palm Computing Platform devices running the Palm OS versions 2.x, or 3.x on a Dragonball processor. For example, the PalmPilot Professional, Palm III, and Palm V organizers are suitable target platforms, as are the Handspring Visor, TR6Pro, and so on. The PalmPilot Personal is not a supported target platform.

UltraLite applications can be run for testing and demonstration purposes on the Palm emulator.

The supported development platform for the Palm Computing Platform is the Metrowerks CodeWarrior version 5.0 or 6.0 on Windows NT, and the GCC Tools version 2.0.

•	Windows CE    UltraLite applications can be built for devices running the Windows CE 2.11 operating system on any of the following processors:

•	MIPS

•	Hitachi SH3 or SH4 processor.

•	ARM processor.

•	Power PC, with an SDK from the device manufacturer or Microsoft Platform Builder 2.11.

•	Intel x86 processor, with an SDK from the device manufacturer or Microsoft Platform Builder 2.11.

UltraLite applications can be run for testing and demonstration purposes in the Windows CE emulator.

The supported development platform for Windows CE is Microsoft Visual C++ 6.0 on Windows NT.

•	WindRiver VxWorks    UltraLite applications can be built for devices running the VxWorks operating system in any of the following configurations:

•	A 386, 486 or Pentium PC running VxWorks 5.3 or above with the Intel x86 Board Support Package (BSP) version 1.1 or above.

•	A PowerPC running VxWorks 5.4. The UltraLite library has been compiled for the PowerPC860 chip and tested on an MBX860 board using TCP/IP synchronization.

The VxWorks version of UltraLite also runs under the VxSim emulator. The full simulator is required to carry out synchronization. VxSim-Lite can be used for testing, but does not support synchronization.

Development for VxWorks is supported on WindRiver Tornado development environment for Windows, version 1.0.1 or above.

UltraLite requires a dosFs (MS-DOS-compatible file system) device or a functionally equivalent device to store the database in a persistent manner in a file.

•	DOS    Devices running MS DOS version 6.02 or above. DOS does not include any native synchronization streams; but PC/TCP version 3.2 from FTP software is supported for synchronization. In addition, for the Symbol device, the series 3000 NDK is a supported synchronization stream.

Development for DOS is supported on Microsoft Visual C++ version 1.52c or above. Compile applications for real mode using the large memory model. You can compile real-mode code for the Intel 186, 286, or 386 processor if the target device uses these particular processors.

UltraLite applications can be installed on any device running DOS; for example, the Symbol handheld device. If you choose to build UltraLite applications for the Symbol device and synchronize via TCP/IP, you also need the Series 3000 Network Development Kit (NDK) version 2.01. Use this software instead of the PC/TCP software that is used for standard DOS applications.

•	Windows 95/98 and Windows NT    These operating systems are supported for testing and demonstration purposes only.


Supported platforms for Java applications
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

        Supported platforms

 Supported platforms for Java applications

Deployment using the Sun Java 2 (JDK 1.2.x) environment is supported. Also, deployment using the Sun JDK 1.1.4 or later is supported. To use UltraLite in applets, you must use the Java Plug-in 1.2.x to run the applets. There is no guarantee that applets will work with the built-in Java VMs for the Internet Explorer or Netscape browsers.

Development using Sybase PowerJ or the Sun JDK is supported.


UltraLite architecture
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

 UltraLite architecture

SQL database products typically use a client/server architecture. The database is normally stored in one or more files in the file system, or directly on a storage device. The database server receives and processes SQL requests from client applications, maintaining the database according to the requests. The server protects you from failures by guaranteeing that complete transactions are recovered in case of a failure and incomplete transactions are rolled back.

UltraLite has the same client/server architecture as other SQL database systems. However, the UltraLite database engine is not a separate process, but is instead a library of functions that is called by an application. If you build your application using C/C++, this engine is accessed as a DLL or from a statically linked library. If you build your application in Java, the engine is accessed from Java byte codes stored in a JAR file.

C/C++ deployment

If you build your application using C/C++, the UltraLite development tools generate C/C++ source code that is compiled along with your application source code. When you link your application, you link all of the compiled C/C++ together with the UltraLite runtime library or imports library. The result is a single executable file containing application logic and database logic required by the application.

When first executed on a new device, this executable automatically creates the UltraLite database for your application. This database is initially empty, but you can add data, either explicitly or through synchronization with a central database.

Java deployment

If you build a Java UltraLite application, the UltraLite development process generates Java source code that represents the database schema. The generated source file is to be compiled into classes that you deploy as part of your application with the UltraLite runtime JAR file. You may wish to package all files together into a single JAR file for ease of deployment.

When first executed on a new device, the UltraLite runtime automatically creates the database for your application. This database is initially empty, but you can add data, either explicitly or through synchronization with a central database.

Persistent memory

UltraLite provides protection against system failures. Some UltraLite target devices have no disk drive, but instead feature memory that retains content when the device is not running. The storage mechanism for the UltraLite database is platform-dependent, but is managed by the UltraLite runtime library, and does not need explicit treatment from the application developer.

Fixed schema

UltraLite does not allow the schema of an UltraLite database to be modified once the application is deployed. When a newer version of the application requires more tables or more columns, the newer version of the application is deployed and the UltraLite database is repopulated through synchronization.

 UltraLite development tools


UltraLite development tools
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

        UltraLite architecture

 UltraLite development tools

The UltraLite development tools supplement a supported C/C++ or Java development tool. They manage the generation of the data access code for your application.

During UltraLite application development you create an Adaptive Server Anywhere reference database, which is a model of your UltraLite database. You use the UltraLite generator, which uses the reference database to create the data access and data management code for your application.

Parameterized SQL statements

The SQL statements used in the application must be determined at compile time. In other words, you cannot dynamically construct a SQL statement within an UltraLite application and execute it. However, SQL statements in UltraLite applications can use placeholders or host variables to adjust their behavior.


MobiLink synchronization
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

 MobiLink synchronization

Many mobile and embedded computing applications are integrated into an information infrastructure. They require data to be uploaded to a central database, which consolidates all the data throughout the MobiLink installation, and downloaded from a consolidated database. This bidirectional sharing of information is called synchronization.

MobiLink synchronization technology, included in SQL Anywhere Studio along with UltraLite, is designed to work with industry standard SQL database management systems from Sybase and other vendors. The UltraLite runtime automatically keeps track of changes made to the UltraLite database between each synchronization with the consolidated database. When the UltraLite database is synchronized, all changes since the previous synchronization are uploaded for synchronization.

Subset of the central database

Mobile and embedded databases may not contain all the data that exists in the consolidated database.

The tables in each UltraLite database can have a subset of the rows and columns in the central database. For example, a customer table might contain over 100 columns and 100,000 rows in the consolidated database, but the UltraLite database may only require 4 columns and 1000 rows. MobiLink allows you to define the exact subset to be downloaded to each remote database.

Flexibility

MobiLink synchronization is flexible. You define the subset of data using the native SQL dialect of the consolidated database management system. Tables in the UltraLite database can correspond to tables in the consolidated database, but you can also populate an UltraLite table from a consolidated table with a different name, or from a join of one or more tables.

Conflict resolution

Mobile and embedded databases frequently share common data. They also must allow updates to the same data. When two or more remote databases simultaneously update the same row, the conflict cannot be prevented. It must be detected and resolved when the changes are uploaded to the central database. MobiLink synchronization automatically detects these conflicts. The conflict resolution logic is defined in the native SQL dialect of the central DBMS.

The MobiLink synchronization server

An UltraLite application synchronizes with a central, consolidated database through the MobiLink synchronization server. This server provides an interface between the UltraLite application and the database server.

You control the synchronization process using synchronization scripts. These scripts are SQL statements or procedures written in the native language of the consolidated DBMS. For example, you can use a SELECT statement to identify the columns and tables in the consolidated database that correspond to each column of a row uploaded from a table in your UltraLite application. These scripts are stored in tables within the consolidated database. Each script controls a particular event during the synchronization process.

Synchronization streams

Synchronization occurs through a synchronization stream. Supported streams include TCP/IP, HTTP, HotSync, Scout Sync, and direct serial port communication. Regardless of the stream, you control the synchronization process using the same SQL scripts defined in your consolidated database.

  For a detailed introduction to MobiLink synchronization, see MobiLink Synchronization.

  For information on adding synchronization to your UltraLite application, see Synchronizing UltraLite applications.


Enterprise productivity
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

 Enterprise productivity

UltraLite was designed for development using existing tools, skills, and components. You can thus leverage the current capabilities of your organization.

High-level programming and portability

UltraLite encourages high productivity by providing robust, high-level programming solutions on an increasing variety of devices. You can develop applications for small devices using the proven and powerful methodology of full-featured SQL. You need not become familiar with device-specific aspects (such as flash memory) and the disparate operating system interfaces that provide access to them. Similarly, synchronization can be achieved without becoming an expert in the various transmission protocols. Moreover, the database and synchronization components in your application are portable.

High-level development environments

UltraLite allows you to continue to use whatever tools you already use for productive development. It adds functionality to your development process. For example, you can develop applications using Microsoft Visual C++ and test them in the various Windows PC environments before deploying them, for final testing, on a specific device.

Industrial strength

MobiLink synchronization allows UltraLite applications to synchronize with many widely-used databases, not just those from Sybase. Built with the established technology of Sybase Adaptive Server Anywhere, it uses mature and proven database technology.


What's new in version 7.0.1
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

 What's new in version 7.0.1

UltraLite 7.0.1 introduces several new features:

•	Develop UltraLite applications with MobileBuilder     MobileBuilder is a rapid application development tool for small devices. You can use MobileBuilder to develop UltraLite applications, using the UltraLite Database component included with SQL Anywhere 7.0.1.

  For information on this feature, see the separate book Developing UltraLite Applications with MobileBuilder.

•	New synchronization stream for Palm Computing Platform    In addition to the current ULPalmDBStream synchronization stream, a new synchronization stream is available for the Palm Computing Platform in this release. The new stream is called ULConduitStream, and in many circumstances this stream can provide dramatic performance improvements for HotSync synchronization.

  For more information, see Choosing a synchronization method.

•	Support for gnu compiler for Palm Computing Platform    As an alternative to the Metrowerks CodeWarrior development tool, you can now use gnu development tools to develop applications for the Palm.

  For more information, see Developing UltraLite applications with GNU development tools.

•	Monitoring and canceling synchronization    You can view synchronization status and build the ability to cancel synchronization into your UltraLite applications.

  For more information, see Monitoring and canceling synchronization, and Monitoring and canceling synchronization.

•	User authentication in MobiLink    MobiLink synchronization now has its own user authentication scheme. Password fields and methods have been added to the UltraLite synchronization parameters to take advantage of this scheme.

  For more information, see Setting synchronization parameters.

•	New platforms for secure synchronization    You can now use the transport-layer security features for synchronization from a wider range of target platforms, including Windows CE on the Hitachi SH4 chip, and VxWorks on Intel x86 chips and on the Windows VxSim emulator.

  For more information, see the following:

•	Supported platforms.

•	Setting synchronization parameters.

•	Synchronization on Windows CE.

•	Synchronization on the VxWorks platform.

•	Non-replicating tables    You can include tables in the reference database that are included in the UltraLite database, but are not synchronized. Other than synchronization, the tables can be used like any other table in the remote database.

  For more information, see Including non-synchronizing tables in UltraLite databases.

•	Windows CE emulator support enhancements    You can now run UltraLite applications under Windows CE x86 emulators.

•	Synchronization optimization    Client applications can specify that a synchronization includes only uploads, and that no download phase should be attempted. This option lessens the overall synchronization time when only uploads are needed, especially over slow communication links.

  For more information, see Setting synchronization parameters.

•	Automatic HTTP version detection    The MobiLink synchronization server now detects and uses the HTTP version used by each client. This capability renders the version parameter on the MobiLink synchronization server -x command-line option redundant.

  For information on the MobiLink synchronization server command line, see MobiLink synchronization server.

•	Client port specification    You can specify, at a client, a range of ports used by a client during synchronization. This feature can be useful when synchronizing from a client inside a firewall to a MobiLink server outside.

  For more information, see Setting stream_parms values.


What's new in version 7.0
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

 What's new in version 7.0

UltraLite version 7.0 includes both major new features and enhancements to already-existing features.

Major features

The following are major new capabilities introduced in version 7.0:

•	Java UltraLite applications    You can now develop UltraLite applications in Java using JDBC. Using JDBC, you can write your database application in Java and send SQL statements to the UltraLite database.

  For more information regarding the development of Java/JDBC UltraLite applications, see UltraLite Overview and Developing UltraLite Java Applications.

•	C++ API for UltraLite applications    You can now develop C++ UltraLite applications using a new C++ API. The C++ API provides the same functionality as embedded SQL, but as an object-oriented API.

  For more information, see Developing C++ API Applications, and C++ API Reference.

•	New target platforms    You can now develop UltraLite applications for use on the VxWorks and DOS platforms. UltraLite applications can then be installed on any device running DOS or VxWorks, for example the Symbol handheld device (DOS) and the Intel x86 chip (VxWorks).

  For more information regarding the VxWorks platform, see Developing for VxWorks. For more information regarding the DOS platform, see Developing for DOS.

•	CodeWarrior plugin    A plugin for CodeWarrior is provided to make creation of UltraLite projects in CodeWarrior easier. The plugin automatically carries out the required preprocessing steps for embedded SQL and C++ API development projects. It also ensures that the UltraLite header files and libraries are included in the relevant paths.

  For more information, see Developing UltraLite applications with Metrowerks CodeWarrior.

•	Scout Sync synchronization    You can now synchronize via Scout Sync technology on the Palm OS platform. Scout Sync synchronization is similar to Hot Sync. In addition, Scout Sync allows multiple users to simultaneously synchronize data stored on Palm devices with data in the consolidated database.

  For more information regarding Scout Sync, see Configuring ScoutSync synchronization on the Palm Computing platform.

•	HTTP synchronization    You can now synchronize over HTTP, which permits easier synchronization across firewalls.

  For more information on the HTTP stream, see ULSynchronize library function.

•	Secure synchronization    MobiLink now supports transport-layer security for synchronization. For UltraLite applications to use this security, you must supply values for security parameters in the argument to the synchronization call.

  For information on how to call secure synchronization from an UltraLite application, see Adding synchronization to your application.

Enhancements

The following is a list of other enhancements in version 7.0:

•	CodeWarrior version 6 support    Development for the Palm Computing Platform on Metrowerks CodeWarrior 6 is now supported, in addition to Version 5.

  For more information on using CodeWarrior, see Developing for the Palm Computing Platform. For a list of supported host and target platforms, see Supported platforms.

•	New Synchronization function prototype    The call to synchronize now takes a structure as its argument, rather than a set of parameters. This change helps to provide improved upwards compatibility with future releases.

  For more information, see Adding synchronization to your application.

•	Suspension of synchronization    You can use the START SYNCHRONIZATION DELETE and STOP SYNCHRONIZATION DELETE statements to temporarily suspend synchronization of any delete operations in the UltraLite database. You can now use TRUNCATE TABLE in UltraLite applications.

  For more information, see SQL features and limitations of UltraLite applications.

•	New persistent storage parameter    A new persistent storage parameter, reserve_size, has been added that allows you to reserve file system space for storage of UltraLite persistent data. Reserving file system space can improve performance slightly and can also prevent out of memory failures.

  For more information regarding persistent storage parameters, see Configuring file-based persistent storage.

•	Synchronization script version    Additional flexibility has been added to MobiLink synchronization. A version string can be associated with each script, so that different client applications within an installation can synchronize in different ways.

Specifying different script versions allows a single UltraLite application to synchronize in more than one way. It can control the version of synchronization scripts used to apply the changes to the consolidated database.

In UltraLite, this enhancement is reflected in a change to the ULSynchronize and ULPalmExit function prototypes.

  For the ULSynchronize prototype, see ULSynchronize library function. For the ULPalmExit prototype, see ULPalmExit library function.

 Behavior changes

 Upgrading to version 7.0


Behavior changes
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

        What's new in version 7.0

 Behavior changes

Following is a list of behavior changes to the software in version 7.0.

•	Synchronization prototype changes    The ULSynchronize and ULPalmExit prototypes have been changed to allow script versioning, security, and upwards compatibility with future releases.

  For more information, see Adding synchronization to your application.

•	ULPalmLaunch return value changed    The ULPalmLaunch function return value is a member of the new UL_PALM_LAUNCH_RET enumeration, instead of a boolean. This change allows error checking and additional flexibility.

  For more information, see ULPalmLaunch library function.

•	Maximum row size limit    The limits to UltraLite row sizes is now 4076 bytes. UltraLite databases are compressed, and so this corresponds to a larger row size in uncompressed form. previously there was no absolute limit.

If you exceed the limit, a SQLE_MEMORY_ERROR code is signaled.


Upgrading to version 7.0
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

        What's new in version 7.0

 Upgrading to version 7.0

Older UltraLite applications do not compile without change in version 7.0. A new prototype for the ULSynchronize function and the ULPalmExit function must be added to compile. These prototype changes have been made to support synchronization script versions, alternative synchronization streams on the Palm, and improved compatibility in future releases.

  For the ULSynchronize prototype, see ULSynchronize library function. For the ULPalmExit prototype, see ULPalmExit library function.


What's new in 6.0.3
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

 What's new in 6.0.3

Following is a list of changes and additions to the software introduced in version 6.0.3.

•	Windows CE 2.11 and Visual C++ 6.0    The development tools now use Microsoft Visual C++ 6.0 to target Windows CE version 2.11. Previous releases of Windows CE are no longer supported. You may be able to develop applications for older versions of Windows CE, but this application of the UltraLite technology is not supported. The initial release of UltraLite used Microsoft Visual C++ 5.0 to target Windows CE version 2.0.

•	File-based persistent stores    UltraLite applications under Windows CE and Windows NT, 95, and 98 now use a file-based persistent storage mechanism. Under Windows CE, the use of a file improves performance of the UltraLite database by improving the access times for raw data. The Windows NT, 95, and 98 version uses a read-write memory mapped file as its file caching mechanism.

•	New data types    Real and double data types are now fully supported by both UltraLite and MobiLink technologies.

  For information on supported data types, see UltraLite data types.

•	ODBC 3.51    The MobiLink Server now uses ODBC 3.51, in common with the rest of Adaptive Server Anywhere. Version 6.0.2 of the MobiLink server used ODBC 2.0.

•	User settable BAUD rate    You can now specify the baud rate for communication via serial streams with Palm devices. Previously, the only available speed was 19200 BAUD. This value remains the default.

  For more information, see Configuring serial synchronization for the Palm Computing platform.

•	Character set translation    The MobiLink synchronization server now translates all uploaded characters to Unicode and passes them to the consolidated database using the Unicode ODBC API. Conversely, it translates all downloaded characters from Unicode to the character set of your UltraLite application. Character set translation within the consolidated database server can influence the results, but the new system allows more consistent behavior across multiple platforms.

 Behavior changes for 6.0.3

 Upgrade issues for 6.0.3


Behavior changes for 6.0.3
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

        What's new in 6.0.3

 Behavior changes for 6.0.3

•	Development on Windows CE versions before 2.11 no longer supported    The development of UltraLite Windows CE applications is now restricted to version 2.11 of the operating system.

•	Debug runtime libraries no longer available    Debug versions of the runtime libraries are no longer available. Debug versions were released for version 6.0.2, but were found to be of very limited use.

•	Persistent storage change on Windows CE    UltraLite applications under Windows CE and Windows NT, 95, and 98 now use a file-based persistent storage mechanism. The use of a file improves performance of the UltraLite database by improving the access times for row data.

•	Location of synchronization scripts changed    The synchronization scripts for non-Adaptive Server Anywhere databases are now installed into the MobiLink\setup subdirectory of your Adaptive Server Anywhere installation directory.


Upgrade issues for 6.0.3
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 1.  Introduction to UltraLite

        What's new in 6.0.3

 Upgrade issues for 6.0.3

You do not need to upgrade your existing reference or consolidated databases in order to use this version of the software.

Older versions of UltraLite applications can synchronize with the new version of the MobiLink synchronization server. However, new UltraLite applications cannot synchronize with older versions of the MobiLink synchronization server.


CHAPTER 2.  Tutorial: A Sample UltraLite Application
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

 CHAPTER 2.  Tutorial: A Sample UltraLite Application

About this chapter

This chapter illustrates some key features of UltraLite by walking through a sample application. The sample application is a simple sales-status application built around a database named CustDB (Customer Database).

The chapter includes information on how to run the sample application, and a brief description of how the application works.

Before you begin

To get the most from this chapter, you should be able to run the sample application as you read.

This chapter assumes that you have read the chapter Introduction to UltraLite. Much of the material in this chapter is explained in a more general manner elsewhere in the book. Cross references to these places are provided.

 Introduction

 Lesson 1: Start the MobiLink synchronization server

 Lesson 2: Install the sample application to your target platform

 Lesson 3: Start the sample application and synchronize

 Lesson 4: Add an order

 Lesson 5: Act on some existing orders

 Lesson 6: Synchronize your changes

 Lesson 7: Confirm the synchronization at the consolidated database

 Lesson 8: Browse the consolidated database

 Summary


Introduction
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Introduction

CustDB is a sample application included with UltraLite. It is a simple sales-status application that you can run against any of the supported databases, and on any of the supported target operating systems.

By working with the CustDB sample application, this chapter demonstrates the following core features of UltraLite.

•	UltraLite database applications run on small devices using very limited resources.

•	UltraLite applications include a relational database engine.

•	UltraLite applications share data with a central, consolidated database in a two-way synchronization scheme. The UltraLite databases are also called remote databases.

•	Each remote database contains a subset of the data in the consolidated database.

•	The MobiLink synchronization server carries out data synchronization between the consolidated database and each UltraLite installation.

•	SQL scripts stored in the consolidated database implement the synchronization logic.

•	You can use Sybase Central to browse and edit the synchronization scripts.

 The CustDB sample application

 File locations for the sample application

 Synchronization techniques in the sample application


The CustDB sample application
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Introduction

 The CustDB sample application

Versions of the CustDB application are supplied for each supported operating system. Also, source code for the application is provided in embedded SQL, the C++ API, and Java. This tutorial uses the compiled version of the application for Windows 95/98, Windows NT, the Palm Computing Platform, and Windows CE.

  For information about the Java version of the sample application, see The CustDB sample application. For information on compiling the sample application for each C/C++ target platform, see Platform-Specific Development.

When running the sample application, you are acting as an order taker or sales manager. The application allows you to view outstanding orders, approve or deny orders, and add new orders.

You can carry out the following tasks with the sample application.

•	View lists of customers and products.

•	Add new customers.

•	Add or delete orders.

•	Scroll through the list of outstanding orders.

•	Accept or deny orders.

•	Synchronize changes with the consolidated database.

When you run the CustDB UltraLite application, you are working on a single remote database, and synchronizing your changes with a consolidated database.

In a typical UltraLite installation, there will be many remote databases, each running on a handheld device, and each containing a small subset of the data from the consolidated database.


File locations for the sample application
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Introduction

 File locations for the sample application

Your UltraLite installation includes the files needed to run the sample application, and the source code used to develop it. Studying the sample application source code is a good way to learn more about UltraLite.

When you install SQL Anywhere Studio, the UltraLite sample files are installed into a directory named ultralite under your installation directory. This is your UltraLite directory.

 Runtime file location

 Source file locations


Runtime file location
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Introduction

          File locations for the sample application

 Runtime file location

To run the CustDB sample application, you need the following components:

•	The consolidated database    An Adaptive Server Anywhere version of the customer database is installed as the file custdb.db in the samples\custdb subdirectory of your UltraLite directory.

This database serves as a consolidated database. It contains the following information:

•	MobiLink system tables that hold the synchronization metadata.

•	The CustDB data, stored in rows in base tables.

•	The synchronization scripts.

During the installation process, an ODBC data source named UltraLite 7.0 Sample is created for this database.

•	The MobiLink synchronization server    The MobiLink synchronization server is in the win32 subdirectory of your SQL Anywhere directory.

•	The UltraLite application executable    A different executable is supplied for each operating system. These executables are held in subdirectories of your ultralite directory named for the operating system. Each operating system directory has a separate subdirectory for each supported CPU, and the executable files are located in these subdirectories.

•	ce    Windows CE applications.

•	dos    DOS applications.

•	palm    Palm Computing Platform applications.

•	vxw    VxWorks applications.

•	win32    A Windows 95/98 and Windows NT application.

•	java    A Java application.

This chapter uses the win32, ce, and palm versions of the application.


Source file locations
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Introduction

          File locations for the sample application

 Source file locations

Source code is provided for both the consolidated database and the UltraLite application in the samples\custdb directory of your UltraLite directory, and it subdirectories.

•	Consolidated database source    In this chapter we use the Adaptive Server Anywhere CustDB database as the consolidated database.

You can also build Sybase Adaptive Server Enterprise, Microsoft SQL Server, or Oracle consolidated databases and run the application against those database management systems.

You can use one of the SQL scripts in the samples\CustDB directory to build a consolidated database for a DBMS other than Adaptive Server Anywhere.

•	custase.sql    Sybase Adaptive Server Enterprise.

•	custdb.sql    Sybase Adaptive Server Anywhere.

•	custdb2.sql    IBM DB2.

•	custmss.sql    Microsoft SQL Server.

•	custora.sql    Oracle 8.

The Adaptive Server Anywhere consolidated database is already built and installed. You only need the scripts to make a consolidated database using another relational database product. You do not need the scripts for this tutorial.

•	Application source    The source code for the sample application is in two parts.

•	The user interface code for each platform is held in a separate subdirectory of samples\CustDB, named for each supported development tool.

•	The data access code is help in the samples\CustDB subdirectory of your UltraLite directory.

•	The embedded SQL data access code is held in custdb.sqc.

•	The C++ API data access code is held in custdbapi.cpp.

  For information on the UltraLite development process, see UltraLite Overview.

  For a list of supported development tools, see Supported platforms. For information on building the application for each supported platform, see Platform-Specific Development.


Synchronization techniques in the sample application
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Introduction

 Synchronization techniques in the sample application

The sample application demonstrates several useful synchronization techniques. This chapter provides a glimpse at synchronization, but in order to understand how to use these techniques in applications, you need to understand in more detail how the synchronization process works.

Synchronization is carried out using the MobiLink synchronization server, running on your desktop machine, against the CustDB sample database.

For more information

For an overview of the synchronization process, see MobiLink Synchronization.

For a description of how to write the synchronization scripts that control synchronization, see Writing Synchronization Scripts.

For information on the techniques used in the CustDB sample application, see The CustDB sample code.


Lesson 1: Start the MobiLink synchronization server
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Lesson 1: Start the MobiLink synchronization server

When you start the sample UltraLite application for the first time, it contains no data. The application carries out an initial synchronization to download an initial copy of the data from the consolidated database. You must have the database server running in order to carry out this initial download, and you must also have the MobiLink synchronization server running against the UltraLite sample database.

The SQL Anywhere Studio installation adds some items to the Start menu to make this step easier.

♦ To start the MobiLink synchronization server against the consolidated database:

1	Start the consolidated database server, running the CustDB sample database.

The Adaptive Server Anywhere consolidated database server runs on your desktop machine. From the Start menu, choose Programs [image] Sybase SQL Anywhere 7 [image] UltraLite [image] UltraLite Sample Database.

2	Start the MobiLink synchronization server against the CustDB database.

The MobiLink synchronization server connects to the consolidated database server through ODBC. It could run from a separate machine from the database server, but in this example we will run it on the same machine.

From the Start menu, select Programs [image] Sybase SQL Anywhere 7 [image] Synchronization [image] MobiLink Synchronization Server Sample.

The command executed by this icon connects the MobiLink synchronization server to the consolidated database server.

  For the next step, see the section for your platform under Lesson 2: Install the sample application to your target platform.


Lesson 2: Install the sample application to your target platform
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Lesson 2: Install the sample application to your target platform

The UltraLite application must be installed onto a target machine in order for you to proceed. This section describes how to install the sample application to your target machine.

No installation needed for Windows NT or Windows 95/98
If you want to run the Windows NT or Windows 95/98 version of the CustDB application from your desktop, you do not need to read this section.

  For the next step, see Lesson 3: Start the sample application and synchronize.

 Install the sample application (Palm Computing Platform)

 Install the sample application (Windows CE)


Install the sample application (Palm Computing Platform)
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 2: Install the sample application to your target platform

 Install the sample application (Palm Computing Platform)

You need to carry out the steps in this section only if you wish to run the tutorial on a Palm Computing device. If you wish to run the tutorial on a desktop Windows NT or Windows 95/98 machine, proceed to Lesson 3: Start the sample application and synchronize.

Use the Palm Install Tool to deploy the application to your device. You must tell Install Tool the location of the application, and then use HotSync to transfer the executable file to the device.

The Adaptive Server Anywhere installation automatically sets registry entries to enable CustDB synchronization via HotSync. These entries associate the UltraLite conduit on Windows NT with the CustDB application on the Palm Computing device. You must have HotSync Manager 3 installed for HotSync synchronization to work properly.

♦ To install the sample application to a Palm Computing device:

1	Prepare your PC for running Adaptive Server Anywhere and the Palm Desktop software.

Install Adaptive Server Anywhere onto a machine that has Palm Desktop already installed. The Adaptive Server Anywhere installation then adds the registry entries required for HotSync.

2	On your PC, start Palm Desktop.

3	Add the sample application to the list of files to install onto your handheld.

Click Install on the Palm Desktop toolbar.

Click Add. Locate the Palm Computing executable file for the sample application. This executable is the file custdb.prc, and it is in the palm\68k subdirectory of your UltraLite directory.

Click Done.

4	HotSync your Palm Computing device.

The CustDB application is copied into the Applications view on your Palm device.

♦ To copy the sample application to a Palm Computing Platform emulator:

1	Start the Palm emulator.

2	Right click and select Install Application/Database from the popup menu.

3	Locate the application and click OK to install.

You may have to refresh the Applications view to see the installed application on the emulator interface.

  For the next step, see Lesson 3: Start the sample application and synchronize.


Install the sample application (Windows CE)
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 2: Install the sample application to your target platform

 Install the sample application (Windows CE)

You need to carry out the steps in this section only if you wish to run the tutorial on a Windows CE device. If you wish to run the tutorial on a desktop Windows NT or Windows 95/98 machine, proceed to Lesson 3: Start the sample application and synchronize.

♦ To copy the sample application to a CE device:

1	Ensure that Windows CE Services is properly installed. You can do this by checking whether Windows Explorer can view and modify the file system on the CE device.

2	Open the Windows Explorer. Right click on My Computer and select Explore.

3	Find your SQL Anywhere installation directory. The default location is as follows:

c:\Program Files\Sybase\SQL Anywhere 7

Open the ultralite\vc6\CECustDB folder so that the contents of the folder are visible. Open mips or sh3 depending on the CPU used in the CE device. The executable file CustDB.exe should be visible at this point.

4	Right click on CustDB.exe and select Copy.

5	Find the CE device in the Explorer hierarchy. It should be under the Mobile Devices folder. Create a folder on the CE device called Sybase. Open the Sybase folder on the device and paste the executable to copy the CustDB.exe file to the CE device. You may be asked whether you want the file to always be synchronized or converted before copying, both of these actions can be refused.

6	In the Sybase folder on the device, there should be one executable file, namely, CustDB.exe. Right click on CustDB.exe to create a shortcut and rename the shortcut to CustDB.

7	On the CE Device, open the root folder Windows followed by Start Menu and Programs. In the Programs folder, add a Sybase folder.

8	Move the shortcut for CustDB from \Sybase to the \Windows\Start Menu\Programs\Sybase folder by cutting and pasting the shortcut.

9	The samples are now accessible from the CE device Start button. Select Start [image] Programs [image] Sybase [image] CustDB.

  For the next step, see Start the application (Windows CE).


Lesson 3: Start the sample application and synchronize
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Lesson 3: Start the sample application and synchronize

When started for the first time, the sample UltraLite application contains no data. In this step, you start the sample application, and carry out an initial synchronization with the consolidated database to obtain an initial set of data. The particular data you download depends on the user ID you enter when you start the application.

 Start the application (Windows 95/98 or Windows NT)

 Start the sample application (Palm Computing Platform)

 Start the application (Windows CE)


Start the application (Windows 95/98 or Windows NT)
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 3: Start the sample application and synchronize

 Start the application (Windows 95/98 or Windows NT)

♦ To start and synchronize the sample application:

1	Launch the sample application.

From the Start menu, choose Programs [image] Sybase SQL Anywhere 7 [image] UltraLite [image] Sample Application.

2	Enter an employee ID.

When running through this section as a tutorial, enter a value of 50 and press Enter. The application also allows values of 51, 52, or 53, but behaves slightly differently in these cases.

The application synchronizes after you enter the employee ID, and a set of customers, products, and orders are downloaded to the application.

3	Confirm that the data has been synchronized into the application.

Confirm that a company name and a sample order appear on the application window.

You have now synchronized your data.

  For the next step, see Lesson 4: Add an order.


Start the sample application (Palm Computing Platform)
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 3: Start the sample application and synchronize

 Start the sample application (Palm Computing Platform)

The sample application for the Palm Computing Platform uses HotSync as the synchronization mechanism.

♦ To start and synchronize the sample application:

1	Place your Palm device into its cradle.

When you start the sample application for the first time it must be able to synchronize, to download an initial copy of the data. This step is required only the first time you start the application. After that, the downloaded data is stored in the UltraLite database.

2	Launch the sample application.

From the Applications view, tap CustDB. An initial dialog displays, prompting you for an employee ID.

3	Enter an employee ID.

When running through this section as a tutorial, enter a value of 50. The application also allows values of 51, 52, or 53, but behaves slightly differently in these cases.

A message box tells you that you must synchronize before proceeding.

4	Synchronize your application.

Use HotSync to obtain an initial copy of the data.

5	Confirm that the data has been synchronized into the application.

From the Applications view, tap the CustDB application. There is a delay as the application processes the synchronized data. Then the display shows an entry sheet for a customer, with entries.

You have now synchronized your data.

  For the next step, see Lesson 4: Add an order.


Start the application (Windows CE)
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 3: Start the sample application and synchronize

 Start the application (Windows CE)

For synchronization to succeed, you must have the consolidated database server and a MobiLink synchronization server running when you start the sample application.

♦ To start and synchronize the sample application:

1	Connect your Windows CE device to your PC.

When you start the sample application for the first time, it must be able to connect to the MobiLink synchronization server and download an initial copy of the data. This step is required only the first time you start the application. Once you have downloaded the data, it is stored in the UltraLite database.

2	Launch the sample application.

On the CE device, choose Start [image] Programs [image] Sybase [image] CustDB.

3	Enter an employee ID.

When running through this section as a tutorial, enter a value of 50 and press Enter. The application does also allow values of 51, 52, or 53, but behaves slightly differently in these cases.

The application synchronizes after you enter the employee ID, and a set of customers, products, and orders are downloaded to your machine.

4	Confirm that the data has been synchronized into the application.

Confirm that a company name and a sample order appear on the application window.

You have now synchronized your data.

  For the next step, see Lesson 4: Add an order.


Lesson 4: Add an order
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Lesson 4: Add an order

In this section, you display the initial data in the sample application and add a new order. These step are carried out in a similar way in each version of the application.

The application holds information about a set of orders. For each order, this data includes the customer, the product, the quantity, the price, and any applicable discount. Also included are a status field and a notes field, which you can modify from the application.

Only unapproved orders are downloaded to the application. The sample application does not receive all the orders listed in the ULOrder table in the consolidated database. You control which information is sent to your application using synchronization scripts.

 Add an order (Windows 95/98, Windows NT, or Windows CE)

 Add an order (Palm Computing Platform)


Add an order (Windows 95/98, Windows NT, or Windows CE)
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 4: Add an order

 Add an order (Windows 95/98, Windows NT, or Windows CE)

The procedure is the same for Windows CE as for other Windows operating systems.

♦ To add an order:

1	Scroll through the outstanding orders.

Click Next to display the next customer.

2	Open the window to enter a new order.

From the Order menu, choose New.

The Add New Order screen is displayed.

3	Choose a customer.

The UltraLite application holds the complete list of customers from the consolidated database. To see this list, open the Customer drop-down list.

Choose Basements R Us from the list. The current list of orders does not have any from this customer.

4	Choose a product.

The UltraLite application holds the complete list of products from the consolidated database. To see this list, open the Product drop-down list box.

Choose Screwmaster Drill from the list. The price of this item is automatically entered in the Price field.

5	Enter the quantity and discount.

Enter a value of 20 for the quantity, and a value of 5 for the discount.

6	Press Enter to add the new order.

7	Click X to close the New Order screen.

You have now modified the data in your local UltraLite database. This data is not shared with the consolidated database until you synchronize.

  For the next step, see Lesson 5: Act on some existing orders.


Add an order (Palm Computing Platform)
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 4: Add an order

 Add an order (Palm Computing Platform)

♦ To add an order:

1	Scroll through the outstanding orders.

Tap the Down arrow in the bottom right corner to display the next customer.

2	Open the window to enter a new order.

Tap New. The Add New Order screen is displayed.

3	Choose a customer.

The UltraLite application holds the complete list of customers from the consolidated database. To see this list, open the Customer drop-down list.

Choose Basements R Us from the list. The current list of orders does not have any from this customer.

4	Choose a product.

The UltraLite application holds the complete list of products from the consolidated database. To see this list, open the Product drop-down list box.

Choose Screwmaster Drill from the list. The price of this item is automatically entered in the Price field.

5	Enter the quantity and discount.

Enter a value of 20 for the quantity, and a value of 5 for the discount.

6	Add the new order.

Tap Add to add the order.

You have now modified the data in your local UltraLite database. This data is not shared with the consolidated database until you synchronize.

  For the next step, see Lesson 5: Act on some existing orders.


Lesson 5: Act on some existing orders
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Lesson 5: Act on some existing orders

In this step, you approve one order and deny another. Approving or denying orders updates two columns in the local database. No data in the consolidated database is changed until you synchronize.

The instructions for this step are very similar for all platforms.

♦ To approve, deny, and delete orders:

1	Approve the order from Apple Street Builders.

•	Go to the first order in the list, which is from Apple Street Builders.

•	Tap or Click Approve to approve the order.

•	Add a note to your approval, saying Good Work!.

•	The order appears with a status of Approved.

2	Deny the order from Art's Renovations.

•	Go to the next order in the list, which is from Art's Renovations.

•	Tap or click Deny to deny this order.

•	Add a note stating Discount too high.

3	Delete the order from Awnings R Us.

•	Go to the next order in the list, which is from Awnings R Us.

•	Delete this order by choosing Order [image] Delete. It disappears from your local copy of the data.

Having changed these orders, you now need to communicate your changes to the consolidated database.

  For the next step, see Lesson 6: Synchronize your changes.


Lesson 6: Synchronize your changes
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Lesson 6: Synchronize your changes

In this step, you synchronize changes you made on your handheld device to the consolidated database.

For synchronization to take place, your MobiLink synchronization server must be running. If you have shut down your MobiLink synchronization server since the beginning of the tutorial, restart it.

  For instructions, see Lesson 1: Start the MobiLink synchronization server.

 Synchronize your changes (Windows CE, Windows NT, Windows 95/98)

 Synchronize your changes (Palm Computing Platform)


Synchronize your changes (Windows CE, Windows NT, Windows 95/98)
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 6: Synchronize your changes

 Synchronize your changes (Windows CE, Windows NT, Windows 95/98)

♦ To synchronize your changes:

1	If you are running on a Windows CE handheld device, place the device in its cradle, so that it can connect to the machine running the MobiLink synchronization server.

2	Choose File [image] Synchronize to synchronize your data.

3	Confirm that the synchronization took place.

•	Confirm that the approved order for Apple Street Builders is no longer in your application.

•	The synchronization process for this sample application removes approved orders from your application.

  For the next step, see Lesson 7: Confirm the synchronization at the consolidated database.


Synchronize your changes (Palm Computing Platform)
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 6: Synchronize your changes

 Synchronize your changes (Palm Computing Platform)

♦ To synchronize your changes:

1	Place the Palm device in its cradle.

2	Press the HotSync button to synchronize.

3	Confirm that the synchronization took place.

•	Confirm that the approved order for Apple Street Builders is no longer in your application.

•	The synchronization process for this sample application removes approved orders from your application.

  For the next step, see Lesson 7: Confirm the synchronization at the consolidated database.


Lesson 7: Confirm the synchronization at the consolidated database
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Lesson 7: Confirm the synchronization at the consolidated database

In this step, you use Interactive SQL to connect to the consolidated database and confirm that the changes made have been synchronized. This step is independent of the platform on which your UltraLite application is running

♦ To confirm that the changes are synchronized to the consolidated database:

1	Connect to the consolidated database from Interactive SQL.

In the Interactive SQL connection dialog, choose the UltraLite 7.0 Sample ODBC data source.

2	Confirm the status change of the approved and denied orders.

To confirm that the approval and denial have been synchronized, issue the following statement.

SELECT order_id, status

FROM ULOrder

WHERE status IS NOT NULL

The results show that order 5100 is approved, and 5101 is denied.

3	Confirm that the deleted order has been removed.

The deleted order has an order_id of 5102. The following query returns no rows, demonstrating that the order has been removed from the system.

SELECT *

FROM ULOrder

WHERE order_id = 5102

The tutorial is now complete.


Lesson 8: Browse the consolidated database
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Lesson 8: Browse the consolidated database

You can use Sybase Central to manage MobiLink synchronization. The synchronization logic is held in the consolidated database.

This section describes how to use Sybase Central to browse the scripts in the CustDB consolidated database.

 The CustDB database

 Connect to the CustDB database from Sybase Central

 Browse the synchronization scripts


The CustDB database
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 8: Browse the consolidated database

 The CustDB database

The following figure shows the tables in the CustDB consolidated database and how they relate to each other.

The tables hold the following information.

•	ULCustomer    A list of customers.

•	ULProduct    A list of products.

•	ULEmployee    A list of sales employees. This table is not present in the UltraLite database.

•	ULEmpCust    A many-to-many relationship between employees and customers. This table is not present in the UltraLite database.

•	ULOrder    A list of orders, including details of the customer who placed the order, the employee who took the order, and the product being ordered.

•	ULCustomerIDPool    A table to maintain unused unique primary key values on the customer table throughout a deployed UltraLite system.

•	ULOrderIDPool    A table to maintain unused unique primary key values on the order table throughout a deployed UltraLite system.

•	ULIdentifyEmployee    This table holds a list of employee ID numbers.


Connect to the CustDB database from Sybase Central
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 8: Browse the consolidated database

 Connect to the CustDB database from Sybase Central

1	Start the CustDB database    If it is not already running, start the database server.

Select Programs [image] Sybase SQL Anywhere 7 [image] UltraLite [image] UltraLite Sample Database.

An Adaptive Server Anywhere database server starts, running the CustDB UltraLite Sample Database.

2	Start Sybase Central    From the Start menu, select Programs [image] Sybase SQL Anywhere 7 [image] Sybase Central 4.0.

3	Connect Sybase Central to the sample database    In Sybase Central, select Tools [image] Connect. If there is a choice of connection types, select MobiLink. The MobiLink connection dialog is displayed.

Select ODBC, enter UltraLite 7.0 Sample in the Data Source box. Click OK to connect.

You are now connected to the CustDB sample database.


Browse the synchronization scripts
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

        Lesson 8: Browse the consolidated database

 Browse the synchronization scripts

From Sybase Central, you can browse through the tables, users, synchronized tables, and synchronization scripts that are stored in the consolidated database. Sybase Central is the primary tool for adding these scripts to the database.

Open the Connection Scripts folder. The right hand pane lists a set of synchronization scripts and a set of events that these scripts are associated with. As the MobiLink synchronization server carries out the synchronization process, it triggers a sequence of events. Any synchronization script associated with an event is run at that time. By writing synchronization scripts and assigning them to the synchronization events, you can control the actions that are carried out during synchronization.

Open the Synchronized Tables folder, and open the ULCustomer table folder. The right hand pane lists a pair of scripts that are specific to this table, and their corresponding events. These scripts control the way that data in the ULCustomer table is synchronized with the remote databases.

This section does not discuss the content of the synchronization scripts. These are discussed in detail in the chapter Writing Synchronization Scripts.


Summary
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 2.  Tutorial: A Sample UltraLite Application

 Summary

In this tutorial you learned how to:

•	Copy an UltraLite application to a Palm or Windows CE device.

•	Start and work with the sample application on a Palm or Windows CE device, or on Windows.

•	Synchronize changes with a consolidated database, via the MobiLink synchronization server.

•	Use Sybase Central to view the scripts controlling the synchronization process.

The CustDB sample application is used throughout the current book and in the Replication and Synchronization Guide to illustrate programming methods and synchronization techniques.


CHAPTER 3.  UltraLite Overview
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

 CHAPTER 3.  UltraLite Overview

About this chapter

This chapter describes the features and internal organization of UltraLite databases.

 UltraLite database features

 Backup, recovery, and transaction processing

 UltraLite database internals

 Synchronizing UltraLite applications

 Character sets in UltraLite


UltraLite database features
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

 UltraLite database features

This background information is provided to help you better understand how UltraLite works, and to understand the features supported by UltraLite databases.

 UltraLite data types

 Size and number limitations for UltraLite databases

 UltraLite tables must have primary keys

 User IDs in UltraLite databases

 SQL features and limitations of UltraLite applications

 Including non-synchronizing tables in UltraLite databases


UltraLite data types
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database features

 UltraLite data types

UltraLite supports all Adaptive Server Anywhere data types, with the following exceptions.

•	Java data types

•	CHAR(n), VARCHAR(n), BINARY(n), VARBINARY(n) data types, where n > 2048. You can use LONG VARCHAR and LONG BINARY data types to hold this kind of information.

•	The maximum size of LONG VARCHAR and LONG BINARY values is 64 Kb.

•	Domains (user-defined data types) that include DEFAULT values or CHECK constraints. You can use IMAGE or TEXT data types.

•	The BIGINT data type is not supported on DOS.

As you design your database, you should also confirm that MobiLink supports the features you wish to use.

  For a list of Adaptive Server Anywhere data types, see SQL Data Types.


Size and number limitations for UltraLite databases
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database features

 Size and number limitations for UltraLite databases

The following table lists the absolute limitations imposed by data structures in the software on the size and number of objects in an UltraLite database. In most cases, the memory, CPU, and disk drive of the computer, and the response time of the database, impose stricter limits.

Item	Limitation
Number of connections per database	14
Number of columns per table	65535 but limited by row size
Number of indexes	65535
Number of rows per database	Limited by persistent store
Number of rows per table	65533
Number of tables per database	Approximately 1000
Number of tables referenced per transaction	No limit
Row size	Approximately 4 Kb (compressed). LONG VARCHAR and LONG BINARY values are stored separately, and are in addition to the 4K limit.
File-based persistent store	2 Gb file or OS limit on file size
Palm Computing Platform database size	512 Mb


UltraLite tables must have primary keys
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database features

 UltraLite tables must have primary keys

Each table in your UltraLite application must include a primary key.

The UltraLite generator uses primary keys from your reference database to generate primary keys in the UltraLite database. If the primary key columns for any table are not included in the data required in the UltraLite database, the UltraLite generator looks for a uniqueness constraint on the table, and promotes the columns with such a constraint to a primary key in the UltraLite database. If there are no unique columns, the generator reports an error.

Primary keys are required not only for UltraLite applications, but also during MobiLink synchronization, to associate rows in the UltraLite database with rows in the consolidated database.


User IDs in UltraLite databases
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database features

 User IDs in UltraLite databases

Each UltraLite application has its own database, and that database contains data that can be accessed only by its application. UltraLite does not require or use database user IDs for connection or permission checking, or when referencing tables. In other words, there are no user IDs in UltraLite databases.

In the CustDB sample application, and in other UltraLite applications, you may be prompted for a user name when starting the application. This user name identifies the database for the purposes of MobiLink synchronization, and is not an UltraLite user ID for connection or data access purposes.

A reference database user ID and password are used during development. For example, you must supply a user ID and password when running the UltraLite generator, or when adding SQL statements to the reference database.

  For the use of a user ID and password in embedded SQL CONNECT statements, see User IDs and database authorization.


SQL features and limitations of UltraLite applications
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database features

 SQL features and limitations of UltraLite applications

The following SQL statements can be used in UltraLite applications:

•	Data Manipulation Language    SELECT, INSERT, UPDATE, and DELETE statements can be included. You can use placeholders in these statements that are filled in at runtime.

  For more information, see Writing UltraLite SQL statements.

•	TRUNCATE TABLE statement    You can use this statement to rapidly delete entire tables.

•	Transaction control    You can use COMMIT and ROLLBACK statements to provide transaction control within your UltraLite application.

•	START/STOP SYNCHRONIZATION DELETE statements    These statements are used to temporarily suspend synchronization of delete operations.

  For more information, see Temporarily stopping synchronization of deletes.

Some features of Adaptive Server Anywhere cannot be used in UltraLite databases. You cannot use the following Adaptive Server Anywhere features in your UltraLite applications:

•	Dynamic SQL    All SQL in UltraLite applications must be known at compile time (static SQL), so that the analyzer can generate code to process the statements. You can not include code in your application that generates and executes arbitrary SQL statements. You can, however, use parameterized SQL statements to control the behavior of your statements at run time.

If you need the capability to execute dynamic SQL, or need other features not present in UltraLite, consider using Adaptive Server Anywhere. Adaptive Server Anywhere is a full-featured database that has a footprint small enough for many mobile and embedded applications.

•	Cascading updates and deletes    Some applications rely on declarative referential integrity to implement business rules. These features are not available in UltraLite databases.

•	Check constraints    You cannot include table or column check constraints in an UltraLite database.

•	Timestamp columns    You cannot use Transact-SQL timestamp columns in UltraLite databases. Transact-SQL timestamp columns are created with the following default:

DEFAULT TIMESTAMP

You can use columns created as follows:

DEFAULT CURRENT TIMESTAMP

There is a behavior difference between the two: a DEFAULT CURRENT TIMESTAMP column is not automatically updated when the row is updated, while a DEFAULT TIMESTAMP column is automatically updated. You must explicitly update columns created with DEFAULT CURRENT TIMESTAMP if you wish the column to reflect the latest update time.

•	Schema modification    To modify the schema of a UltraLite database, you must build a new version of your application.

  For more information, see Schema changes in remote databases.

•	Global temporary tables    The temporary aspect of global temporary tables is not recognized by UltraLite. They are treated as if they were permanent base tables, which you should use instead.

•	Declared temporary tables    You cannot declare a temporary table within an UltraLite application.

•	System table access    There are no system tables in an UltraLite database.

•	Stored procedures    You cannot call stored procedures or user-defined functions in an UltraLite application.

•	Java in the database    You cannot include Java methods in your queries or make any other use of Java in the database.

•	SQL variables    You cannot use SQL variables in UltraLite applications, including global variables such as @@identity.

•	SAVEPOINT statement    UltraLite databases support transactions, but not savepoints within transactions.

•	SET OPTION statement    You can determine the option settings in an UltraLite database by setting them in the reference database, but you cannot use the SET OPTION statement in an UltraLite application to change option settings.

•	System functions    You cannot use Adaptive Server Anywhere system functions, including property functions, in UltraLite applications.

•	Triggers    Triggers are not available in UltraLite databases.

The SQL error message Feature not available in UltraLite is reported when an UltraLite program attempts to use a SQL statement or feature that is not supported in UltraLite.

•	SELECT INTO limitation    You cannot use SELECT INTO statement to fill host variables with data from more than a single table. Instead, you should use separate single-table statements.


Including non-synchronizing tables in UltraLite databases
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database features

 Including non-synchronizing tables in UltraLite databases

By default, all tables in an UltraLite database are synchronized to the consolidated database. You can include tables in your UltraLite database that are excluded from synchronization, but you must explicitly identify these tables when you create your reference database.

Tables with names ending in nosync are excluded from synchronization. You can use these tables for persistent data that is not related to the consolidated database. Other than being excluded from synchronization, you can use these tables in exactly the same way as other tables in the UltraLite database.


Backup, recovery, and transaction processing
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

 Backup, recovery, and transaction processing

The best way of making a backup of an UltraLite application is to synchronize with a consolidated database. To restore an UltraLite database, start with an empty database and populate it from the consolidated database through synchronization.

UltraLite provides protection against system failures, but not against media failures. If the UltraLite data store itself is corrupted, the only way to protect is through synchronization.

UltraLite provides transaction processing. If an application using an UltraLite database stops running unexpectedly, the UltraLite database automatically recovers to a consistent state when the application is restarted. All transactions committed prior to the unexpected failure are present in the UltraLite database. All transactions not committed at the time of the failure are rolled back.

UltraLite does not use a transaction log to perform recovery. Instead, UltraLite uses the state byte for every row to determine the fate of a row when recovering. When a row is inserted, updated, or deleted in an UltraLite database, the state of the row is modified to reflect the operation and the connection that performed the operations. When a transaction is committed, the states of all rows affected by the transaction are modified to reflect the commit. If an unexpected failure occurs during a commit, the entire transaction is rolled back on recovery.

  For more information on state bytes, see How UltraLite tracks row states.


UltraLite database internals
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

 UltraLite database internals

This section gives an outline of how data is stored in an UltraLite database, and how UltraLite maintains data in a database.

 Database storage mechanism

 The information in an UltraLite database

 How UltraLite tracks row states

 Indexes in UltraLite databases


Database storage mechanism
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database internals

 Database storage mechanism

Each UltraLite application has its own database. The UltraLite runtime creates the database when you first start your application. The physical storage of the UltraLite database depends on the target platform. In all cases, except for Java, the database is persistent by default: it continues to exist when the application is not running.

•	On the Palm Computing Platform, the UltraLite database is stored in the Palm persistent (static) memory using the Data Manager API.

•	On Windows CE, the UltraLite database is stored in the file system. The default file is \UltraLiteDB\ul.udb.

•	On VxWorks, UltraLite requires a dosFs (MS-DOS-compatible file system) device or a functionally equivalent device to store the persistent data file. UltraLite defaults to using a device named ULDEV:, and a filename ul_<project>.udb, where <project> is the UltraLite project name, and the filename is truncated to an 8.3 format. You can configure a storage device with this name and it will be used to store persistent data for the application, or you can override the default filename and specify a different device.

•	In Java applications, the database is either transient, or is stored as a file in the file system. By default, it is transient.

•	On DOS, the UltraLite database is stored in the file system. The default file is ul_<project>.udb in the working directory of the application, where <project> is the UltraLite project name used during the development process. The filename is truncated to 8.3 format.

•	On Windows 95/98 and Windows NT, the UltraLite database is stored in the file system. The default file is ul_<project>.udb in the working directory of the application, where <project> is the UltraLite project name used during the development process.

  For information on configuring UltraLite databases in C and C++ applications, see Configuring file-based persistent storage.

  For information on configuring UltraLite Java databases, see UltraLite JDBC URLs.


The information in an UltraLite database
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database internals

 The information in an UltraLite database

UltraLite stores the rows of data in each table. It also stores state information about each row, and stores indexes to efficiently access the rows.

UltraLite performs compression on values in an UltraLite database when they are stored in persistent memory. UltraLite compresses variable length strings, integers, numerical values, and date/time data. The only time UltraLite does not compress the raw data is when the columns contain fixed length character or binary data.


How UltraLite tracks row states
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database internals

 How UltraLite tracks row states

Each row in an UltraLite database has a one-byte marker to keep track of the state of the row. The row states are used to control transaction processing, recovery, and synchronization.

When a delete is issued, the state of each affected row is changed to reflect the fact that it was deleted. Rolling back a delete is as simple as restoring the original state of the row.

When a delete is committed, the affected rows are not always removed from memory. If the row has never been synchronized, then it is removed. If the row has been synchronized, then it is not removed until the next synchronization confirms the delete with the consolidated database. After the next synchronization, the row is removed from memory.

Similarly, when a row is updated in an UltraLite database, a new version of the row is created. The states of the old and new rows are set so the old row is no longer visible and the new row is visible. When an update is synchronized, both the old and new versions of the row are needed to allow conflict detection and resolution.

The old version of the row is deleted after synchronization. If a row is updated many times between synchronizations, only the oldest version of the row and the most recent version of the row are kept.


Indexes in UltraLite databases
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        UltraLite database internals

 Indexes in UltraLite databases

UltraLite indexes are B+ trees with very small index entries.

In C/C++ UltraLite databases, each index entry is exactly two bytes, and each index page contains 256 entries. Since index pages are rarely 100% full and each index has some fixed overhead, the memory used by an UltraLite index is more than two bytes per row in the table. The overhead for each index is just over 1 Kb per index. Typically, UltraLite index pages on larger tables will be least 85% full.

No similar consistent rule can be given for the memory requirements of UltraLite Java databases.


Synchronizing UltraLite applications
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

 Synchronizing UltraLite applications

Adding MobiLink synchronization to an UltraLite application is a matter of supplying arguments to a function call. The details of the call, and the synchronization options available to your application, depend on your target platform. This section summarizes the supported synchronization streams, and the kind of information you need to supply when synchronizing.

See also

For more information on synchronization, see About MobiLink Synchronization.

For an introduction to synchronization concepts, see MobiLink Synchronization.

For information about synchronization techniques, see Synchronization Techniques.

 Supported synchronization streams


Supported synchronization streams
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

        Synchronizing UltraLite applications

 Supported synchronization streams

The following synchronization streams are supported:

Synchronization stream	Supported languages and platforms
TCP/IP	C/C++ and Java. All platforms.
Serial	All C/C++ target platforms except DOS and VxWorks.
HTTP	C/C++ and Java. All platforms.
HotSync	Palm Computing Platform only.
ScoutSync	Palm Computing Platform only.
  For a list of the supported target platforms under C/C++ and Java, see Supported platforms.

The HotSync synchronization stream is the method used by many Palm OS applications. ScoutSync is a synchronization technology licensed by Palm Computing for incorporation into their HotSync Server.


Character sets in UltraLite
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 3.  UltraLite Overview

 Character sets in UltraLite

An UltraLite application uses the collating sequence of the reference database if either of the following conditions is met.

•	The reference database uses a single-byte character set.

•	The native character encoding of the target device is multi-byte, the reference database uses the same multi-byte character encoding, and the UltraLite analyzer can find a compact representation for the collation sequence used by the reference database.

Multi-byte platforms

An UltraLite application uses the native multi-byte character encoding of the target platform for reasons of efficiency. When the reference database uses a different character encoding, the UltraLite application uses the default collation of the target device.

For example, if you use a SJIS reference database to build an UltraLite application for the Windows CE platform, the application will use Unicode and the default Unicode collation information. If, instead, you use a SJIS reference database to build an application for the Japanese Palm Computing Platform, then the UltraLite application can inherit the collation information because the native character encoding is the same as that of the reference database.

Sort orders

If the character set is single byte, or the native character set of the target device is the same as the character set of the reference database, columns that are CHAR(n) or VARCHAR(n) compare and sort according to the collation sequence of the reference database.

Synchronization

When you synchronize, the MobiLink synchronization server always translates characters uploaded from your application database to Unicode and passes them to your consolidated database server using the Unicode ODBC API. The consolidated database server, or its ODBC driver, then performs any translation that may be required to convert them to the character encoding of your consolidated database. This second translation will always occur unless your consolidated database uses Unicode.

When information is downloaded, the consolidated database server converts the characters to Unicode. The MobiLink Synchronization server then automatically translates the characters, if necessary, to suit the requirements of your UltraLite application.

When both UltraLite application and consolidated database use the same character encoding, no translation is necessary. If translation is necessary, problems can arise when multiple character codes in your UltraLite application map to a single Unicode value, or vice versa. In this event, the MobiLink server translates in a consistent manner, but behavior is influenced by the translation mechanism within the consolidated database server.

Palm Computing Platform

At the time of printing, all single-byte Palm Computing Platform devices uses a character set based on code page 1252 (the Windows US code page). The default Adaptive Server Anywhere collation sequence (1252latin1) is appropriate for developing applications for the Palm Computing Platform. Japanese Palm Computing Platform devices use SJIS.

Windows CE

The Windows CE operating system uses Unicode. UltraLite running on Windows CE also uses Unicode to store CHAR(N) and VARCHAR(N) columns. Adaptive Server Anywhere collating sequences define behavior for 8-bit ASCII character sets.

UltraLite for Windows CE uses the Adaptive Server Anywhere collating sequence when comparing Unicode characters that have a corresponding 8-bit ASCII character in the collating sequence being used, allowing accented characters to compare equal and sort with unaccented characters. Unicode characters that have no corresponding 8-bit ASCII character use a comparison of two Unicode values.

Java

The error-handling objects SQLException and SQLWarning provide the capability for Java applications to obtain error or warning messages. By default, these messages are supplied in English.

Localized error and warning messages may be obtained in a non-English language by setting the Java Locale to the appropriate language. For example, to obtain French messages, the following code fragment might be used:

java.util.Locale locale = new java.util.Locale( "fr", "" );

java.util.Locale.setDefault( locale );

The default Locale should be set at the start of the program. Once a message is placed in an error-handling object, the language to be used for the message is established for that execution of the program.


CHAPTER 4.  Developing UltraLite Applications
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

 CHAPTER 4.  Developing UltraLite Applications

About this chapter

This chapter presents an overview of the UltraLite development process.

UltraLite applications can be developed using either C/C++ or using Java. Later chapters in the book describe the specifics of each approach. This chapter describes aspects common to all UltraLite application development.

  For additional information, specific to your target device, see Platform-Specific Development.

 Introduction

 Preparing a reference database

 Defining SQL statements for your application

 Generating the UltraLite data access code

 Adding synchronization to your application

 Configuring development tools for UltraLite development

 Deploying your application


Introduction
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

 Introduction

UltraLite development models

UltraLite supports the following development models:

•	C++ applications using the UltraLite C++ API.

•	C/C++ applications using embedded SQL.

•	Java applications.

The overall development process for each model is similar, but the details are different. This chapter describes those aspects of development that are similar among the development models. It should be used together with the chapter on the particular development model you are using:

•	Developing C++ API Applications

•	Developing Embedded SQL Applications

•	Developing UltraLite Java Applications

Host and target platforms

UltraLite applications are developed on a host platform, and deployed on a target platform. The host platform is PC-based, and the target platform is generally a handheld or embedded device.

To create an UltraLite application, you need to use a development tool or compiler that supports your target platform, together with the UltraLite development tools. For example, you may want to use Metrowerks CodeWarrior for Palm OS development, or Microsoft Visual C++ for Windows CE development.

  For information on supported host platforms, target platforms, and development tools, see Supported platforms.

  For information specific to each target platform, see Platform-Specific Development.

 The UltraLite development environment

 The UltraLite development process

 Adding synchronization


The UltraLite development environment
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Introduction

 The UltraLite development environment

When developing UltraLite applications, you will be working with the following tools.

•	A reference database    A reference database is an Adaptive Server Anywhere database that serves as a model of the UltraLite database you want to create. You create this database yourself, using tools such as Sybase Central.

Your UltraLite database is a subset of the columns, tables, and indexes, in your reference database. The arrangement of tables and of the foreign key relationships between them is called the database schema.

In addition to modeling the UltraLite database, you need to add the SQL statements that are to be included in your UltraLite application to the reference database.

  For more information, see Preparing a reference database.

•	A supported development tool    You use a standard development tool to develop UltraLite applications. For the non-UltraLite specific portions of your application, such as the user interface, use your development tool in the usual way. For the UltraLite-specific data-access portions, you also need to use the UltraLite development tools.

It can be convenient to separate the data access code from the user interface and internal logic of your application.

  For information on supported application development tools, see Supported platforms.

•	UltraLite development tools    UltraLite includes several tools for development.

•	The UltraLite generator    This application uses Java classes in the reference database to generate source code that implements the underlying query execution, data storage, and synchronization features of your application. The generator is required for all kinds of UltraLite development. The Java classes in the database are called the UltraLite Analyzer.

•	The SQL preprocessor    This application is needed only if you are developing an UltraLite application using embedded SQL. It reads your embedded SQL source files and generates standard C/C++ files. As it scans the embedded SQL source files, it also stores information in the reference database that is used by the generator.

•	UltraLite runtime libraries    UltraLite includes a runtime library for each target platform. On some platforms, this is a static library that becomes part of your application executable; on other platforms it is a dynamic link library. For Java, the runtime library is a jar file. UltraLite includes all the header files and import files needed to use the runtime libraries.


The UltraLite development process
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Introduction

 The UltraLite development process

The basic features of the development process are common to all development models. The following diagram summarizes the key features.

•	Create a reference database, which contains a superset of the tables to be included in your application. It may also contain representative data for your application. This reference database is needed only as part of the development process, and is not required by your final application.

•	Add the SQL statements into a special table in the reference database. The way this is accomplished is dependent on the development model you choose:

•	If you are using the C++ API or Java, these statements are added to your database using Sybase Central or a stored procedure.

•	If you are using embedded SQL, the SQL preprocessor adds the statements to the reference database for you.

•	Run the UltraLite generator, which produces source files that include code needed to execute your SQL statements, and code needed to define the database schema for your UltraLite application. This generated code includes function calls into the UltraLite runtime library.

•	Create application source files. If you are using embedded SQL, the SQL preprocessor reads your .sqc files and inserts the SQL statements into the reference database for you.

•	Compile your application source files together with the generated source files to produce your UltraLite application.


Adding synchronization
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Introduction

 Adding synchronization

Most UltraLite applications include synchronization to integrate their data with data on a consolidated database. Adding synchronization to your application is a straightforward task.

  For information on how to add synchronization to your application, and the kinds of synchronization available, see Adding synchronization to your application.


Preparing a reference database
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

 Preparing a reference database

To implement the UltraLite database engine for your application, the UltraLite generator must have access to an Adaptive Server Anywhere reference database. This database must contain the following information:

•	The database objects used in your UltraLite application, including tables and any indexes on those tables you wish to use in your application.

•	The UltraLite system tables must contain any SQL statements you wish to use in your application.

•	(Optional) You can fill your reference database with data that is similar in quantity and distribution to the data you expect your UltraLite database to hold. The UltraLite analyzer automatically uses this information to optimize the performance of your application.

You can design and build the reference database using familiar methods and tools. You can use the schema of an existing database as a starting point.

 Creating a reference database

 Setting database options in the reference database

 Using an existing database as a reference database


Creating a reference database
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Preparing a reference database

 Creating a reference database

The analyzer uses the reference database as a template when constructing your UltraLite application.

♦ To create a reference database:

1	Start with an existing Adaptive Server Anywhere database or create a new database using the dbinit command. The database must be Java-enabled, the default.

  For more information on upgrading a database, see Using an existing database as a reference database.

2	Add the tables and foreign key relationships that you need within your application. You can use any convenient tool, such as Sybase Central or Sybase SQL Modeler (included with SQL Anywhere Studio), or a more powerful database design tool such as Sybase PowerDesigner.

Performance tip
You do not need to include any data in your reference database. However, if you populate your database tables with data representative of the data you expect to be stored by a typical user of your application, the UltraLite analyzer automatically uses this data to optimize the performance of your application.

  For information about designing a database and creating a schema, see Designing Your Database.

Example

1	Create a database.

From a command prompt, execute the following statement:

dbinit path\dbname.db

2	Use Sybase Central to add tables for your UltraLite application, based on your own needs.

3	Add your sample data. Interactive SQL includes an Import menu item that allows several common file formats to be imported.

  For more information, see Import tasks.


Setting database options in the reference database
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Preparing a reference database

 Setting database options in the reference database

UltraLite does not support the getting or setting of option values.

When the UltraLite application is generated, certain option values in the reference database affect the behavior of the generated code. The following options have an effect:

•	Date_format

•	Date_order

•	Nearest_century

•	Precision

•	Scale

•	Time_format

•	Timestamp_format

By setting these options in the reference database, you can control the behavior of your UltraLite database. The option setting in your reference database is used when generating your UltraLite application.


Using an existing database as a reference database
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Preparing a reference database

 Using an existing database as a reference database

Many UltraLite applications synchronize data via MobiLink with a central, master store of data called the consolidated database. Do not confuse a reference database with a consolidated database. The reference database for the UltraLite application is generally a different database from the consolidated database.

Only an Adaptive Server Anywhere consolidated database can also be used as a reference database. If your consolidated database is of another type, you must create an Adaptive Server Anywhere reference database. Even if your consolidated database is Adaptive Server Anywhere, you must create a separate reference database if you wish to have a different schema or use different settings in your UltraLite application.

You can choose any of the supported ODBC-compliant database management products to create and manage the consolidated database, including Adaptive Server Enterprise, Adaptive Server Anywhere, Oracle, Microsoft SQL Server, and IBM DB2.

If you have an existing Adaptive Server Anywhere database that you will be using as a consolidated database, you could make a copy of it for your reference database.

♦ To create a reference database from another type of database:

1	Create a new Adaptive Server Anywhere database.

You can use the dbinit command or use Sybase Central. The database must be Java-enabled, which is the default setting.

2	Add the tables and foreign-key relationships that you need within your application using your consolidated database as a guide.

You can use a tool such as Sybase Physical Data Architect to re-engineer the consolidated database.

3	Populate your database tables with representative data from your consolidated database.

You need not transfer all the information in your consolidated database, only a representative sample. In the early stages of development, you do not need sample data at all. For production applications, you may want to use representative data because access plans of UltraLite queries are based on the distribution of data in the reference database.


Defining SQL statements for your application
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

 Defining SQL statements for your application

All the data access instructions for your application are defined by adding SQL statements to the reference database.

If you use the C++ API, you can also use SQL Remote publications to define data access methods. For information on using publications, see Defining UltraLite tables.

If you are using embedded SQL, the SQL preprocessor carries out the tasks in this section for you.

 Creating an UltraLite project

 Adding SQL statements to an UltraLite project

 Writing UltraLite SQL statements


Creating an UltraLite project
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Defining SQL statements for your application

 Creating an UltraLite project

When you add SQL statements to a reference database, you assign them to an UltraLite project. By grouping them this way, you can develop multiple applications using the same reference database.

When the UltraLite generator runs against a reference database to generate the database source code files, it takes a project name as an argument and generates the code for the SQL statements in that project.

You can define an UltraLite project using Sybase Central or by directly calling a system stored procedure.

If you are using embedded SQL, the SQL preprocessor defines the UltraLite project for you and you do not need to create it explicitly.

♦ To create an UltraLite project (Sybase Central):

1	From Sybase Central, connect to your reference database.

  For instructions on using Sybase Central, see Connect to the sample database.

2	In the left pane, open the database container.

3	In the left pane, open the UltraLite Projects folder.

4	In the right pane, double-click Add UltraLite Project.

The New UltraLite Project dialog is displayed.

5	Enter an UltraLite project name and click OK to create the project in the database.

  For information on UltraLite project naming rules, see ul_add_project system procedure.

♦ To create an UltraLite project (SQL):

•	From Interactive SQL or another application, enter the following command:

call ul_add_project( 'project-name' )

where project-name is the name of the project.

  For more information, see ul_add_project system procedure.

♦ To create an UltraLite project (embedded SQL):

•	If you are using the embedded SQL development model, specify the UltraLite project name on the SQL Preprocessor command line, and the preprocessor adds the project to the database for you.

  For more information, see Pre-processing your embedded SQL files.

Notes

UltraLite project names must conform to the rules for database identifiers. If you include spaces in the project name, do not enclose the name in double quotes, as these are added for you by Sybase Central or the stored procedure.

  For more information, see Identifiers.


Adding SQL statements to an UltraLite project
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Defining SQL statements for your application

 Adding SQL statements to an UltraLite project

Each UltraLite application carries out a set of data access requests. These requests are implemented differently in each development model, but the data access requests are defined in the same way for each model.

You define the data access requests that an UltraLite application can carry out by adding a set of SQL statements to the UltraLite project for that application in your reference database. The UltraLite generator then creates the code for a database engine that can execute the set of SQL statements.

In the C++ API, you can also use SQL Remote publications to define data access methods. For information on using publications, see Defining UltraLite tables.

You can add SQL statements to an UltraLite project using Sybase Central, or by directly calling a system stored procedure. If you are using embedded SQL, the SQL preprocessor adds the SQL statements in your embedded SQL source files to the reference database for you.

♦ To add a SQL statement to an UltraLite project (Sybase Central):

1	From Sybase Central, connect to your reference database.

  For instructions on using Sybase Central, see Connect to the sample database.

2	In the left pane, open the database container.

3	In the left pane, open the UltraLite Projects folder.

4	Open the project for your application.

5	Double-click Add UltraLite Statement.

The Create a New UltraLite Project Statement dialog is displayed.

6	Enter a short, descriptive name for the statement, and click Next

7	Enter the statement itself, and click Finish to add the statement to the project.

You can start Interactive SQL from this dialog, which allows you to test SQL statements against the database.

  For information on what kinds of statement you can use, see Writing UltraLite SQL statements.

♦ To add a SQL statement to an UltraLite project (SQL):

•	From Interactive SQL or another application, enter the following command:

call ul_add_statement( 'project-name',

'statement-name',

'sql-statement' )

where project-name is the name of the project, statement-name is a short descriptive name, and sql-statement is the actual SQL statement.

  For more information, see ul_add_statement system procedure.

♦ To add a SQL statement to an UltraLite project (embedded SQL):

•	If you are using the embedded SQL development model, specify the UltraLite project name on the SQL Preprocessor command line.

No statement name is used in embedded SQL development.

  For more information, see Pre-processing your embedded SQL files.

Notes

Statement names should be short and descriptive. They are used by the UltraLite generator to identify the statement for use in Java or in the C++ API. For example, a statement named ProductQuery generates a C++ API class named ProductQuery and a Java constant named PRODUCT_QUERY. Names should be valid SQL identifiers.

The SQL statement syntax is checked when you add the statement to the database, and syntax errors give an error message to help you identify mistakes.

You can use Sybase Central or ul_add_statement to update a statement in a project, in just the same way as you add a statement. If a statement already exists, it is overwritten with the new syntax. You must regenerate the UltraLite code whenever you modify a statement.


Writing UltraLite SQL statements
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Defining SQL statements for your application

 Writing UltraLite SQL statements

This section describes what SQL statements you can add to an UltraLite project, and describes how to use placeholders in your SQL statements.

  For information on the range of SQL that you can use, see SQL features and limitations of UltraLite applications.

How to supply double quotes

The SQL statement that you enter, whether into Sybase Central or as an argument to ul_add_statement, is added to the reference database as a string. It must therefore conform to the rules for SQL strings.

You must escape some characters in your SQL statements using the backslash character.

  For information on SQL strings, see Strings.

Using variables with statements

For most insert or update statements, you do not know the new values ahead of time. You can use question marks as placeholders for variables, and supply values at run time:

call ul_add_statement(

'ProductApp',

'AddCap',

'INSERT INTO \"dba\".product ( id, name, price )

VALUES( ?, ?, ? )'

)

Placeholders can also be used in the WHERE clause of queries:

call ul_add_statement(

'ProductApp',

'ProductQuery',

'SELECT id, name, price

 FROM \"dba\".product

 WHERE price > ?'

)

The backslash characters are used to escape the double quotes.

In embedded SQL, you use host variables as placeholders. For more information, see Using host variables.

For SQL statements containing placeholders, an extra parameter on the Open or Execute method of the generated C++ class is defined for each parameter. For Java applications, you use the JDBC set methods to assign values for the parameters.


Generating the UltraLite data access code
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

 Generating the UltraLite data access code

To generate the code for storing and accessing the UltraLite database, the UltraLite generator analyzes your reference database and the SQL statements you use in your application. It does so using a set of Java classes that run inside your reference database, called the UltraLite analyzer.

The UltraLite analyzer generates code that implements data access and storage for your application. It is a single application that can generate either C/C++ or Java code, depending on the command-line options you supply.

The data storage code includes only those tables and columns of the reference database that you use in your application. Additionally, the analyzer includes indexes present in your reference database whenever they improve the efficiency of your application.

The data access code includes only those SQL statements that you have added to the project in the reference database.

The result is a custom database engine tailored to your application. The engine is much smaller than a general-purpose database engine because the analyzer includes only the features your application uses.

 Using the UltraLite generator

 Error on starting the analyzer


Using the UltraLite generator
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Generating the UltraLite data access code

 Using the UltraLite generator

The UltraLite generator is a command-line application. It takes a set of command-line options to customize the behavior for each project.

♦ To run the UltraLite generator:

•	Enter the following command at a command-prompt:

ulgen -c "connection-string" options

where options depend on the specifics of your project.

The UltraLite generator command-line customizes its behavior. The following command-line switches are used across development models:

•	-c    You must supply a connection string, to connect to the reference database.

  For information on Adaptive Server Anywhere connection strings, see Connection parameters.

•	-f    Specify the output file name.

•	-j    Specify the UltraLite project name.

  For more information on UltraLite generator options, see The UltraLite generator.

If you are using embedded SQL, and if you need to run only a single source file through the SQL preprocessor, you can instruct the preprocessor to also run the UltraLite generation process as a shortcut.

  For more information, see Pre-processing your embedded SQL files.

Which databases contain the UltraLite analyzer?

The generator relies on a current version of the UltraLite analyzer classes being installed into the reference database. If you have upgraded your UltraLite software, you must also upgrade the reference database so that it contains the new analyzer classes.

Older databases, created with previous versions of Adaptive Server Anywhere, may not contain any version of the analyzer. You can upgrade these older databases using the Upgrade utility.

  For more information about upgrading an older Java-enabled database, see Preparing a reference database.


Error on starting the analyzer
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Generating the UltraLite data access code

 Error on starting the analyzer

Either sqlpp or ulgen can report the error message Unable to use Java in the database when these utilities are unable to run the analyzer. The UltraLite analyzer is a Java class that is added to your reference database when it is initialized. For the analyzer to run, the database must have been initialized with Java classes and the database engine must be able to start the Java support in Adaptive Server Anywhere.

The following situations may cause this error to happen:

•	The database was not initialized with Java classes.

•	The Adaptive Server Anywhere database server was not started with a cache of sufficient size. This should not be a problem on Windows NT, where the database server can dynamically increase its cache size.

•	SQL Anywhere Studio was moved to a new directory without uninstalling and reinstalling. In this case, there may be registry entries pointing to the old location.

•	There may be mismatched DLLs or mismatched Java jar files. This can happen if you copy files from a maintenance release or emergency bug fix, but miss copying all the files.


Adding synchronization to your application
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

 Adding synchronization to your application

Synchronization is a key feature of many UltraLite applications. This section describes how to add synchronization to your application.

Overview

The specifics of each synchronization is controlled by a set of synchronization parameters. These parameters are gathered into a structure (C/C++) or object (Java), which is then supplied as an argument in a function call to synchronize. The outline of the method is the same in each development model.

♦ To add synchronization to your application:

1	Initialize the structure (C/C++) or object (Java) that holds the synchronization parameters.

  For information, see Initializing the synchronization parameters.

2	Assign the parameter values for your application.

  For information, see Setting synchronization parameters.

3	Call the synchronization function, supplying the structure or object as argument.

  For information, see Invoking synchronization.

You must ensure that there are no uncommitted changes when you synchronize. For more information, see Commit all changes before synchronizing.

 Initializing the synchronization parameters

 Setting synchronization parameters

 Setting stream_parms values

 Setting synchronization parameters: C/C++ examples

 Invoking synchronization

 Commit all changes before synchronizing

 Adding initial data to your application

 Monitoring and canceling synchronization

 Writing a synchronization callback function


Initializing the synchronization parameters
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Adding synchronization to your application

 Initializing the synchronization parameters

The synchronization parameters are stored in a C/C++ structure or Java object.

C/C++ initialization

In C/C++ the members of the structure may not be well-defined on initialization. You must set your parameters to their initial values with a call to a special function.

The synchronization parameters are defined in a structure declared in the UltraLite header file ulglobal.h.

♦ To initialize the synchronization parameters (embedded SQL):

•	Call the ULInitSynchInfo function. For example:

auto ul_synch_info synch_info;

ULInitSynchInfo( &synch_info );

♦ To initialize the synchronization parameters (C++ API):

•	Call the InitSynchInfo() method on the connection object. For example:

auto ul_synch_info synch_info;

conn.InitSynchInfo( &synch_info );

Java initialization

In Java, the members of any object are initialized by the constructor.

♦ To initialize the synchronization parameters (Java):

•	Use the constructor. For example:

UlSynchOptions synch_options = new UlSynchOptions();

Once the structure or object is initialized, you must set the values to meet your particular requirements.

  For information on the individual parameters, see Setting synchronization parameters.


Setting synchronization parameters
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Adding synchronization to your application

 Setting synchronization parameters

The synchronization parameters are grouped into a structure (C/C++) or object (Java) that is provided as an argument in the call to synchronize. The C/C++ structure has the following members, and the Java UlSynchOptions object has equivalent access methods.

String parameters are null-terminated strings in C/C++, and String objects in Java.

Use UL_TEXT around constant strings in C/C++ applications
The UL_TEXT macro allows constant strings to be compiled as single-byte strings or wide-character strings. In embedded SQL and C++ API applications, use this macro to enclose all constant strings supplied as members of the ul_synch_info structure so that the compiler handles these parameters correctly.

•	user_name    A string specifying the user name that uniquely identifies the application to the MobiLink synchronization server. MobiLink uses this value to determine the download content, to record the synchronization state, and to recover from interruptions during synchronization.

The parameter is required, and is a string.

The Java access methods are getUserName and setUserName.

  For more information, see The synchronization user name.

•	password    A string specifying the MobiLink password associated with the user_name. This user name and password are separate from any database user ID and password, and server to identify and authenticate the application to the MobiLink synchronization server.

The parameter is optional, and is a string.

The Java access methods are getPassword and setPassword.

  For information on MobiLink user authentication, see Authenticating MobiLink users.

•	new_password    A string that sets a new MobiLink password associated with the user_name.

The parameter is optional, and is a string.

The Java access methods are getNewPassword and setNewPassword.

  For information on MobiLink user authentication, see Authenticating MobiLink users.

•	observer    A pointer to a callback function that monitors synchronization. For more information, see Monitoring and canceling synchronization.

The Java access method is setObserver, which takes a UlSynchObserver object as argument. For more information, see Monitoring and canceling synchronization.

•	auth_status    This member is used during MobiLink user authentication. In C/C++, this member is of type ul_auth_status, and has one of the following values:

•	UL_AUTH_STATUS_UNKNOWN    0

•	UL_AUTH_STATUS_VALID    1000

•	UL_AUTH_STATUS_VALID_BUT_EXPIRES_SOON    2000

•	UL_AUTH_STATUS_EXPIRED    3000

•	UL_AUTH_STATUS_INVALID    4000

If you are implementing a custom authentication scheme, the authenticate_user or authenticate_user_hashed synchronization script must return one of these values. The MobiLink synchronization server provides this information to the client.

In Java, the constants are the same as above, but prefixed with UlDefn. You retrieve the authorization status using UlSynchOptions.getAuthStatus().

  For more information, see Authenticating MobiLink users.

•	version    Each synchronization script in the consolidated database is marked with a version string. For example, there may be two different download_cursor scripts, identified by different version strings. The version string allows an UltraLite application to choose from a set of synchronization scripts.

The parameter is a string, and by default is the MobiLink default version string.

The Java access methods are getScriptVersion and setScriptVersion.

  For information about script versions, see Script versions.

•	stream    A stream definition returned by one of the UltraLite stream functions. When the type of stream requires a parameter, pass that parameter using the stream_parms parameter; otherwise, set the stream_parms parameter to null.

The following C/C++ stream functions are available, but may not be supported on all platforms:

Stream	Description
ULConduitStream()	Synchronize via HotSync or ScoutSync stream (C/C++ only, Palm Computing Platform only)
ULFTPSocketStream()	DOS only, using FTP software.
ULHTTPStream()	Synchronize via HTTP. The HTTP stream uses TCP/IP as its underlying transport. UltraLite applications act as Web browsers and the MobiLink synchronization server acts as a Web server. UltraLite applications send POST requests to send data to the server and GET requests to read data from the server.
ULPalmDBStream()	Synchronize via HotSync or ScoutSync stream (C/C++ only, Palm Computing Platform only)
ULSerialStream()	Synchronize via a serial port (not available on VxWorks or DOS).
ULSocketStream()	Synchronize via TCP/IP.
ULSymbolSocketStream()	DOS only, on the Symbol device.

The parameter has no default value, and must be explicitly set.

 The Java access methods are getStream and setStream. For information on Java synchronization streams, see Initializing the synchronization options.

•	stream_parms    A semi-colon separated list of parameter assignments. Each assignment is of the form keyword=value, where the allowed sets of keywords depends on the communications protocol.

The parameter is optional, is a string, and by default is null.

  For details, see Setting stream_parms values.

•	security    The security stream over which synchronization is to take place. Currently, the following security stream is supported in C/C++ development:

•	ULSecureCerticomTLSStream()  Transport Layer Security provided by Certicom. Use of security requires separate licensing and is subject to export regulations.

  For more information, see Transport-layer security.

The security parameter is a stream, and by default is null, corresponding to no transport-layer security.

You cannot use secure synchronization from UltraLite Java applications.

•	security_parms    The ULSecureCerticomTLSStream() security parameter takes a string composed of the following optional parameters, supplied in an semicolon-separated string.

•	certificate_company    The UltraLite application only accepts server certificates when the organization field on the certificate matches this value. By default, this field is not checked.

•	certificate_unit    The UltraLite application only accepts server certificates when the organization unit field on the certificate matches this value. By default, this field is not checked.

•	certificate_name    The UltraLite application only accepts server certificates when the common name field on the certificate matches this value. By default, this field is not checked.

For example:

ul_synch_info info;

...

info.security = ULSecureCerticomTLSStream();

info.security_parms = ULTEXT( "certificate_company=Sybase" )

                      ULTEXT( ";" )

                      ULTEXT( "certificate_unit=Sales" );

The security_parms parameter is a string, and by default is null.

If you use secure synchronization, you must also use the -r command-line option on the UltraLite generator. For more information, see The UltraLite generator.

You cannot currently use secure synchronization from UltraLite Java applications.

•	upload_only    Indicates that there should be no downloads in the current synchronization, which can save communication time, especially over slow communication links. When set to true, the client waits for the upload acknowledgement from the MobiLink synchronization server, after which it terminates the synchronization session successfully.

The parameter is an optional Boolean value, and by default is false.

In C/C++ the parameter is set to true as follows:

ul_synch_info info;

// ...

info.upload_only = ul_true;

The Java access methods are setUploadOnly and getUploadOnly. The parameter is set to true as follows:

UlSynchOptions info = new UlSynchOptions();

// ...

info.setUploadOnly( true );

•	setUserData    (Java only). When implementing the synchronization observer interface UlSynchObserver, you may wish to make application-specific information to the synchronization observer class. You do this by providing an object in the setUserData method.


Setting stream_parms values
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Adding synchronization to your application

 Setting stream_parms values

Each synchronization stream has a set of appropriate stream_parms values. This section lists the values for each stream.

HotSync and ScoutSync parameters

When you supply ULConduitStream() or ULPalmDBStream() as the stream parameter, the stream_parms values do not control the connection from the device to the HotSync Manager or HotSync Server. Instead, they specify the connection from the MobiLink conduit, running at the HotSync manager or server, to the MobiLink synchronization server.

In the HotSync or ScoutSync case, the stream_parms argument has the following form:

{stream=stream_name;conduit_stream_parameters}

where stream_name indicates the protocol for the conduit to use when communicating from the conduit to the MobiLink synchronization server. It must be one of the following:

•	tcpip

•	serial

•	http

and where conduit_stream_parameters is a set of stream parameters for use by the conduit, and has the same form as the stream_parms argument for the protocol in use.

If you use the ULConduitStream() or ULPalmDBStream() stream, and supply a null value to stream_parms, the conduit searches in the ClientParms registry entry for the stream name and stream parameters. If it finds no valid stream, the default stream and stream parameters is used. This default stream_parms parameter is:

{stream=tcpip;host=localhost}

Serial stream parameters

These parameters are chosen from the following table:

Parameter	Description
baud=integer	The baud rate at which information is to be passed through the serial connection. The default is 19200 baud.
port=integer	The COM port to use for the serial connection. Typically, the port number is 1, which represents COM1: on a standard PC. Devices that do not have multiple serial ports should not have this parameter specified when creating the serial stream. For example, the Palm Computing Platform does not require a port setting.
timeout=t	The length of time (in seconds) that the client waits for a serial connection read request before abandoning the attempt. This can be useful to ensure that connections are abandoned after a certain amount of time has elapsed. The default value for the timeout parameter is 30 seconds. The value 0 can be used to specify no timeout.
TCPIP parameters

These parameters are chosen from the following table:

Parameter	Description
client_port=nnnnn client_port=nnnnn-mmmmm	A range of client ports for communication. If only one value is specified, the end of the range is 100 greater than the initial value, for a total of 101 ports. The option can be useful for clients inside a firewall communicating with a MobiLink server outside the firewall.
host=hostname	The host name or IP number for the machine on which the MobiLink server is running. The default value is localhost, except on Windows CE. For Windows CE, the default setting corresponds to the desktop machine where the CE device's cradle is connected, which is stored as the ipaddr entry in the registry folder Comm\Tcpip\Hosts\ppp_peer. Do not use localhost, which refers to the device itself, on Windows CE. For the Palm Computing Platform, the default value of localhost refers to the device itself. You should supply an explicit host name or IP address to connect to a desktop machine.
port=portnumber	The socket port number on the host machine. The port number must be a decimal number that matches the port the MobiLink server is setup to monitor. The default value for the port parameter is 2439, which is the IANA registered port number for the MobiLink server.
HTTP parameters

These parameters are chosen from the following table:

Parameter	Description
client_port=nnnnn client_port=nnnnn-mmmmm	A range of client ports for communication. If only one value is specified, the end of the range is 100 greater than the initial value, for a total of 101 ports. The option can be useful for clients inside a firewall communicating with a MobiLink server outside the firewall.
version= versionnumber	A string specifying the version of HTTP to use. You have a choice of 1.0 or 1.1. The default value is 1.1.
host=hostname	The host name or IP number for the machine on which the MobiLink synchronization server is running. The default value is localhost. For Windows CE, the default value is the value of ipaddr in the registry folder Comm\Tcpip\Hosts\ppp_peer. This allows a CE device to connect to a MobiLink server executing on the desktop machine where the CE device's cradle is connected. For the Palm Computing Platform, the default value of localhost refers to the device. It is recommended that an explicit host name or IP address be specified.
port=portnumber	The socket port number. The port number must be a decimal number that matches the port the MobiLink server is setup to monitor. The default value for the port parameter is 2439, which is the IANA registered port number for the MobiLink server.
proxy_host= proxy_hostname	The host name of the proxy server.
proxy_port= proxy_portnumber	The port number of the proxy server. The default value is 80.
url_suffix=suffix	The suffix to add to the URL on the first line of each HTTP request. When synchronizing through a proxy server, the suffix may be necessary in order to find the MobiLink server. The default value is MobiLink.


Setting synchronization parameters: C/C++ examples
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Adding synchronization to your application

 Setting synchronization parameters: C/C++ examples

  For Java examples, see Initiating synchronization.

The following code fragment initiates TCP/IP synchronization in an embedded SQL application. The MobiLink user name is Betty Best, with password TwentyFour, the script version is default, and the MobiLink synchronization server is running on the host machine test.internal, on port 2439:

auto ul_synch_info synch_info;

ULInitSynchInfo( &synch_info );

synch_info.user_name = UL_TEXT("Betty Best");

synch_info.password = UL_TEXT("TwentyFour");

synch_info.version = UL_TEXT("default");

synch_info.stream = ULSocketStream();

synch_info.stream_parms =

UL_TEXT("host=test.internal;port=2439");

ULSynchronize( &sqlca, &synch_info );

The following code fragment initiates TCP/IP synchronization in a C++ API application. The MobiLink user name is 50, with an empty password, the script version is custdb, and the MobiLink synchronization server is running on the same machine as the application (localhost), on the default port (2439):

auto ul_synch_info synch_info;

conn.InitSynchInfo( &synch_info );

synch_info.user_name = UL_TEXT( "50" );

synch_info.version = UL_TEXT( "custdb" );

synch_info.stream = ULSocketStream();

synch_info.stream_parms =

UL_TEXT("host=localhost");

conn.Synchronize( &synch_info );

The following code fragment for an embedded SQL application on the Palm Computing Platform is called when the user exits the application. It allows HotSync synchronization to take place, with a MobiLink user name of 50, an empty password, a script version of custdb. The HotSync conduit communicates over TCP/IP with a MobiLink synchronization server running on the same machine as the conduit (localhost), on the default port (2439):

auto ul_synch_info synch_info;

ULInitSynchInfo( &synch_info );

synch_info.name = UL_TEXT("Betty Best");

synch_info.version = UL_TEXT("default");

synch_info.stream = ULConduitStream();

synch_info.stream_parms =

UL_TEXT("stream=tcpip;host=localhost");

ULPalmExit( &sqlca, &synch_info );


Invoking synchronization
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Adding synchronization to your application

 Invoking synchronization

The details of how to invoke synchronization depends on your target platform and programming language, and also on the particular synchronization stream.

♦ To invoke synchronization (TCP/IP, serial, or HTTP streams):

•	When using embedded SQL, call ULInitSynchInfo to initialize the synchronization parameters, and call ULSynchronize to synchronize.

or

When using the C++ API, use the Connection.InitSynchInfo() method to initialize the synchronization parameters, and Connection.Synchronize() method to synchronize. See Synchronize method.

or

When using Java, construct a new ULSynchInfo object to initialize the synchronization parameters, and use the JdbcConnection.synchronize() method to synchronize. See Adding synchronization to your application.

♦ To invoke synchronization (HotSync or ScoutSync streams):

•	In embedded SQL, use ULInitSynchInfo to initialize the synchronization parameters, and call ULPalmExit and ULPalmLaunch functions to manage synchronization.

or
In the C++ API, use the ULConnection.InitSynchInfo to initialize the synchronization parameters, and call ULData.PalmExit and ULData.PalmLaunch functions to manage synchronization.

  For more information on the embedded SQL functions, see ULPalmExit library function, and ULPalmLaunch library function. For more information on the C++ API methods, see PalmExit method, and PalmLaunch method.

The synchronization call requires a structure that holds a set of parameters describing the specifics of the synchronization. The particular parameters used depend on the stream.


Commit all changes before synchronizing
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Adding synchronization to your application

 Commit all changes before synchronizing

An UltraLite database cannot have uncommitted changes when it is synchronized. If you attempt to synchronize an UltraLite database when any connection has an uncommitted transaction, the synchronization fails, an exception is thrown and the SQLE_UNCOMMITTED_TRANSACTIONS error is set. This error code also appears in the MobiLink server log.


Adding initial data to your application
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Adding synchronization to your application

 Adding initial data to your application

Many UltraLite application need data in order to start working. You can download data into your application by synchronizing. You may want to add logic to your application to ensure that, the first time it is run, it downloads all necessary data before any other actions are carried out.

Development tip
It is easier to locate errors if you develop an application in stages. When developing a prototype, temporarily code INSERT statements in your application to provide data for testing and demonstration purposes. Once your prototype is working correctly, enable synchronization and discard the temporary INSERT statements.

  For more synchronization development tips, see Development tips.


Monitoring and canceling synchronization
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Adding synchronization to your application

 Monitoring and canceling synchronization

This section describes how to monitor and cancel synchronization from C/C++ applications. For information on carrying out these tasks in Java, see Monitoring and canceling synchronization.

To monitor and cancel synchronization, you specify a synchronization observer callback function in the ul_synch_info structure. This structure is passed to the synchronization function (embedded SQL) or method (C++ API). The observer function is then called at various points during the synchronization, and supplied with information about the synchronization state.

Monitoring synchronization

To monitor synchronization from an UltraLite C/C++ application, you supply the name of a callback function in the observer member of your synchronization structure.

The overall process for monitoring synchronization is as follows:

•	Specify the name of your callback function in the synchronization structure.

•	Call the synchronization function or method to start synchronization.

•	UltraLite calls your callback function called whenever the synchronization state changes. The following section describes the synchronization state.

Example

The following code shows how this sequence of tasks can be implemented in an embedded SQL application:

ULInitSynchInfo( &info );

info.user_name = m_EmpIDStr;

...

//The info parameter of ULSynchronization() contains

// a pointer to the observer function

info.observer = ObserverFunc;

ULSynchronize( &sqlca, &info );


Writing a synchronization callback function
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

        Adding synchronization to your application

 Writing a synchronization callback function

The callback function that you use to monitor synchronization takes a ul_synch_status structure as parameter. The ul_synch_status structure has the following members:

•	state    One of the following states:

•	UL_SYNCH_STATE_STARTING    No synchronization actions have yet been taken.

•	UL_SYNCH_STATE_CONNECTING    The synchronization stream has been built, but not yet opened.

•	UL_SYNCH_STATE_SENDING_HEADER    The synchronization stream has been opened, and the header is about to be sent.

•	UL_SYNCH_STATE_SENDING_TABLE    A table is being sent.

•	UL_SYNCH_STATE_RECEIVING_UPLOAD_ACK    An acknowledgement that the upload is complete is being received.

•	UL_SYNCH_STATE_RECEIVING_TABLE    A table is being received.

•	UL_SYNCH_STATE_SENDING_DOWNLOAD_ACK    An acknowledgement that download is complete is being sent.

•	UL_SYNCH_STATE_DISCONNECTING    The synchronization stream is about to be closed.

•	UL_SYNCH_STATE_DONE    Synchronization has completed successfully.

•	UL_SYNCH_STATE_ERROR    Synchronization has completed, but with an error.

  For a description of the synchronization process, see The synchronization process.

•	tableCount    The total number of tables

•	tableIndex    The current table which is being uploaded or downloaded

•	info    A pointer to the ul_synch_info structure.

•	stop    Set this member to true to interrupt the synchronization

Example

The following code illustrates how a very simple observer function could be implemented:

extern void __stdcall ObserverFunc( p_ul_synch_status status )

{

    printf( "UL_SYNCH_STATE is %d: ", status->state );

    switch( status->state ) {

        case UL_SYNCH_STATE_STARTING:

        printf( "Starting\n");

        break;

    case UL_SYNCH_STATE_CONNECTING:

        printf( "Connecting\n"  );

        break;

    case UL_SYNCH_STATE_SENDING_HEADER:

        printf( "Sending Header\n" );

        break;

    case UL_SYNCH_STATE_SENDING_TABLE:

        printf( "Sending Table %d of %d\n", status->tableIndex + 1, status->tableCount );

        break;

...

This function produces the following output when synchronizing two tables:

UL_SYNCH_STATE is 0: Starting

UL_SYNCH_STATE is 1: Connecting

UL_SYNCH_STATE is 2: Sending Header

UL_SYNCH_STATE is 3: Sending Table 1 of 2

UL_SYNCH_STATE is 3: Sending Table 2 of 2

UL_SYNCH_STATE is 4: Receiving Upload Ack

UL_SYNCH_STATE is 5: Receiving Table 1 of 2

UL_SYNCH_STATE is 5: Receiving Table 2 of 2

UL_SYNCH_STATE is 6: Sending Download Ack

UL_SYNCH_STATE is 7: Disconnecting

UL_SYNCH_STATE is 8: Done

CustDB example

An example of an observer function is included in the CustDB sample application. The implementation in CustDB provides a dialog that displays synchronization progress and allows the user to cancel synchronization. The user-interface component makes the observer function platform specific.

The CustDB sample code is in the UltraLite\samples\CustDB subdirectory of your SQL Anywhere directory. The observer function is contained in the platform-specific subdirectories of the CustDB directory.


Configuring development tools for UltraLite development
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

 Configuring development tools for UltraLite development

Most development tools use a dependency model, sometimes expressed as a makefile, in which the timestamp on each source file is compared with that on the target file (object file, in most cases) to decide whether the target file needs to be regenerated.

With UltraLite development, a change to any SQL statement in a development project means that the generated code needs to be regenerated. Changes are not reflected in the timestamp on any individual source file because the SQL statements are stored in the reference database,.

This section describes in general terms a strategy for incorporating UltraLite application development into a dependency-based build environment. The UltraLite plugin for Metrowerks CodeWarrior automatically provides Palm Computing platform developers with the features described here. For other development tools, you must make the appropriate changes yourself.

  For information on the UltraLite plugin for CodeWarrior, see Developing UltraLite applications with Metrowerks CodeWarrior.

  For specific instructions on adding embedded SQL projects to a dependency-based development environment, see Configuring development tools for embedded SQL development.

♦ To add UltraLite code generation into a dependency-based development model:

1	Add a dummy file to your development project.

The development project is defined in your development tool. It is separate from the UltraLite project name used by the UltraLite generator.

Add a file named, for example, uldatabase.ulg, in the same directory as your generated files.

2	Set the build rules for this file to be the UltraLite generator command line.

For example, in Visual C++, use a command of the following form (which should be all on one line):

"%asany7%\win32\ulgen.exe" -q -c "connection-string" $(InputName) $(InputName).c

where asany7 is an environment variable that points to your SQL Anywhere installation directory, connection-string is a connection to your reference database, and InputName is the UltraLite project name, and should match the root of the text file name. The output is $(InputName).c.

3	Compile the dummy file to generate the UltraLite database code.

4	Add the generated UltraLite database file to your development project.

5	Add the UltraLite import libraries for your target platform to your include path.

  For information on the libraries needed for each target platform, see Platform-Specific Development.

6	When you alter any SQL statements in the reference database, touch the dummy file, to update its timestamp and force the UltraLite generator to be run.


Deploying your application
  UltraLite  Developer's Guide

    PART 1. Introduction to UltraLite

      CHAPTER 4.  Developing UltraLite Applications

 Deploying your application

Once built, your application is contained in a single executable file (C/C++) or set of classes (Java).

Your UltraLite application automatically initializes its own database the first time it is invoked. At first, your database contains no data. You can add data explicitly using INSERT statements in your application, or you can import data from a consolidated database through synchronization. Explicit INSERT statements are especially useful when developing prototypes. You do not need to deploy a separate UltraLite database with your application.

If you linked a C/C++ UltraLite application using the UltraLite library, the custom database engine is an integral component of this executable. To deploy your application, copy the executable file to your target device.

Using the UltraLite runtime DLL

Some platforms, such as Windows CE, support dynamic link libraries. If your target is one of these platforms, you have the option to use the UltraLite runtime DLL.

♦ To build and deploy an application using the UltraLite runtime DLL

1	Preprocess your code, then compile the output with UL_USE_DLL.

2	Link your application using the UltraLite imports library.

3	Copy both your application executable and the UltraLite runtime DLL to your target device.

  For more information on specific platforms, see Platform-Specific Development.


PART 2. Developing UltraLite Applications in C/C++
  UltraLite  Developer's Guide

 PART 2. Developing UltraLite Applications in C/C++

This part describes the development of applications written in C or C++.  	It explains how to write and build applications using embedded SQL and using the UltraLite Object API, and also provides tutorials to guide you through the development process.

 CHAPTER 5.  A C++ API Tutorial

 CHAPTER 6.  Developing C++ API Applications

 CHAPTER 7.  C++ API Reference

 CHAPTER 8.  An Embedded SQL Tutorial

 CHAPTER 9.  Developing Embedded SQL Applications

 CHAPTER 10.  The Embedded SQL Interface

 CHAPTER 11.  Platform-Specific Development


CHAPTER 5.  A C++ API Tutorial
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

 CHAPTER 5.  A C++ API Tutorial

About this chapter

This chapter provides a tutorial that guides you through the process of developing a UltraLite application using the C++ API. It describes how to build a very simple application, and how to add synchronization to your application.

 Introduction to the UltraLite C++ API

 Lesson 1: Getting started

 Lesson 2: Create an UltraLite database template

 Lesson 3: Run the UltraLite generator

 Lesson 4: Write the application source code

 Lesson 5: Build and run your application

 Lesson 6: Add synchronization to your application

 Restore the sample database


Introduction to the UltraLite C++ API
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 5.  A C++ API Tutorial

 Introduction to the UltraLite C++ API

You can use the UltraLite C++ API to develop UltraLite C/C++ programs using an API instead of embedded SQL. It provides an equivalent functionality to embedded SQL, but in the form of a C++ interface.

Base classes

The UltraLite C++ API starts with a set of base classes that represent the basic components of an UltraLite application. These are:

•	ULData    Represents an UltraLite database.

•	ULConnection    Represents a connection to an UltraLite database, and also handles synchronization.

•	ULCursor    Provides methods used by generated table or result set objects, for accessing and modifying the data.

•	ULTable    Provides methods used by generated table objects, but not by generated result set objects. This class inherits from ULCursor.

•	ULResultSet    Provides methods used by generated result set objects, but not by generated table objects. This class inherits from ULCursor, and is not documented separately as it contains only methods that are in ULCursor.

•	ULStatement    Represents a statement that does not return a result set, such as an INSERT or UPDATE statement. All methods of this class are generated.

Generated classes

For each application, the UltraLite generator writes out a set of classes that describe your particular UltraLite database.

•	Generated result set classes    Individual SQL statements that return result sets are represented by a class, with methods for traversing the result set, and for modifying the underlying data.

•	Generated table classes    Each table in the application is represented by a class, and methods on that table allow the rows of the table to be modified.

For example, for a table named Employee, the UltraLite generator generates a class also named Employee.

•	Generated statement classes    Individual SQL statements that do not return result sets are represented by a simple class with an Execute method.

You use these classes in your application to access and modify data, and to synchronize with consolidated databases.

 Tutorial overview


Tutorial overview
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 5.  A C++ API Tutorial

        Introduction to the UltraLite C++ API

 Tutorial overview

This tutorial describes how to construct a very simple application using the UltraLite C++ API. The application is a Windows console application, developed using Microsoft Visual C++, which queries data in the ULProduct table of the UltraLite 7.0 Sample database.

The tutorial takes you through configuration of Visual C++, in such a way that users of other development platforms should be able to identify the steps required. These steps are supplied so that you can start development of your own applications.

In the tutorial, you write and build an application that carries out the following tasks.

1	Connects to an UltraLite database, consisting of a single table. The table is a subset of the ULProduct table of the UltraLite Sample database.

2	Inserts rows into the table. Initial data is usually added to an UltraLite application by synchronizing with a consolidated database. Synchronization is added later in the chapter.

3	Writes the first row of the table to standard output.

In order to build the application, you must carry out the following steps:

1	Design the UltraLite database in an Adaptive Server Anywhere reference database.

Here we use a single table from the UltraLite sample database (CustDB).

2	Run the UltraLite generator to generate the API for this UltraLite database.

The generator writes out a C++ file and a header file.

3	Write source code that implements the logic of the application.

Here, the source code is just main.cpp.

4	Compile, link, and run the application.

You then add synchronization to your application.


Lesson 1: Getting started
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 5.  A C++ API Tutorial

 Lesson 1: Getting started

In this tutorial, you will be creating a set of files, including source files and executable files. You should make a directory to hold these files. In addition, you should make a copy of the UltraLite sample database so that you can work on it, and be sure you still have the original sample database for other projects.

♦ To prepare a tutorial directory:

•	Create a directory to hold the files you will create. In the remainder of the tutorial, we assume that this directory is c:\APITutorial.

♦ To copy the sample database:

•	Make a backup copy of the UltraLite 7.0 Sample database into the tutorial directory. The UltraLite 7.0 Sample database is the file custdb.db, in the UltraLite\Samples\CustDB subdirectory of your SQL Anywhere installation directory. In this tutorial, we use the original UltraLite 7.0 Sample database, and at the end of the tutorial you can copy the untouched version from the APITutorial directory back into place.


Lesson 2: Create an UltraLite database template
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 5.  A C++ API Tutorial

 Lesson 2: Create an UltraLite database template

In this tutorial, you use the original copy of the UltraLite 7.0 Sample database (CustDB) as a reference database. The copy you placed in the APITutorial directory serves as a backup copy.

An UltraLite database template is a set of tables, and columns within tables, that are to be included in your UltraLite database. You create an UltraLite database template by creating a SQL Remote publication in the reference database. The SQL Remote publication is simply a convenient device for assembling tables and column-based subsets of tables: there is no direct connection to SQL Remote.

You can also define your UltraLite database by adding SQL statements to the reference database. SQL statements allow you to include joins and more advanced features in your UltraLite application. Here, we build an UltraLite database template by defining tables, as it is more simple.

♦ To create the UltraLite database template:

1	Start Sybase Central.

2	Connect to the UltraLite 7.0 Sample database.

•	Choose Tools [image] Connect.

•	If a list of plugins is displayed, choose Adaptive Server Anywhere.

•	In the Connection dialog, choose the UltraLite 7.0 Sample ODBC data source.

•	Click OK to connect.

3	Create a SQL Remote publication that reflects the data you wish to include in your UltraLite database.

•	In Sybase Central, open the custdb database.

•	Open the SQL Remote folder. Open the Publications folder, and click Add Publication. The Publication Wizard is displayed.

•	Name the publication ProductPub, and click Next.

•	Click Add Article, and choose the ULProduct table from the list.

•	Include all columns in the publication, and click OK.

•	Click Next and Finish to create the publication.

You have now finished designing the UltraLite database template. Leave Sybase Central and the database server running for the next lesson.


Lesson 3: Run the UltraLite generator
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 5.  A C++ API Tutorial

 Lesson 3: Run the UltraLite generator

The UltraLite generator writes a C++ file and a header file that define an interface to the UltraLite database, as specified in the UltraLite database template.

♦ To generate the UltraLite interface code:

1	From a command prompt, change directory to your APITutorial directory.

2	Run the UltraLite generator with the following arguments (all on one line):

ulgen -c "dsn=UltraLite 7.0 Sample" -t c++

-u ProductPub -f ProductPubAPI

The generator writes out the following files:

•	ProductPubAPI.hpp    This file contains prototypes for the generated API. You should inspect this file to determine the API you can use in your application.

•	ProductPubAPI.cpp    This file contains the interface source. You do not need to look at this file.

•	ProductPubAPI.h    This file contains internal definitions required by UltraLite. You do not need to look at this file.


Lesson 4: Write the application source code
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 5.  A C++ API Tutorial

 Lesson 4: Write the application source code

Copy and paste the following source code into a file named main.cpp in your tutorial directory.

The code does not contain error checking or other features that you would require in a complete application. It is provided as a simplified application, for illustrative purposes only.

// (1) include headers

#include <stdio.h>

#include "ProductPubAPI.hpp"

void main() {

// (2) declare variables

long price;

ULData db;

ULConnection conn;

ULProduct productTable;

// (3) connect to the UltraLite database

db.Open() ;

    	conn.Open( &db, "dba", "sql" );

productTable.Open( &conn );

// (4) insert sample data

productTable.SetProd_id( 1 );

productTable.SetPrice( 400 );

productTable.SetProd_name( "4x8 Drywall x100" );

productTable.Insert();

productTable.SetProd_id( 2 );

productTable.SetPrice( 3000 );

productTable.SetProd_name( "8' 2x4 Studs x1000" );

productTable.Insert();

// (5) Write out the price of the items

productTable.BeforeFirst();

while( productTable.Next() ) {

productTable.GetPrice( price );

printf("Price: %d\n", price );

}

// (6) close the objects to finish

productTable.Close();

conn.Close();

db.Close();

}

Explanation

The numbered comments in the code indicate the main tasks this routine carries out:

1	Include headers.

In addition to stdio.h, you need to include the generated header file ProductPubAPI.hpp to include the generated classes describing the Product table. This file in turn includes the UltraLite header file ulapi.h.

2	Declare variables.

The UltraLite database is declared as an instance of class ULData, and the connection to the database is an instance of class ULConnection. These classes are included from ulapi.h.

The table is declared as  an instance of class ULProduct, a generated name derived from the name of the table in the reference database.

3	Connect to the database.

Opening each of the declared objects establishes access to the data. Opening the database requires no arguments; opening a connection requires a user ID and password, and also the name of the database. Opening the table requires the name of the connection.

4	Insert sample data.

In a production application, data is entered into the database by synchronizing. It is a useful practice to insert some sample data during the initial stages of development, and include synchronization at a later stage.

The method names in the ULProduct class are unique names that reflect the columns of the table in the reference database.

  Synchronization is added to this routine in Lesson 6: Add synchronization to your application.

5	Write out the price of each item.

The price is retrieved and written out for each row in the table.

6	Close the objects.

Closing the objects used in the program frees the memory associated with them.


Lesson 5: Build and run your application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 5.  A C++ API Tutorial

 Lesson 5: Build and run your application

You can compile and link your application in the development tool of your choice. In this section, we describe how to compile and link using Visual C++; if you are using one of the other supported development tools, modify the instructions to fit your tool.

1	Start Microsoft Visual C++ from your desktop in the standard fashion.

2	Configure Visual C++ to search the appropriate directories for UltraLite header files and library files.

Select Tools [image] Options and click on the Directories tab. In the Show Directories For drop down list, choose Include Files. Include the following directory, so that the header files can be accessed.

C:\Program Files\Sybase\SQL Anywhere 7\h

On the same tab, select Library Files under the Show Directories For drop down menu. Include the following directory so that the UltraLite library files can be accessed.

C:\Program Files\Sybase\SQL Anywhere 7\ultralite\win32\386\lib

Click OK to submit the changes.

3	Create a project named APITutorial (it should be the same name as the directory you have used to hold your files).

•	Select File [image] New. The New dialog is displayed.

•	On the Projects tab choose Win32 Console Application.

•	Specify a project name of APITutorial.

•	Specify the APITutorial directory as location.

•	Select New Workspace and click OK.

•	Choose to create An Empty Project and click Finish.

•	On the Workspace window, click the FileView tab. The workspace tutorial consists of just the APITutorial project. Double-click APITutorial files to display the three folders: Source Files, Header Files, Resource Files.

4	Configure the project settings.

•	Right click on APITutorial files and select Settings. The Project Settings dialog is displayed.

•	From the Settings For drop down menu, choose All Configurations.

•	Click the Link tab. Add the following runtime library to the Object/Library Modules box.

ulimp.lib

•	Click on the C/C++ tab. From the Category drop-down menu, choose General. Add the following to the Preprocessor definitions list:

__NT__,UL_USE_DLL

Here, __NT__ has two underscores either side of NT.

•	Click OK to finish.

5	Add main.cpp and ProductPubAPI.cpp to the project.

•	Right click on the Source Files folder and select Add Files to Folder. Locate your main.cpp file and click OK. Open the Source Files folder to verify that it contains main.cpp.

•	Repeat to add the generated ProductPubAPI.cpp file to the project.

6	Add the file containing the base classes for the UltraLite API to the project.

•	Right click on the Source Files folder and choose Add Files to Folder. Browse to ulapi.cpp, which is in the src subdirectory of your SQL Anywhere directory, and click OK.

7	Compile and link the application.

•	Select Build [image] Build APITutorial.exe to compile and link the executable. Depending on your settings, the APITutorial.exe executable may be created in a Debug directory within your APITutorial directory.

8	Ensure that the application can locate the UltraLite runtime library.

•	The UltraLite runtime library is ulrt7.dll. In Visual C++, choose Tools [image] Options, click the Directories tab. From the Show Directories For list choose Executable files. Add the win32 subdirectory of your SQL Anywhere directory to the list. Click OK to complete.

9	Run the application.

•	Select Build [image] Execute APITutorial.exe.

A command prompt window appears and displays the prices of the products in the product table.

You have now built and run a simple UltraLite application. The next step is to add synchronization to your application.


Lesson 6: Add synchronization to your application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 5.  A C++ API Tutorial

 Lesson 6: Add synchronization to your application

UltraLite applications exchange data with a consolidated database. In this lesson, you add synchronization to the simple application you created in the previous section. In addition, you change the output to verify that synchronization has taken place.

Adding synchronization actually simplifies the code. Your initial version of main.cpp has the following lines, that inserts some data into your UltraLite database.

productTable.SetProd_id( 1 );

productTable.SetPrice( 400 );

productTable.SetProd_name( "4x8 Drywall x100" );

productTable.Insert();

productTable.SetProd_id( 2 );

productTable.SetPrice( 3000 );

productTable.SetProd_name( "8' 2x4 Studs x1000" );

productTable.Insert();

This code is included to provide an initial set of data for your application. In a production application, you would usually not insert an initial copy of your data from source code, but would carry out a synchronization.

♦ To add synchronization to your application:

1	Add a synchronization information structure to your code.

•	Add the following line immediately after the line that says // (2) declare variables.

auto ul_synch_info synch_info;

This structure holds the parameters that control the synchronization.

2	Replace the explicit inserts with a synchronization call.

•	Delete the productTable methods listed above.

•	Add the following lines in their place:

conn.InitSynchInfo( &synch_info );

synch_info.user_name = UL_TEXT( "50" );

synch_info.version = UL_TEXT( "custdb" );

synch_info.stream = ULSocketStream();

synch_info.stream_parms =

UL_TEXT("host=localhost");

conn.Synchronize( &synch_info );

The value of 50 is the MobiLink user name.

The string custdb instructs MobiLink to use the default script version for synchronization.

ULSocketStream() instructs the application to synchronize over TCP/IP, and host=localhost specifies the host name of the MobiLink server, which in this case is the current machine.

3	Compile and link your application.

•	Select Build [image] Build APITutorial.exe to compile and link the executable. Depending on your settings, the APITutorial.exe executable may be created in a Debug directory within your APITutorial directory.

4	Start the MobiLink server running against the sample database.

From a command prompt in your APITutorial directory, enter the following command:

start dbmlsrv7 -c "dsn=UltraLite 7.0 Sample"

5	Run your application.

From the Build menu, choose Execute APITutorial.exe.

The application connects, synchronizes to receive data, and writes out information to the command prompt window. The output is as follows:

The ULData object is open

Price: 400

Price: 3000

Price: 40

Price: 75

Price: 100

Price: 400

Price: 3000

Price: 75

Price: 40

Price: 100

In this lesson, you have added synchronization to a simple UltraLite application.


Restore the sample database
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 5.  A C++ API Tutorial

 Restore the sample database

Now that you have completed the tutorial, you should restore the sample database so that it can be used again. You created a copy of the UltraLite 7.0 Sample database in Lesson 1: Getting started. You can now replace the version of custdb.db that you just changed with the copy.

♦ To restore the sample database:

1	Copy the custdb.db file from your tutorial directory to the UltraLite\Samples\CustDB subdirectory of your SQL Anywhere directory.

2	In the same directory, delete the transaction log file custdb.log.

Your sample database is now restored to its original state.


CHAPTER 6.  Developing C++ API Applications
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

 CHAPTER 6.  Developing C++ API Applications

About this chapter

This chapter describes how to develop applications using the UltraLite C++ API. This interface represents predefined queries or tables in your UltraLite database as objects, and provides methods that enable you to manipulate them from your application without using SQL.

 Introduction

 Defining data access features for your application

 Working with the C++ API classes

 Building your UltraLite C++ application


Introduction
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

 Introduction

This chapter provides notes for developers who are writing and building UltraLite applications using the C++ API.

What's in this chapter?

The chapter includes the following information:

•	Information about how to define the data access features to be used in your application.

  See Defining data access features for your application.

•	Information on generating C++ API classes from your reference database.

  See Generating UltraLite C++ classes.

•	Notes on the C++ API classes that are generated.

  See Working with the C++ API classes.

•	Notes on compiling and linking UltraLite C++ API applications.

  See Compiling and linking your application.

Before you begin

The development process for the C++ API is similar to that for other UltraLite development models. This chapter assumes a familiarity with that process.

  For more information, see Developing UltraLite Applications.


Defining data access features for your application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

 Defining data access features for your application

The SQL statements to be included in the UltraLite application, and the structure of the UltraLite database itself, are defined by adding the SQL statements to the reference database for your application.

 Defining projects

 Adding statements to a project

 Defining UltraLite tables

 Tables or queries?


Defining projects
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

        Defining data access features for your application

 Defining projects

When you run the UltraLite generator, it writes out class definitions for all the SQL statements in a given project. A project is a name defined in the reference database, which groups the SQL statements for an application. You can store SQL statements for multiple applications in a single reference database by defining multiple projects.

  For information on creating projects, see Creating an UltraLite project.

You can use the ul_delete_project stored procedure to remove a project definition.


Adding statements to a project
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

        Defining data access features for your application

 Adding statements to a project

  For information on adding SQL statements to an UltraLite project, see Adding SQL statements to an UltraLite project.

  For information on using placeholders, and other aspects of writing SQL statements for UltraLite, see Writing UltraLite SQL statements.


Defining UltraLite tables
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

        Defining data access features for your application

 Defining UltraLite tables

If you do not intend to carry out joins, and if you have strong constraints on your application executable size, you can define tables instead of queries for your UltraLite application.

You define a subset of a database for use in a C++ API application by creating a SQL Remote publication in the reference database. A publication defines the set of tables, and columns in those tables, that you want to include in your UltraLite application. The use of a SQL Remote publication is purely a convenience for UltraLite, and does not imply any connection with SQL Remote software.

SQL Remote publications allow you to qualify which rows any SQL Remote user receives using subqueries and parameters. You cannot use these devices when creating publications for use with UltraLite: only the set of tables and columns within those tables is used for defining the UltraLite classes.


Tables or queries?
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

        Defining data access features for your application

 Tables or queries?

Table definitions and query definitions provide alternative ways of defining the data that is to be included in your UltraLite database, and the range of operations you can carry out on that data.

Using SQL statements and projects provides a more general approach to defining applications, and are most likely to be used in larger enterprise applications. Table definitions may be useful as a convenient device in the following cases:

•	Your application needs to access data only one table at a time. You cannot define joins using table definitions.

•	You are severely constrained for memory use. The code generated for table definitions is smaller than that for queries, because of their simpler structure.


Working with the C++ API classes
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

 Working with the C++ API classes

This section contains notes about the classes that make up the C++ API.

 Working with the ULData and ULConnection objects

 Using table and query classes


Working with the ULData and ULConnection objects
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

        Working with the C++ API classes

 Working with the ULData and ULConnection objects

The ULData object makes the data in the database object available to your application. You need to call ULData::Open() before you can connect to the UltraLite database or carry out any operations on the data.

The ULData::Open() method can be called with parameters that define the storage and access parameters for the database (file name, cache size, reserved size).

Once the ULData object is opened, you can open a connection on the database. You do that using the ULConnection::Open() method, supplying a reference to the ULData object and a set of connection parameters to establish the connection. You can use multiple connections on a single database. Once the connection is established, you can open the generated ULStatement, ULResultSet or ULTable objects that define the tables or statements used in your application, and use these objects to manipulate the data.

The ULConnection object defines the general characteristics of how you interact with the data.

Synchronization is carried out using the ULConnection object. The Synchronize method carries out synchronization of the data with a MobiLink server.

Palm Computing Platform developers

If you are developing an application for the Palm Computing Platform, there are some extra considerations for how to use these objects.

  For more information, see Developing for the Palm Computing Platform.


Using table and query classes
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

        Working with the C++ API classes

 Using table and query classes

Each table or query is represented by a class. The API for accessing and modifying the rows in the table or query is based on a SQL cursor: a pointer to a position in the table or query.

The cursor can have the following positions:

•	Before the first row    This position has value 0. This is the position of the cursor when the table or query is opened.

•	On a row    If a table or query has n rows, positions 1 to n for the cursor correspond to the rows.

•	After the last row    This position has value (n+ 1)

You can move through the rows of the object using methods of the object, including Next() and Previous().

Palm Computing Platform developers

If you are developing an application for the Palm Computing Platform, there are some extra considerations for how to use these objects.

  For more information, see Launching and closing UltraLite applications.

 Row ordering


Row ordering
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

        Working with the C++ API classes

          Using table and query classes

 Row ordering

The order of the rows in the object is determined when it is opened. By default, tables are ordered by primary key. The UltraLite generator adds an enumeration for the object definition, with a member for each index on the table in the reference database (the primary key is named Primary), and by specifying a member of this enumeration, you can control the ordering of the rows in the object.

If you update a row so that it no longer belongs in the current position, or if you insert a row that does not belong at the current position, the row is added at the proper position, and the current row of the cursor moves to that row.

For example, consider a single-column object with the values A, B, C, and E.

•	If a cursor is sitting on row B (position 2) and modifies the value to D, then the row is moved to sit between C and E (becoming position 3) and the current row of the cursor changes to position 3.

•	If a cursor is sitting on row B (position 2) and inserts a row with a value of D, the row is inserted between C and E (position 4) and the current row of the cursor changes to position 4.


Building your UltraLite C++ application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

 Building your UltraLite C++ application

This section covers the following subjects:

•	Generating UltraLite C++ classes.

•	Compiling and linking your application.

 Generating UltraLite C++ classes

 Compiling and linking your application


Generating UltraLite C++ classes
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

        Building your UltraLite C++ application

 Generating UltraLite C++ classes

The generator generates table classes from publications in the database, and query classes from any SQL statements added with the ul_add_statement stored procedure, writing the output to the following files:

•	filename.hpp  This file contains the prototypes for the generated interface. You should inspect this file to determine the API you can use in your application.

•	filename.cpp  This file contains the interface source. You do not need to look at this file.

•	filename.h  This file contains internal definitions required by UltraLite. You do not need to look at this file.

•	Here, filename is the name supplied on the ulgen command line.

Whether you use queries in a project, SQL Remote publications, or a mix to define the classes in your application, you must generate all the code in a single run of the UltraLite generator.

♦ To generate UltraLite code for a SQL Remote publication:

•	Run the UltraLite generator specifying the publication name with the -u command-line switch. For example:

ulgen -c "uid=dba;pwd=sql" -t c++ -u pubName -f filename

♦ To generate UltraLite code for a UltraLite project:

•	Run the UltraLite generator, specifying the project name with the -j command-line switch. For example:

ulgen -c "uid=dba;pwd=sql" -t c++ -j projectname -f filename

♦ To generate UltraLite code for both a project and a publication:

•	Run the UltraLite generator, specifying the project name and the publication name. For example:

ulgen -c "uid=dba;pwd=sql" -t c++ -j projectname -u pubname -f filename

  For more information on the UltraLite generator, see The UltraLite generator.


Compiling and linking your application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 6.  Developing C++ API Applications

        Building your UltraLite C++ application

 Compiling and linking your application

When you compile your UltraLite application, you must ensure that the compiler can locate all the required files.

•	Generated source files    You must included the generated files describing the API in your project. This includes the generated .cpp file, .h file, and .hpp file.

•	UltraLite header files    You must configure your compiler so that it can locate the UltraLite header files.

These header files are installed into the h directory under your Adaptive Server Anywhere installation directory.

•	UltraLite c file    You must configure your linker so that it can locate the UltraLite API file ulapi.cpp.

This file is installed into the src subdirectory of your Adaptive Server Anywhere installation directory.

•	Library or import library    You must configure your compiler so that it can locate the UltraLite runtime library for your target platform or, in the case that you are using the UltraLite runtime DLL, the UltraLite imports library.

These files are installed under the UltraLite subdirectory of your Adaptive Server Anywhere installation directory. Each target platform has a separated directory, and if there are different processors for a platform, each has its own subdirectory.

  For specific instructions for each platform, see Platform-Specific Development.


CHAPTER 7.  C++ API Reference
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

 CHAPTER 7.  C++ API Reference

About this chapter

This chapter describes the UltraLite C++ API.

 C++ API class hierarchy

 C++ API language elements

 ULConnection class

 ULData class

 ULCursor class

 ULResultSet class

 ULTable class

 Generated result set class

 Generated statement class

 Generated table class


C++ API class hierarchy
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 C++ API class hierarchy

The classes in the C++ API are displayed in the following diagram:

The classes are described in the following header files:

•	generated-name.hpp    The interface generated for a particular set of statements or tables is defined in the generated .hpp file.

•	ulapi.h    The base classes are defined in ulapi.h, in the h subdirectory of your SQL Anywhere installation directory.

•	ulglobal.h    You may want to look at ulglobal.h, in the h subdirectory of your SQL Anywhere installation directory, for some of the data types and other definitions used in ulapi.h.


C++ API language elements
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 C++ API language elements

The UltraLite API methods and variables are described in terms of a set of UltraLite data types. These data types are described in this section.

 UltraLite data types


UltraLite data types
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        C++ API language elements

 UltraLite data types

•	an_sql_code    A data type for holding SQL error codes.

•	ul_char     A data type representing a character. If the operating system uses Unicode, ul_char uses two bytes per character. For single-byte character sets, ul_char uses a single byte per character.

•	ul_column_num    A data type for holding a number indicating a column of a table or query. The first column in the table or query is number one.

•	ul_fetch_offset    A data type for holding a relative number in a ULCursor object.

•	ul_length    A data type for holding the length of a data type.

•	UL_NULL    A constant representing a SQL NULL.


ULConnection class
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 ULConnection class

Object

Represents a database connection.

Description

A ULConnection object represents an UltraLite database connection. It provides methods to open and close a connection, to check whether a connection is open, to synchronize a database on the current connection, and more.

For embedded SQL users, opening a ULConnection object is equivalent to the EXEC SQL CONNECT statement.

 Close method

 Commit method

 GetCA method

 GetSQLCode method

 InitSynchInfo method

 IsOpen method

 LastCodeOK method

 LastFetchOK method

 Open method

 Reopen method

 Rollback method

 Synchronize method


Close method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 Close method

Syntax

bool  Close ( )

Description

Disconnects your application from the database, and frees resources associated with the ULConnection object. Once you have closed the ULConnection object, your application is no longer connected to the UltraLite database.

Closing a connection rolls back any outstanding changes.

You should not close a connection object in a Palm Computing Platform application. Instead, use the Reopen method when the application is reactivated.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example closes a ULConnection object:

conn.Close();

See also

Open method


Commit method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 Commit method

Syntax

bool  Commit( )

Description

Commits outstanding changes to the database.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following code inserts a value to the database, and commits the change.

productTable.Open( &conn );

productTable.SetProd_id( 2 );

productTable.SetPrice( 3000 );

productTable.SetProd_name( "8' 2x4 Studs x1000" );

productTable.Insert();

conn.Commit();

See also

Rollback method


GetCA method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 GetCA method

Syntax

SQLCA *GetCA( )

Description

Retrieves the SQLCA associated with the current connection.

This function is useful if you are combining embedded SQL and the C++ API in a single application.

Return

A pointer to the SQLCA.

Example

ULConnection conn;

conn.Open();

conn.GetCA();

See also

The SQL Communication Area


GetSQLCode method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 GetSQLCode method

Syntax

an_sql_code  GetSQLCode( )

Description

Provides error checking capabilities by checking the SQLCODE value for the success or failure of a database operation. The SQLCODE is the standard Adaptive Server Anywhere code.

Return

The SQLCODE value as an integer.

Example

The following code writes out a SQLCODE. If the synchronization call fails, a value of -85 is returned.

conn.Synchronize( &synch_info );

sqlcode = conn.GetSQLCode();

printf("sqlcode: %d\n", sqlcode );

See also

Database Error Messages


InitSynchInfo method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 InitSynchInfo method

Syntax

an_sql_code  InitSynchInfo( ul_synch_info * synch_info )

Description

Initializes the synch_info structure used for synchronization.

Return

None

Example

The following code illustrates where the InitSynchInfo method is used in the sequence of calls that synchronize data in a UltraLite application.

auto ul_synch_info synch_info;

conn.InitSynchInfo( &synch_info );

conn.Synchronize( &synch_info );

See also

Synchronize method


IsOpen method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 IsOpen method

Syntax

bool  IsOpen ( )

Description

Checks whether the ULConnection object is currently open.

Return

true (1) if the ULConnection object is open.

false (0) if the ULConnection object is not open.

Example

The following example checks that an attempt to Open a connection succeeded:

ULConnection conn;

conn.Open();

if( conn.IsOpen() ){

printf( "Connected to the database.\n" );

}

See also

Open method


LastCodeOK method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 LastCodeOK method

Syntax

bool  LastCodeOK ( )

Description

Checks whether the most recent SQLCODE returned was zero (true) or non-zero (false).

This method provides a convenient way of checking for the success (SQLCODE zero) or potential failure (non-zero) of operations. You can use GetSQLCode to obtain the numerical value.

Return

true (1) if the previous SQLCode was zero.

false (0) if the previous SQLCode was non-zero.

Example

The following example checks that an attempt to Open a connection succeeded:

ULConnection conn;

conn.Open();

if( conn.LastCodeOK() ){

printf( "Connected to the database.\n" );

};

See also

GetSQLCode method


LastFetchOK method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 LastFetchOK method

Syntax

bool  LastFetchOK( )

Description

Provides a convenient way of checking that the most recent fetch of a row succeeded (true) or failed (false).

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example moves to the last row in a table, fetches a value from the row, and checks for the success of the fetch:

tb.Open( &conn );

tb.Last();

tb.GetID( iVal );

if( tb.LastFetchOK() ){

... operations on success...

}

See also

AfterLast method

First method


Open method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 Open method

Syntax

bool  Open ( ULData* db,
ul_char* userid,
ul_char* password,
ul_char* name = SQLNULL )

Description

Open a connection to a database. The ULData object must be open for this call to succeed.

db    A pointer to the ULData object on which the connection is made. This argument is usually the address of the ULData object opened prior to making the connection.

userid    The user ID argument is a placeholder reserved for possible future use. It is ignored.

  For more information on user IDs and UltraLite, see User IDs in UltraLite databases.

password    The password parameter is a placeholder reserved for possible future use. It is ignored.

name    An optional name for the connection. This is needed only if you have multiple connections from a single application to the same database.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example opens a connection to the UltraLite database.

ULData db;

ULConnection conn;

db.Open();

conn.Open( &db, "dummy", "dummy" );

See also

Close method


Reopen method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 Reopen method

Syntax

bool  Reopen ( )

bool  Reopen( ULData *db, ul_char * name = SQLNULL )

Description

This method is available for the Palm Computing Platform only. The ULData object must be reopened for this call to succeed.

When developing Palm applications, you should never close the connection object. Instead, you should call Reopen when the user switches to the UltraLite application. The method prepares the data in use by the database object for use by the application.

db    A pointer to the ULData object on which the connection is made. This argument is usually the address of the ULData object opened prior to reopening the connection.

name    An optional name for the connection. This is needed only if you have multiple connections from a single application to the same database.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example reopens a database object, and then a connection object:

db.Reopen();

conn.Reopen( &db );

See also

Open method


Rollback method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 Rollback method

Syntax

bool  Rollback( )

Description

Rolls back outstanding changes to the database.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following code inserts a value to the database, but then rolls back the change.

productTable.Open( &conn );

productTable.SetProd_id( 2 );

productTable.SetPrice( 3000 );

productTable.SetProd_name( "8' 2x4 Studs x1000" );

productTable.Insert();

conn.Rollback();

See also

Commit method


Synchronize method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULConnection class

 Synchronize method

Syntax

bool  Synchronize ( ul_synch_info * synch_info )

Description

Synchronizes an UltraLite database.

  For a detailed description of the members of the synch_info structure, see Setting synchronization parameters.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following code fragment illustrates how information is provided to the Synchronize method.

auto ul_synch_info synch_info;

conn.InitSynchInfo( &synch_info );

synch_info.user_name = UL_TEXT( "50" );

synch_info.version = UL_TEXT( "custdb" );

synch_info.stream = ULSocketStream();

synch_info.stream_parms =

UL_TEXT("host=localhost");

conn.Synchronize( &synch_info );

See also

Setting synchronization parameters


ULData class
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 ULData class

Object

Represents an UltraLite database.

Syntax

To create a ULData object:

ULData db;
db.Open();

Description

The ULData class represents an UltraLite database to your application. It provides methods to open and close a database, and to check whether a database is open.

You must open a database before connecting to it or carrying out any other operation, and you must close the database after you have finished all operations on the database, and before your application terminates.

For embedded SQL users, opening a ULData object is equivalent to calling db_init.

  For its position in the API hierarchy, see C++ API class hierarchy.

Example

The following example declares a ULData object and opens it:

ULData db;

db.Open();

 Close method

 getSQLCode method

 IsOpen method

 Open method

 PalmExit method

 PalmLaunch method

 Reopen method


Close method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULData class

 Close method

Syntax

bool  Close ( )

Description

Frees resources associated with a ULData object, before you terminate your application. Once you have closed the ULData object, you cannot execute any other operations on that database using the C++ API without reopening.

You should not close a database object in a Palm Computing Platform application. Instead, use the Reopen method when the application is reactivated.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example closes a ULData object:

db.Close();

See also

Open method


getSQLCode method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULData class

 getSQLCode method

Syntax

an_sql_code getSQLCode()

Description

Returns the SQLCODE from the most recent operation.

an_sql_code    A 4-byte integer.

Return

0 for success.

For other SQLCODE values, see Error messages indexed by Adaptive Server Anywhere SQLCODE.


IsOpen method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULData class

 IsOpen method

Syntax

bool  IsOpen ( )

Description

Checks whether the ULData object is currently open.

Return

true (1) if the ULData object is open.

false (0) if the ULData object is not open.

Example

The following example declares a ULData object, opens it, and checks that the Open method succeeded:

ULData db;

db.Open();

if( db.IsOpen() ){

printf( "The ULData object is open\n" );

}

See also

Open method


Open method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULData class

 Open method

Syntax

bool  Open ( )

bool  Open( SQLCA* ca )

bool  Open( ul_char* parms )

bool  Open( SQLCA* ca , ul_char* parms )

Description

Prepares your application to work with a database. You must open the ULData object before carrying out any other operations on the database using the C++ API.

Open( )    No arguments are needed if you are not using embedded SQL as well as the C++ API in your application and wish to use the default persistent store parameters.

Open( SQLCA* ca )    If you are also using embedded SQL in your application, and you have a SQLCA in use, you can use this method to access the same data using the C++ API.

Open( ul_char* parms )    A string specifying persistent storage parameters (file_name, cache_size, reserve_size) to govern database access. The string is a semicolon-separated list of assignments, of the form parameter=value.

Open( SQLCA *ca, ul_char* parms )    A call specifying both the SQLCA and persistent storage parameters.

  For more information on the parameters, see Configuring file-based persistent storage.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example declares a ULData object and opens it:

ULData db;

db.Open();

See also

Close method


PalmExit method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULData class

 PalmExit method

Syntax

bool PalmExit( SQLCA *ca )

bool PalmExit( ul_synch_info * synch_info )

Arguments

sqlca    A pointer to the SQLCA. You do not need to supply this argument unless you are using embedded SQL as well as the C++ API in your application and have used a non-default SQLCA.

synch_info    For information on the members of the synch_info structure, see Setting synchronization parameters.

Returns

true (1) if successful.

false (0) if unsuccessful

Description

Call this method just before your application is closed, to save the state of the application.

For applications using HotSync or Scout Sync synchronization, the method also writes an upload stream. When the user uses HotSync or Scout Sync to synchronize data between their Palm device and a PC, the upload stream is read by the MobiLink HotSync conduit or the MobiLink Scout conduit respectively.

If you are using TCP/IP, HTTP, or serial synchronization, supply NULL values for the user_name, stream, and stream_parms members of ul_synch_info. This information is supplied instead in the ULConnection.Synchronize method.

If you use HotSync or Scout Sync synchronization, supply ULConduitStream() or ULPalmDBStream() as the stream parameter. You must also supply the user_name and stream_parms parameters.

The MobiLink HotSync and ScoutSync conduits synchronize with the MobiLink synchronization server through a TCP/IP, HTTP, or serial stream using stream parameters. Specify the stream and stream parameters in the ul_synch_info structure. Alternatively, you may specify the stream and stream parameters via the ClientParms registry entry. If the ClientParms registry entry does not exist, a default setting of {stream=tcpip;host=localhost} is used.


PalmLaunch method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULData class

 PalmLaunch method

Syntax

UL_PALM_LAUNCH_RET PalmLaunch( );

UL_PALM_LAUNCH_RET PalmLaunch( ul_synch_info * synch_info );

UL_PALM_LAUNCH_RET PalmLaunch( SQLCA* ca );

UL_PALM_LAUNCH_RET PalmLaunch( SQLCA* ca ,
ul_synch_info * synch_info );

typedef enum {
LAUNCH_SUCCESS_FIRST,
LAUNCH_SUCCESS,
LAUNCH_FAIL
} UL_PALM_LAUNCH_RET;

Arguments

ca    A pointer to the SQLCA. You do not need to supply this argument unless you are using embedded SQL as well as the C++ API in your application and have used a non-default SQLCA.

synch_info    A synchronization structure. For information on the members of this structure, see Setting synchronization parameters.

If you are using TCP/IP, HTTP or serial synchronization, supply a null value for the stream parameter.

Returns

A member of the UL_PALM_LAUNCH_RET enumeration. The return values have the following meanings:

•	LAUNCH_SUCCESS_FIRST    This value is returned the first time the application is successfully launched. In embedded SQL applications you should call db_init immediately after this return code is detected; in C++ API applications, you should open a database object.

•	LAUNCH_SUCCESS    This value is returned when an application is successfully launched, after the Palm user has been using other applications.

•	LAUNCH_FAIL    This value is returned when the launch fails.

Description

This function restores the application state when the application is activated. For applications using HotSync or Scout Sync synchronization, it carries out the additional task of processing the download stream prepared by the MobiLink HotSync conduit or MobiLink Scout conduit.

If you are using TCP/IP, HTTP or serial synchronization, supply a null value for the stream parameter in the ul_synch_info synchronization structure. This information is supplied instead in the synchronization structure called by the ULConnection.Synchronize method.

Examples

A typical C++ API example is

ULData db;

switch( db.PalmLaunch( &synch_info ) ){

case LAUNCH_SUCCESS_FIRST:

if( !db.Open() ){

// initialization failed: add error handling here

break;

}

// fall through

case LAUNCH_SUCCESS:

db.Reopen();

// do work here

break;

case LAUNCH_FAIL:

// error

break;

}


Reopen method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULData class

 Reopen method

Syntax

bool  Reopen ( )

bool  Reopen( SQLCA* ca )

Description

This method is available for the Palm Computing Platform only.

When developing Palm applications, you should never close the database object. Instead, you should call Reopen when the user switches to the UltraLite application. The method prepares the data in use by the database object for use by the application.

Open( )    No arguments are needed if you are not using embedded SQL as well as the C++ API in your application.

Open( SQLCA* ca )    If you are also using embedded SQL in your application, and you have a non-default SQLCA in use, you can use this method to access the same data using the C++ API.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example reopens a database object and a connection object:

db.Reopen();

conn.Reopen( &db );

See also

Open method


ULCursor class
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 ULCursor class

The ULCursor class contains methods needed by both generated table objects and generated result set objects.

  For its position in the API hierarchy, see C++ API class hierarchy.

 Data types enumeration

 AfterLast method

 BeforeFirst method

 Close method

 Delete method

 First method

 Get method

 GetColumnCount method

 GetColumnSize method

 GetColumnType method

 Insert method

 Last method

 Next method

 Open method

 Previous method

 Relative method

 Reopen method

 Set method

 SetColumnNull method

 Update method


Data types enumeration
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Data types enumeration

This enumeration lists the available UltraLite data types, as constants. It contains the following members:

Enumeration value	Description
BAD_INDEX	An inappropriate argument was provided
S_LONG	Signed 4-byte integer
S_SHORT	Signed 2-byte integer
LONG	4-byte integer
SHORT	2-byte integer
TINY	1-byte integer
BIT	Bit
TIMESTAMP_STRUCT	Timestamp information as a struct.
DATE	Data and time information as a string
TIME	Time information as a string
S_BIG	Signed 8-byte integer
BIG	8-byte integer
DOUBLE	Double precision number
REAL	Real number
BINARY	Binary data, with a specified length
TCHAR	Character data, with a specified length
NUMERIC	Exact numerical data, with a specified precision and scale


AfterLast method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 AfterLast method

Syntax

bool  AfterLast( )

Description

Changes the cursor position to be after the last row in the current table or result set.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example makes the current row the last row of the table tb:

tb.AfterLast();

tb.Previous();

See also

BeforeFirst method

Last method


BeforeFirst method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 BeforeFirst method

Syntax

bool  BeforeFirst( )

Description

Changes the cursor position to be before the first row in the current table or result set.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example makes the current row the first row of the table tb:

tb.BeforeFirst();

tb.Next();

See also

AfterLast method

First method


Close method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Close method

Syntax

bool  Close( )

Description

Frees resources associated with the generated object in your application. This method must be called after all processing involving the table is complete, and before the ULConnection and ULData objects are closed.

Any uncommitted operations are rolled back when the Close() method is called.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example closes a generated object for a table named ULProduct:

tb.Close();

See also

Open method


Delete method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Delete method

Syntax

bool  Delete( )

Description

Deletes the current row from the current table or result set.

Return

true (1) if successful.

false (0) if unsuccessful. For example, if you attempt to use the method on a SQL statement that represents more than one table.

Example

The following example deletes the last row from a table tb:

tb.Open( &conn );

tb.Last();

tb.Delete();

See also

Insert method

Update method


First method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 First method

Syntax

bool  First( )

Description

Moves the cursor to the first row of the table or result set.

Return

true (1) if successful.

false (0) if unsuccessful. For example, the method fails if there are no rows.

Example

The following example deletes the first row from a table tb:

tb.Open( &conn );

tb.First();

tb.Delete();

See also

BeforeFirst method

Last method


Get method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Get method

Syntax

bool  Get( ul_column_num colnum,
value-declaration,
bool* isNull = UL_NULL)

value-declaration:
  ul_char * ptr, ul_length length
| p_ul_binary name , ul_length length
| DECL_DATETIME &date-value
| { DECL_BIGINT | DECL_UNSIGNED_BIGINT } &bigint-value
| [ unsigned ]  long &integer-value
| unsigned char &char-value
| double & double-value
| float & float-value
| [ unsigned ]  short &short-value

Description

Gets a value from the specified column.

colnum    A 2-byte integer. The first column is column 1.

value declaration    The arguments required to specify the value depend on the data type. Character and binary data must be mapped into buffers, with the buffer name and length specified in the call. For other data types, a pointer to a variable of the proper type is needed.

isNULL    If a value in a column is NULL, isNull is set to true. In this case, the value argument is not meaningful.

Return

true (1) if successful.

false (0) if unsuccessful.

See also

Get generated method

Set method


GetColumnCount method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 GetColumnCount method

Syntax

int  GetColumnCount( )

Description

Returns the number of columns in the current table or result set.

Return

Integer number of columns.

Example

The following example opens a table object named tb and places the number of columns in the variable numCol:

tb.Open( &conn );

numCol = tb.GetColumnCount();


GetColumnSize method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 GetColumnSize method

Syntax

ul_length  GetColumnSize( ul_column_num column-index )

Description

Returns the number of bytes needed to hold the information in the specified column.

column-index    The number of the column. The first column in the table has a value of one.

Return

The number of bytes.

Example

The following example gets the number of bytes needed to hold the third column in the table tb:

tb.Open( &conn );

colSize = tb.GetColumnSize( 3 );

See also

GetColumnType method


GetColumnType method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 GetColumnType method

Syntax

int  GetColumnType( ul_column_num column-index )

Description

Returns the data type needed to hold the information in the specified column.

column-index    The number of the column. The first column in the table or result set has a value of one.

Return

The column type is a member of the UltraLite data types enumeration. For more information, see Data types enumeration:

Example

The following example gets the column type for the third column in the table tb:

tb.Open( &conn );

colType = tb.GetColumnType( 3 );

See also

Data types enumeration

Get generated method


Insert method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Insert method

Syntax

bool  Insert( )

Description

Inserts a row in the table with values specified in previous Set methods.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example inserts a new row into the table based at the current position:

productTable.SetProd_id( 2 );

productTable.SetPrice( 3000 );

productTable.SetProd_name( "8' 2x4 Studs x1000" );

productTable.Insert();

When inserting a row, you must supply a value for each column in the table.

  For information on cursor positioning after inserts, and the position of the inserted row, see Using table and query classes.

See also

Delete method

Update method


Last method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Last method

Syntax

bool  Last( )

Description

Move the cursor to the last row in the table or result set.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example moves to a position after the last row in a table:

tb.Open( &conn );

tb.Last();

tb.Next();

See also

AfterLast method

First method


Next method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Next method

Syntax

bool  Next( )

Description

Moves the cursor position to the next row in the table or result set.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example moves the cursor position to the first row in the table:

tb.Open( &conn );

tb.BeforeFirst();

tb.Next();

See also

Previous method

Relative method


Open method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Open method

Syntax

bool  Open( ULConnection * conn )

Description

Opens a cursor on the specified connection. If the object is a result set with parameters, you must set the parameters before opening the result set.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example opens a result set object (which extends the cursor class) and moves the cursor position to the first row:

rs.Open( &conn );

rs.BeforeFirst();

rs.Next();

See also

Close method

Open method


Previous method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Previous method

Syntax

bool  Previous( )

Description

Moves the cursor position to the previous row in the table or result set.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example moves to the last row in a table:

tb.Open( &conn );

tb.AfterLast();

tb.Previous();

See also

Next method

Relative method


Relative method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Relative method

Syntax

bool  Relative( ul_fetch_offset offset  )

Description

Moves the cursor position relative to the current position. If the row does not exist, the method returns false, and the cursor is left at AfterLast() if offset is positive, and BeforeFirst() if offset is negative.

offset    The number of rows to move. Negative values correspond to moving backwards.

Return

true (1) if the row exists.

false (0) if the row does not exist.

See also

Next method

Previous method


Reopen method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Reopen method

Syntax

bool  Reopen( ULConnection *conn )

Description

This method is available for the Palm Computing Platform only. The ULData and ULCOnnection objects must already be reopened for this call to succeed.

When developing Palm applications, you should never close result set objects if you wish to maintain the cursor position. Instead, you should call Reopen when the user switches back to the UltraLite application.

Although the ULTable object inherits from the ULCursor class, you should not use Reopen on table objects. Instead, you should close them on exiting the Palm application and Open them on re-entering. The cursor position is not maintained in ULTable objects.

conn    A pointer to the ULConnection object on which the cursor is defined.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example reopens a database object, and then a connection object, and then a result set object:

db.Reopen();

conn.Reopen( &db );

rs.Reopen( &conn );

See also

Open method


Set method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Set method

Syntax

bool  Set( ul_column_num colnum, value )

value:
  p_ul_binary buffer-name, ul_length buffer-length
| ul_char * buffer-name, ul_length buffer-length = 0
| DECL_DATETIME date-value
| DECL_UNSIGNED_BIGINT bigint-value
| unsigned char  char-value
| double double-value
| float float-value
| [ unsigned ] long long-value
| [ unsigned ] short short-value

Description

Sets a value in the specified column, for the current row.

colnum    A 2-byte integer. The first column is column 1.

value    For character and binary data you must supply a buffer name and length. For other data types, a value of the proper type is needed. The function fails if the data type is incorrect for the column.

The BIGINT data type is not supported on DOS

Return

true (1) if successful.

false (0) if unsuccessful.

See also

Get method


SetColumnNull method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 SetColumnNull method

Syntax

int  SetColumNull( ul_column_num column-index )

Description

Sets a column to the SQL NULL. The data is not actually changed until you execute an Insert or Update, and that change is not permanent until it is committed.

column-index    The number of the column. The first column in the table has a value of one.

Return

true (1) if successful.

false (0) if unsuccessful.

See also

SetNull<Column> generated method


Update method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULCursor class

 Update method

Syntax

bool  Update( )

Description

Updates a row in the table with values specified in previous Set methods.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example sets a new price on the current row of the productTable object, and then updates the row in the UltraLite database:

productTable.SetPrice( 400 );

productTable.Update();

See also

Delete method

Insert method


ULResultSet class
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 ULResultSet class

The ULResultSet class extends the ULCursor class, and provides methods needed by all generated result sets.

  For more information, see ULCursor class, and Generated result set class.

  For its position in the API hierarchy, see C++ API class hierarchy.

 SetParameter method


SetParameter method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULResultSet class

 SetParameter method

Syntax

virtual bool  SetParameter( int argnum,  value-reference )

value-reference:
  [ unsigned ] long & value
| p_ul_binary value
| unsigned char & value
| ul_char * value
| double & value
| float & value
| [ unsigned ] short & value
| DECL_DATETIME value
| DECL_BIGINT value
| DECL_UNSIGNED_BIGINT value

Description

The following query defines a result set with a parameter:

SELECT id

FROM mytable

WHERE id < ?

The result set object defined in the C++ API that corresponds to this query has a parameter. You must set the value of the parameter before opening the generated result set object.

argnum    An identifier for the argument to be set. The first argument is 1, the second 2, and so on.

value-reference    A reference to the parameter value. The data type listing above provides the possibilities. BIGINT is not supported on DOS.

Return

true (1) if successful.

false (0) if unsuccessful. If you supply a parameter of the wrong data type, the method fails.

See also

Open method


ULTable class
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 ULTable class

The ULTable class extends the ULCursor class, and provides methods needed by all generated table objects.

  For its position in the API hierarchy, see C++ API class hierarchy.

 LookupBackward method

 LookupForward method


LookupBackward method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULTable class

 LookupBackward method

Syntax

bool  LookupBackward( ul_column_num ncols )

Description

Move backwards through the table, looking for the first row that matches a value or set of values in the current index.

To specify the value to search for, set the column value for each column in the index. The cursor is left on the first row that matches the index value. On failure, the cursor position is BeforeFirst().

ncols    For composite indexes, the number of columns to use in the lookup. For example, if there is a three column index, and you want to lookup a value that matches based on the first column only, you should Set the value for the first column, and then supply an ncols value of 1.

Return

true (1) if successful.

false (0) if unsuccessful.

See also

LookupForward method


LookupForward method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        ULTable class

 LookupForward method

Syntax

bool  LookupForward( ul_column_num ncols  )

Description

Move forward through the table, looking for the first row that matches a value or set of values in the current index.

To specify the value to search for, aet the column value for each column in the index. The cursor is left on the first row that matches the index value. On failure, the cursor position is AfterLast().

ncols    For composite indexes, the number of columns to use in the lookup. For example, if there is a three column index, and you want to lookup a value that matches based on the first column only, you should Set the value for the first column, and then supply an ncols value of 1.

Return

true (1) if successful.

false (0) if unsuccessful.

See also

LookupBackward method


Generated result set class
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 Generated result set class

Object

The generated result set class represents a query result set to your application. The name of the class is generated by the UltraLite generator, based on the name of the statement supplied when it was added to the database.

Syntax

To create a generated result set object, you use the generated name in the declaration

result-set  rs;
rs.Open();

result-set: generated name

Description

The UltraLite generator defines a class for each named statement in an UltraLite project that returns a result set. This class inherits methods from ULCursor.

  For its position in the API hierarchy, see C++ API class hierarchy.

See also

ULCursor class

ul_add_statement system procedure

 Open method


Open method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        Generated result set class

 Open method

Syntax

bool Open( ULConnection * conn,
datatype value, ... )

Description

The UltraLite generator defines a class for each named statement in an UltraLite project that returns a result set. This class inherits methods from ULCursor.

You must supply a value for each placeholder in the result set.

conn    The connection on which the result set is to be opened.

value    The value for the placeholder in the result set.

Example

The following query contains a single placeholder:

select prod_id, price, prod_name

from "dba".ulproduct

where price < ?

The generator writes out the following methods for the object (in addition to some others):

bool Open( ULConnection* conn,

    long Price	 );

bool Open( ULConnection* conn );

bool SetParameter( int index, long &value );

See also

SetParameter method


Generated statement class
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 Generated statement class

For each SQL statement that does not return a result set, including inserts, updates, and deletes, the UltraLite generator defines a generated statement class. The name of the class is the name provided in the ul_add_statement stored procedure call that added the statement to the reference database.

The generated statement class inherits from the ULStatement class, which has no methods of its own.

  For its position in the API hierarchy, see C++ API class hierarchy.

 Execute method


Execute method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        Generated statement class

 Execute method

Syntax

bool  Execute( ULConnection* conn,
[ datatype column-name,... ] )

Description

Executes a named statement that does not return a result set. Any change made is not permanent until it is committed.

When a statement is defined using ul_add_statement, you supply placeholders for the values, and supply them at run time. The generated prototype has a data type and name for each value.

conn    The connection on which the statement is to be executed.

datatype    A member of the UltraLite data type enumeration.

column-name    The name of the column.

Return

true (1) if successful.

false (0) if unsuccessful.

See also

ul_add_statement system procedure


Generated table class
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

 Generated table class

Object

The generated table class represents a database table to your application. The name of the class is generated by the UltraLite generator, based on the name of the table in the database.

Syntax

To create a table object:

Tablename tb;
tb.Open();

Tablename:
generated name

Description

The UltraLite generator defines a class for each table in a named SQL Remote publication. The generated table class inherits from ULTable and ULCursor. The class has a name based on the table or statement name, so that for a table named Product, the generator defines a class named Product.

  For its position in the API hierarchy, see C++ API class hierarchy.

See also

ULCursor class

ULTable class

 Get generated method

 Get<Column> generated method

 GetSize<Column> generated method

 Open method

 Set<Column> generated method

 SetNull<Column> generated method

 Index enumeration


Get generated method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        Generated table class

 Get generated method

Syntax

bool  Get ( ul_column_num  column-index,
value-declaration,
bool* isNull = UL_NULL )

value-declaration:
  ul_char * buffer-name, ul_length buffer-length
| p_ul_binary buffer-name, ul_length buffer-length
| DECL_DATETIME &date-value
| { DECL_BIGINT | DECL_UNSIGNED_BIGINT } &bigint-value
| unsigned char &char-value
| double & double-value
| float & float-value
| [ unsigned ]  long &integer-value
| [ unsigned ]  short &short-value

Description

Gets a value of from a column, specified by index.

column-index    The number of the column. The first column in the table has a value of one.

value declaration    The arguments required to specify the value depend on the data type. Character and binary data must be mapped into buffers, with the buffer name and length specified in the call. For other data types, a pointer to a variable of the proper type is needed.

isNULL    If a value in a column is NULL, isNull is set to true. In this case, the value argument is not meaningful.

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example is part of a switch statement that gets values from rows based on their data type:

switch( tb.GetColumnType( colIndex ) ) {

case tb.S_LONG :

ret = tb.Get( colIndex, longval );

printf( "Long column: %d\n", longval );

break;

...

See also

Data types enumeration

Get method

Get<Column> generated method

GetColumnSize method


Get<Column> generated method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        Generated table class

 Get<Column> generated method

Syntax

bool  Getcolumn-name( type* variable, [ ul_length* length, ]
bool* isNull = UL_NULL )

Description

Retrieves a value from column-name. The type specification depends on the column data type.

column-name    The name of the column.

variable    A variable of the proper data type for the column. This data type can be retrieved using GetColumnType.

length    For variable length

isNull    If the value is NULL, this argument is true.

Return

true (1) if successful.

false (0) if unsuccessful.

See also

Get generated method


GetSize<Column> generated method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        Generated table class

 GetSize<Column> generated method

Syntax

ul_length  GetSizecolumn-name(  )

Description

Returns the storage area needed to hold a value from the specified column.

column-name    A generated name derived from the name of the column in the reference database.

Return

true (1) if successful.

false (0) if unsuccessful.

See also

GetColumnType method


Open method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        Generated table class

 Open method

Syntax

bool  Open( ULConnection* conn )

bool  Open( ULConnection* conn, ul_index_num index  )

Description

Prepares your application to work with the data in a generated table object.

conn    The address of a ULConnection object. The connection must be open.

index    An optional index number, used to order the rows in the table. The index is one of the members of the generated index enumeration. By default, the table is ordered by primary key value.

  For more information, see Index enumeration.

When the table is opened, the cursor is positioned before the first row

Return

true (1) if successful.

false (0) if unsuccessful.

Example

The following example declares a generated object for a table named ULProduct, and opens it:

ULData db;

ULConnection conn;

ULProduct tb;

db.Open();

conn.Open( &db, "dba", "sql" );

tb.Open( &conn );

See also

Close method

Index enumeration


Set<Column> generated method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        Generated table class

 Set<Column> generated method

Syntax

bool  Setcolumn-name( )

Description

Sets the value of the cursor at the current position. The data in the row is not actually changed until you execute an Insert or Update, and that change is not permanent until it is committed.

column-name    A generated name derived from the name of the column in the reference database.

Return

true (1) if successful.

false (0) if unsuccessful.

See also

SetColumnNull method


SetNull<Column> generated method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        Generated table class

 SetNull<Column> generated method

Syntax

bool  SetNullcolumn-name( )

Description

Sets a column to the SQL NULL. The data is not actually changed until you execute an Insert or Update, and that change is not permanent until it is committed.

column-name    A generated name derived from the name of the column in the reference database.

Return

true (1) if successful.

false (0) if unsuccessful.

See also

SetColumnNull method


Index enumeration
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 7.  C++ API Reference

        Generated table class

 Index enumeration

Syntax

enum{ index-name,... }

Description

Each member of the enumeration is an index name in the table being generated. You can use the index name to specify an ordering for the table when it is opened, and thereby control the behavior of the cursor movement methods.

index-name    The name of an index in the table. The primary key has the name Primary, and other indexes have their name in the database.

See also

Open method


CHAPTER 8.  An Embedded SQL Tutorial
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

 CHAPTER 8.  An Embedded SQL Tutorial

About this chapter

This chapter provides a tutorial that guides you through the process of developing an embedded SQL UltraLite application. The first section includes a sample embedded SQL source file and discusses the key elements in the sample source file. The second section provides instructions for building an UltraLite application using this sample source file.

  For an overview of the development process and background information on the UltraLite database, see UltraLite Feature Overview.

  For information on developing embedded SQL UltraLite Applications, see Building Embedded SQL UltraLite Applications.

  For a description of embedded SQL, see The UltraLite Embedded SQL Interface.

  For additional information, specific to your target device, see Target-Platform Specific Development.

 Introduction

 Writing source files in embedded SQL

 Building the sample embedded SQL UltraLite application


Introduction
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 8.  An Embedded SQL Tutorial

 Introduction

In this tutorial, you will create an embedded SQL source file and use this source file to build a simple UltraLite application. The next section Writing source files in embedded SQL provides a sample embedded SQL program. Copy this program into a new file and save it as a .sqc source file. Then, follow the step by step instructions in Building the sample embedded SQL UltraLite application to build the UltraLite application. The UltraLite application can be executed in the Windows NT environment on your PC.

This tutorial assumes that you have UltraLite installed on Windows 95/98 or Windows NT.  To follow the tutorial, you should also have Microsoft Visual C++ 6.0 installed.  If you use a different C/C++ development tool, you will have to translate the Visual C++ instructions into their equivalent for your development tool.

♦ To prepare for the tutorial

•	Create a directory to hold the files you will create: c:\esqltutorial.


Writing source files in embedded SQL
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 8.  An Embedded SQL Tutorial

 Writing source files in embedded SQL

The following sample program establishes a connection with the UltraLite CustDB sample database and executes a select query. Copy the following code into a new file and save it as sample.sqc in your c:\esqltutorial directory, or retype the material into a file.

#include <stdio.h>

EXEC SQL INCLUDE SQLCA;

main()

{

/* Declare fields */

EXEC SQL BEGIN DECLARE SECTION;

long pid=1;

long cost;

char pname[31];

EXEC SQL END DECLARE SECTION;

/* Before working with data*/

db_init(&sqlca);

/* Connect to database */

EXEC SQL CONNECT "DBA" IDENTIFIED BY "SQL";

/* Fill table with data first */

EXEC SQL INSERT INTO ULProduct(

prod_id, price, prod_name)

VALUES (1, 400, '4x8 Drywall x100');

EXEC SQL INSERT INTO ULProduct (

prod_id, price, prod_name)

VALUES (2, 3000, '8''2x4 Studs x1000');

EXEC SQL COMMIT;

/* Fetch row from database */

EXEC SQL SELECT price, prod_name

INTO :cost, :pname

FROM ULProduct

WHERE prod_id= :pid;

/* Error handling.  If the row does not exist, or if 	an error occurs, -1 is returned */

if((SQLCODE==SQLE_NOTFOUND)||(SQLCODE<0)) {

return(-1);

}

/* Print query results */

printf("Product id: %ld Price: %ld Product name: %s", 	pid, cost, pname);

/* Preparing to exit:

rollback any outstanding changes and disconnect */

EXEC SQL ROLLBACK;

EXEC SQL DISCONNECT;

db_fini(&sqlca);

return(0);

}

Tip
You can configure Visual C++ to provide syntax highlighting for .sqc files, by adding ;sqc to the list of file extensions in the following registry location:

HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\

Text Editor\Tabs\Language Settings\C/C++\FileExtensions

 Explanation of the sample program


Explanation of the sample program
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 8.  An Embedded SQL Tutorial

        Writing source files in embedded SQL

 Explanation of the sample program

Although too simple to be useful, this example contains elements that must be present in every embedded SQL source file used for database access. The following describes the key elements in the sample program. Use these steps as a guide when creating your own embedded SQL UltraLite application.

1	Include the appropriate header files.

The sample program utilizes standard I/O, therefore the stdio.h header file has been included.

2	Define the SQL communications area, sqlca.

Use the following command:

EXEC SQL INCLUDE SQLCA;

This definition must be your first embedded SQL statement, so place it at the end of your include list.

Prefix SQL statements
All SQL statements must be prefixed with the keywords EXEC SQL and must end with a semicolon.

3	Define host variables by creating a declaration section.

Host variables are used to send values to the database server or receive values from the database server. Create a declaration section as follows:

EXEC SQL BEGIN DECLARE SECTION;

long pid=1;

long cost;

char pname[31];

EXEC SQL END DECLARE SECTION;

  For information on host variables, see Host variables.

4	Call the embedded SQL library function db_init to initialize the UltraLite runtime library.

Call this function as follows:

db_init(&sqlca);

5	Connect to the database using the CONNECT statement.

To connect to the UltraLite sample database, you must supply the login user ID and password. Connect as user DBA with password SQL as follows:

EXEC SQL CONNECT "DBA" IDENTIFIED BY "SQL";

6	Insert data into database tables.

When an application is first started, its database tables are empty. Only when you choose to synchronize the remote database with the consolidated database will the tables be filled with values so that you may execute select, update or delete commands. Rather than using synchronization, however, you may also directly insert data into the tables. Directly inserting data is a useful technique during the early stages of UltraLite development.

If you use synchronization and your application fails to execute a query, it can be due to a problem in the synchronization process or due to a mistake in your program. To locate the source of failure may be difficult. On the other hand, if you directly fill tables with data in your source code rather than perform synchronization, then, if your application fails, you will know automatically that the failure is due to a mistake in your program.

After you have tested that there are no mistakes in your program, remove the insert statements and replace them with a call to the ULSynchronize function to synchronize the remote database with the consolidated database.

  For information on adding synchronization to an UltraLite application, see Adding synchronization to your application.

7	Execute your SQL query.

The sample program executes a select query that returns one row of results. The results are stored in the previously defined host variables cost and pname.

8	Perform error handling.

The sample program executes a select request that returns an error code, sqlcode. This code is negative if an error occurs; SQL_NOTFOUND is returned if there are no query results. The sample program handles these errors by returning -1.

9	Disconnect from the database.

You should rollback or commit any outstanding changes before disconnecting.

To disconnect, use the DISCONNECT statement as follows:

EXEC SQL DISCONNECT;

10	End your SQL work with a call to the library function db_fini:

db_fini(&sqlca);


Building the sample embedded SQL UltraLite application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 8.  An Embedded SQL Tutorial

 Building the sample embedded SQL UltraLite application

After you have created a source file sample.sqc using the sample code in the previous section, you are ready to build your UltraLite application. Follow these steps in Microsoft Visual C++ 6.0 to create the sample embedded SQL UltraLite application.

1	Start the Adaptive Server Anywhere personal database server.

By starting the database server, both the SQL preprocessor and the UltraLite analyzer will have access to your reference database. The sample application uses the CustDB sample database custdb.db as a reference database and as consolidated database. Start the database server at the command line from the directory containing custdb.db as follows:

dbeng7.exe -c 16M custdb.db

Alternatively, you can start the database server by selecting Start [image] Programs [image] Sybase SQL Anywhere 7 [image] UltraLite [image] UltraLite Sample Database.

2	Start Microsoft Visual C++ from your desktop in the standard fashion.

3	Configure Visual C++ to search the appropriate directories for Embedded SQL header files and UltraLite library files.

Select Tools [image] Options and click on the Directories tab. Choose Include Files under the Show Directories For drop down menu. Include the following directory, so that the Embedded SQL header files can be accessed.

C:\Program Files\Sybase\SQL Anywhere 7\h

On the same tab, select Library Files under the Show Directories For drop down menu. Include the following directory so that the UltraLite library files can be accessed.

C:\Program Files\Sybase\SQL  Anywhere 7\Ultralite\win32\386\lib

Click OK to submit the changes.

1	Create a new workspace tutorial.

Select File [image] New [image] Workspaces [image] Blank Workspace. Specify a workspace name tutorial and specify C:\esqltutorial\tutorial as the location to save this workspace. Click OK. Workspace tutorial will be added to the Workspace window.

2	Create a new project ultutorial and add it to the tutorial workspace.

Select File [image] New [image] Projects [image] WIN32 Console Application. Specify a project name ultutorial and select Add To Current Workspace. Click OK. Choose to create An Empty Project and click Finish. The project will be saved in the tutorial folder.

Click the FileView tab on the Workspace window. The workspace tutorial now consists of one project. Project ultutorial is listed under the workspace tutorial and has three folders: Source Files, Header Files, Resource Files.

3	Add the sample.sqc embedded SQL source file to the project.

Right click on the Source Files folder and select Add Files to Folder. Locate your sample.sqc file and click OK. Open the Source Files folder to verify that it contains sample.sqc.

4	Configure the sample.sqc source file settings to invoke the SQL preprocessor to preprocess the source file.

Right click on the sample.sqc file in the Workspace window and select Settings. A Project Settings dialog appears.

From the Settings For drop down menu, choose All Configurations. In the Custom Build tab, enter the following statement in the Commands box. Ensure that the statement is entered all on one line.

"%asany7%\win32\sqlpp.exe" -q -o WINNT -c  "dsn=Ultralite 7.0 Sample" $(InputPath) sample.cpp

Specify sample.cpp in the Outputs box. Click OK to submit the changes. This statement runs the SQL preprocessor sqlpp on the sample.sqc file, and writes the processed output in a file named sample.cpp. The SQL preprocessor translates SQL statements in the source file into C/C++.

Because the sample application consists of only one source file, the preprocessor automatically runs the UltraLite analyzer as well and appends extra C/C++ code to the generated source file.

5	Preprocess the sample.sqc file.

Select sample.sqc in the Workspace window. Choose Build [image] Compile sample.sqc. A sample.cpp file will be created and saved in the tutorial\ultutorial folder.

6	Add the sample.cpp file to the project.

Right click on the Source Files folder in the Workspace window and select Add Files to Folder. Locate your sample.cpp file (in c:\esqltutorial\tutorial\ultutorial) and click OK. The sample.cpp file appears inside the Source Files folder.

7	Configure the project settings.

Right click on the ultutorial project and select Settings. The Project Settings will appear. Select All Configurations under the Settings For drop down menu. Click on the Link tab and add the following runtime library to the Object/Library Modules box.

ulimp.lib

Click on the C/C++ tab. Select Preprocessor from the Category drop-down menu. Ensure that the following are included in the Preprocessor definitions:

__NT__,UL_USE_DLL

8	Build the executable.

Select Build [image] Build ultutorial.exe. The ultutorial executable will be created. Depending on your settings, the executable may be created in a Debug directory within your tutorial directory.

9	Run the application.

Select Build [image] Execute ultutorial.exe. A screen will appear and display the first row of the product table.

 Adding synchronization to your application


Adding synchronization to your application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 8.  An Embedded SQL Tutorial

        Building the sample embedded SQL UltraLite application

 Adding synchronization to your application

Once you have tested that your program is functioning properly, you can remove the lines of code that manually insert data into the ULProduct table. Replace these statements with a call to the ULSynchronize function to synchronize the remote database with the consolidated database.  This process will fill the tables with data and you can subsequently execute a select query.

 Synchronization via TCP/IP

 Running the sample application with synchronization


Synchronization via TCP/IP
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 8.  An Embedded SQL Tutorial

        Building the sample embedded SQL UltraLite application

          Adding synchronization to your application

 Synchronization via TCP/IP

You can synchronize the remote database with the consolidated database using a TCP/IP socket connection. Call ULSynchronize with the ULSocketStream() stream.

auto ul_synch_info synch_info;

ULInitSynchInfo( &synch_info );

synch_info.user_name = UL_TEXT("50");

synch_info.version = UL_TEXT("custdb");

synch_info.stream = ULSocketStream();

synch_info.stream_parms =

UL_TEXT("host=localhost;port=2439");

ULSynchronize( &sqlca, &synch_info );

In order to synchronize with the CustDB consolidated database, the employee ID must be supplied. This ID identifies an instance of an application to the MobiLink server. You may choose a value of 50, 51, 52, or 53. The MobiLink server uses this value to determine the download content, to record the synchronization state, and to recover from interruptions during synchronization.

  For more information on the ULSynchronize function, see ULSynchronize library function.


Running the sample application with synchronization
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 8.  An Embedded SQL Tutorial

        Building the sample embedded SQL UltraLite application

          Adding synchronization to your application

 Running the sample application with synchronization

After you have made changes to the sample.sqc file, you must preprocess the altered sample.sqc file and rebuild ultutorial.exe.

This section assumes that you have completed the tutorial in the previous section and therefore have the appropriate project settings for the ultutorial project. If, however, you have not run the tutorial, you should refer to the guidelines in the previous section for including the appropriate project settings.

♦ To rebuild the sample application:

1	Ensure that the Adaptive Server Anywhere database server is still running.

2	Preprocess your new sample.sqc file.

In the Workspace window, right click on sample.sqc and select Settings. Ensure that the Commands box contains the appropriate command for running the SQL preprocessor. Choose Build [image] Compile sample.sqc to recompile the altered file. A new sample.cpp file will be generated.

1	Build the executable.

Select Build [image] Build ultutorial.exe to build the sample executable.

♦ To run the sample application:

1	Start the MobiLink synchronization server.

Select Start [image] Programs [image] Sybase SQL Anywhere 7 [image] Synchronization [image] MobiLink Synchronization Server Sample

Alternatively, you can start the MobiLink server by running the following command at the Windows NT command prompt (on a single line) as follows:

dbmlsrv7

-c "DSN=UltraLite 7.0 Sample;UID=DBA;PWD=SQL"

-o ulsync.log -vcr -x tcpip

2	Run the application.

Select Build [image] Execute ultutorial.exe to run the sample application. The remote database will be synchronized with the consolidated database, filling the tables in the remote database with data. The select query in the sample application will be processed, and a row of query results will appear on the screen.


CHAPTER 9.  Developing Embedded SQL Applications
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

 CHAPTER 9.  Developing Embedded SQL Applications

About this chapter

Embedded SQL is a method of mixing SQL statements for database access with either C or C++ source code.

This chapter describes the development process for embedded SQL UltraLite applications. It explains how to write applications using embedded SQL and provides instructions on building and deploying an embedded SQL UltraLite application.

  For additional information, specific to your target device, see Platform-Specific Development.

Before you begin

 This chapter assumes an elementary familiarity with the UltraLite development process. For an overview, see Developing UltraLite Applications

  For a description of embedded SQL, see The Embedded SQL Interface.

  For detailed information about the SQL preprocessor, see The SQL preprocessor.

 Building embedded SQL applications

 Pre-processing your embedded SQL files


Building embedded SQL applications
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 9.  Developing Embedded SQL Applications

 Building embedded SQL applications

You can use a simpler build procedure if all your embedded SQL source code is contained in one file.

If you have only one embedded SQL source file and specify no project name when you run the SQL preprocessor, then the SQL preprocessor automatically runs the UltraLite generator. The supplementary code is generated and appended to the generated C/C++ source file.

If you specify a project name, or use more than one embedded SQL source file, you must generate the UltraLite code using the UltraLite generator.

 Single-file build process

 Multiple-file build process

 Configuring development tools for embedded SQL development


Single-file build process
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 9.  Developing Embedded SQL Applications

        Building embedded SQL applications

 Single-file build process

In this case, the SQL preprocessor runs the UltraLite generator when it completes processing of your file. The generator appends extra C/C++ code to the single generated source file.

♦ To build an UltraLite application (one embedded SQL file only)

1	Start the Adaptive Server Anywhere personal database server, specifying your reference database and a cache size of at least 10 Mb.

2	Preprocess the embedded SQL source file using the SQL preprocessor, supplied with SQL Anywhere. Do not specify a project. The SQL preprocessor runs the UltraLite generator automatically and appends additional code to the generated C/C++ source file. This step relies on your reference database and on the database server.

  For more information, see Pre-processing your embedded SQL files.

3	Compile the C or C++ source file for the target platform of your choice. Include

•	the C file generated by the SQL preprocessor,

•	any additional C/C++ source files that comprise your application.

4	Link all these object files, together with the UltraLite runtime library.

The following diagram depicts the procedure for building your own UltraLite database application. In addition to your source files, you need to create a reference database. As explained below, this database plays dual roles, acting as an instance of the schema used in your application and storing information that the UltraLite analyzer needs to implement your database.


Multiple-file build process
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 9.  Developing Embedded SQL Applications

        Building embedded SQL applications

 Multiple-file build process

If your project contains more than one embedded SQL source file, then you must use a project name. Specify the same project name each time you preprocess an embedded SQL source file. You must also perform an additional step: you must run the UltraLite generator explicitly.

  For information about projects, see Creating an UltraLite project.

♦ To build an UltraLite application (two or more embedded SQL files)

1	Start the Adaptive Server Anywhere personal database server, specifying your reference database and a cache size of at least 10 Mb.

2	Preprocess each embedded SQL source file using the SQL preprocessor, specifying the project name. This step relies on your reference database and on the database server.

  For more information, see Pre-processing your embedded SQL files.

3	Run the UltraLite generator. The generator uses the analyzer, inside your reference database, to analyze information collected while pre-processing your embedded SQL files. The analyzer prepares extra code and the generator writes out a new C source file. This step also relies on your reference database and database server.

  For more information, see Generating the UltraLite data access code.

4	Compile each C or C++ source file for the target platform of your choice. Include

•	each C files generated by the SQL preprocessor,

•	the C file made by the UltraLite generator,

•	any additional C or C++ source files that comprise your application.

5	Link all these object files, together with the UltraLite runtime library.

The following diagram depicts the procedure for building your own UltraLite database application. In addition to your source files, you need to create a reference database. As explained below, this database plays dual roles, acting as an instance of the schema used in your application and storing information that the UltraLite analyzer needs to implement your database.

Each section remaining in this chapter describes one step in writing or building your application.

  For more information about the SQL preprocessor, see Pre-processing your embedded SQL files.

  For more information on the generator, see Generating the UltraLite data access code.


Configuring development tools for embedded SQL development
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 9.  Developing Embedded SQL Applications

        Building embedded SQL applications

 Configuring development tools for embedded SQL development

The SQL preprocessor and the UltraLite generator are key features of UltraLite application development. Most development tools use a dependency-based model to assist in compilation, and this section describes how to incorporate UltraLite features into such a model.

  For a general overview of the techniques needed, see Configuring development tools for UltraLite development.

  The UltraLite plugin for Metrowerks CodeWarrior automatically provides Palm Computing platform developers with the techniques described here. For information on this plugin, see Developing UltraLite applications with Metrowerks CodeWarrior.

This section describes how to add UltraLite code generation and the SQL preprocessor into a dependency-based development environment. The specific instructions provided are for Visual C++.

  For a tutorial describing details for a very simple project, see An Embedded SQL Tutorial.

SQL preprocessing

The first set of instructions describes how to add instructions to run the SQL preprocessor to your development tool.

♦ To add embedded SQL preprocessing into a dependence-based development tool:

1	Add the .sqc files to your development project.

The development project is defined in your development tool. It is separate from the UltraLite project name used by the UltraLite generator.

2	Add a custom build rule for each .sqc file.

•	The custom build rule should run the SQL preprocessor. In Visual C++, the build rule should have the following command (entered on a single line):

"%asany7%\win32\sqlpp.exe" -q -o WINNT

-c connection-string -p project-name

$(InputPath) $(InputName).c

where asany7 is an environment variable that points to your SQL Anywhere installation directory, connection-string provides the connection to the reference database, and project-name is the name of your UltraLite project.

If you are generating an executable for a non-Windows NT platform, choose the appropriate setting instead of WINNT.

  For a full description of the SQL preprocessor command-line, see The SQL preprocessor.

•	Set the output for the command to $(InputName).c.

3	Compile the .sqc files, and add the generated .c files to your development project.

You need to add the generated files to your project even though they are not source files, so that you can set up dependencies and build options.

4	For each generated .c file, set the preprocessor definitions.

•	Under General or Preprocessor, add UL_USE_DLL to the Preprocessor definitions.

•	Under Preprocessor, add $(asany7)\h and any other include folders you require to your include path, as a comma-separated list.

UltraLite code generation

The following set of instructions describes how to add UltraLite code generation to your development tool.

♦ To add UltraLite code generation into a dependency-based development environment:

1	Add a dummy file to your development project.

Add a file named, for example, uldatabase.ulg, in the same directory as your generated files.

2	Set the build rules for this file to be the UltraLite generator command line.

In Visual C++, use a command of the following form (which should be all on one line):

"%asany7%\win32\ulgen.exe" -q -c "connection-string" $(InputName) $(InputName).c

where asany7 is an environment variable that points to your SQL Anywhere installation directory, connection-string is a connection to your reference database, and InputName is the UltraLite project name, and should match the root of the text file name. The output is $(InputName).c.

3	Set the dummy file to depend on the output files from the preprocessor.

In Visual C++, click Dependencies on the custom build page, and enter the names of the generated .c files produced by the SQL preprocessor.

This instructs Visual C++ to run the UltraLite generator after all the necessary embedded SQL files have been preprocessed.

4	Compile your dummy file to generate the .c file that implements the UltraLite database.

5	Add the generated UltraLite database file to your project and change its C/C++ settings.

6	Add the UltraLite imports library to your object/libraries modules list.

In Visual C++, go to the project settings, choose the Link tab, and add the following to the Object/libraries module list for Windows 32-bit development.

$(asany7)\ultralite\win32\386\lib\ulimp.lib

For other targets, choose the appropriate import library.


Pre-processing your embedded SQL files
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 9.  Developing Embedded SQL Applications

 Pre-processing your embedded SQL files

The SQL preprocessor (sqlpp.exe) carries out two functions in an UltraLite development project:

•	It preprocesses the embedded SQL files, producing C files to be compiled into your application.

•	It adds the SQL statements to the reference database, for use by the UltraLite generator. You must use the -c switch to specify connection parameters that give sqlpp access to the reference database.

  For information on adding SQL statements to a reference database, see Adding SQL statements to an UltraLite project.

Caution
sqlpp overwrites the output file without regard to its contents. Ensure that the output file name does not match the name of any of your source files. By default, sqlpp constructs the output file name by changing the suffix of your source file to .c. When in doubt, specify the output file name explicitly, following the name of the source file.

 Preprocessing projects with a single embedded SQL source file

 Preprocessing projects with more than one embedded SQL file


Preprocessing projects with a single embedded SQL source file
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 9.  Developing Embedded SQL Applications

        Pre-processing your embedded SQL files

 Preprocessing projects with a single embedded SQL source file

If all your embedded SQL code is contained in one source file, you may use the following technique to pre-process this code using the SQL preprocessor and generate the supplementary code in a single step. In this case, the preprocessor automatically runs the UltraLite generator, which writes additional code that describes your database schema and implements the SQL used in your application.

♦ To preprocess an embedded SQL source file (one file only):

1	Specify no project name when you run sqlpp, the SQL preprocessor. When invoked without a project name, the preprocessor automatically runs the UltraLite generator and appends the additional C/C++ code, which implements your application database. A single C/C++ source file is generated.

2	Do not run the UltraLite generator explicitly.

Example

•	Your application contains only one embedded SQL source file, called store.sqc. You can process this file using the following command. Do not specify a project name. This command causes the SQL preprocessor to write the file store.c.

sqlpp -c "uid=dba;pwd=sql" store.sqc

In addition, the preprocessor automatically runs the UltraLite analyzer, which generates more C/C++ code to implement your application database. This code is automatically appended to the file store.c.

  If the analyzer cannot be invoked, an error results. For more information, see Error on starting the analyzer.

  For a list of the parameters to sqlpp, see The SQL preprocessor.


Preprocessing projects with more than one embedded SQL file
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 9.  Developing Embedded SQL Applications

        Pre-processing your embedded SQL files

 Preprocessing projects with more than one embedded SQL file

If you have more than one embedded SQL source file, you must run the UltraLite generator separately.

You must specify an UltraLite project on the sqlpp command line so that the SQL statements in the files are grouped together in the same project in the reference database.

  For information on projects, see Creating an UltraLite project.

♦ To preprocess an embedded SQL source file (more than one file):

1	Preprocess each embedded SQL source file.

Use the -p switch to specify a project name when you run the SQL preprocessor. Use the same project name when you preprocess each embedded SQL file in your project.

2	Run the UltraLite generator to create the supplementary C/C++ code.

  For more information on the generator, see Generating the UltraLite data access code.

By default, the UltraLite generator, ulgen, writes to the file project-name.c. Choose a project name not already assigned to another C or embedded SQL source file, so that an existing file will not be overwritten.

Example

•	Suppose that your project contains two embedded SQL source files, called store.sqc and display.sqc. You could give your project the name salesdb and  process these two commands using the following commands. (Each command should be entered on a single line.)

sqlpp -c "uid=dba;pwd=sql" -p salesdb store.sqc

sqlpp -c "uid=dba;pwd=sql" -p salesdb display.sqc

These two commands generate the files store.c and display.c, respectively. In addition, they store information in the reference database for the UltraLite analyzer.

  For detailed information about the SQL preprocessor, see The SQL preprocessor.


CHAPTER 10.  The Embedded SQL Interface
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

 CHAPTER 10.  The Embedded SQL Interface

About this chapter

UltraLite applications can interact with their database through a static embedded SQL programming interface, which is a subset of the embedded SQL interface available in Adaptive Server Anywhere. This chapter introduces the UltraLite embedded SQL interface and describes its language and functions.

  For information about the full Adaptive Server Anywhere embedded SQL interface, see The Embedded SQL Interface.

 Introduction

 Using host variables

 Indicator variables

 Fetching data

 The SQL Communication Area

 Configuring file-based persistent storage

 Library functions reference


Introduction
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

 Introduction

Embedded SQL lets you insert standard SQL statements into either C or C++ code. A SQL preprocessor translates these SQL statements into C and C++ compatible source code. You compile each preprocessed file as you would an ordinary C or C++ source file.

The preprocessor generates source code that makes calls to library functions. These functions are defined in a library or imports library. You include one of these libraries when you link your program.

The following is a very simple embedded SQL program. It updates the surname of employee 195 and commits the change.

#include <stdio.h>

EXEC SQL INCLUDE SQLCA;

main( )

{

db_init( &sqlca );

EXEC SQL WHENEVER SQLERROR GOTO error;

EXEC SQL CONNECT "DBA" IDENTIFIED BY "SQL";

EXEC SQL UPDATE employee

SET emp_lname = 'Plankton'

WHERE emp_id = 195;

EXEC SQL COMMIT;

EXEC SQL DISCONNECT;

db_fini( &sqlca );

return( 0 );

error:

printf( "update unsuccessful: sqlcode = %ld\n",

sqlca.sqlcode );

return( -1 );

}

Although too simple to be useful, this example demonstrates the following aspects common to all embedded SQL applications:

•	Each SQL statement is prefixed with the keywords EXEC SQL.

•	Each SQL statement ends with a semicolon.

•	Some embedded SQL statements are not found in standard SQL. The INCLUDE SQLCA statement is one example.

•	Embedded SQL provides library functions to perform some specific tasks. The functions db_init and db_fini are examples.

Before working with data

The above example demonstrates the necessary initialization statements. You must include these before working with the data in any database.

1	You must define the SQL communications area, sqlca, using the following command.

EXEC SQL INCLUDE SQLCA;

This definition must be your first embedded SQL statement, so a natural place for it is the end of your include list.

If you have multiple .sqc files in your application, each file must have this line.

2	Your first executable database action must be a call to an embedded SQL library function named db_init. This function initializes the UltraLite runtime library. Only embedded SQL definition statements can be executed before this call.

  For more information, see db_init library function.

3	You must use the CONNECT statement to connect to your database.

Preparing to exit

This example also demonstrates the sequence of calls you must make when preparing to exit.

1	Commit or rollback any outstanding changes.

2	Disconnect from the database.

3	End your SQL work with a call to a library function named db_fini.

If you leave changes to the database uncommitted when you exit, any uncommitted operations are automatically rolled back.

Error handling

There is virtually no interaction between the SQL and C code in this example. The C code only controls flow. The WHENEVER statement is used for error checking. The error action, GOTO in this example, is executed after any SQL statement causes an error.

 Structure of embedded SQL programs


Structure of embedded SQL programs
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Introduction

 Structure of embedded SQL programs

All embedded SQL statements start with the words EXEC SQL and end with a semicolon (;). Normal C-language comments are allowed in the middle of embedded SQL statements.

Every C program using embedded SQL must contain the following statement before any other embedded SQL statements in the source file.

EXEC SQL INCLUDE SQLCA;

The first embedded SQL executable statement executed in any program must be a CONNECT statement. The CONNECT statement establishes a connection with the database and specifies the user ID that is used for authorizing all statements executed during the connection.

Some embedded SQL commands do not generate any executable C code, or do not involve communication with the database. Only these commands are allowed before the CONNECT statement. Most notable are the INCLUDE statement and the WHENEVER statement for specifying error processing.

User IDs and database authorization

The CONNECT statement specifies a user name and password to be used for authorization of all SQL statements against the reference database. The UltraLite runtime does not have any permissions checking. The user name and password are effectively ignored in the UltraLite application.

  For more information on user IDs and UltraLite, see User IDs in UltraLite databases.


Using host variables
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

 Using host variables

Host variables are C variables that are identified to the SQL preprocessor. You use host variables to send values to the database server or receive values from the database server.

 Declaring host variables

 Data types in embedded SQL

 Host variable usage

 The scope of host variables

 Using expressions as host variables

 Using host variables in C++


Declaring host variables
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Using host variables

 Declaring host variables

You can define host variables by placing them within a declaration section. Host variables are declared by surrounding the normal C variable declarations with BEGIN DECLARE SECTION and END DECLARE SECTION statements.

Whenever you use a host variable in a SQL statement, you must prefix the variable name with a colon (:) so that the SQL preprocessor can distinguish it from other identifiers allowed in the statement.

You can use host variables in place of value constants in any SQL statement. When the database server executes the command, the value of the host variable is read from or written to each host variable. Host variables cannot be used in place of table or column names.

The SQL preprocessor does not scan C language code except inside a declaration section. Initializers for variables are allowed inside a declaration section, while typedef types and structures are not permitted.

Example

•	The following sample code illustrates the use of host variables with an INSERT command. The variables are filled in by the program and then inserted into the database:

/* Declare fields for personal data. */

EXEC SQL BEGIN DECLARE SECTION;

long employee_number = 0;

char employee_name[50];

char employee_initials[8];

char employee_phone[15];

EXEC SQL END DECLARE SECTION;

/* Fill variables with appropriate values. */

/* Insert a row in the database. */

EXEC SQL INSERT INTO Employee

VALUES (:employee_number, :employee_name,

:employee_initials, :employee_phone );


Data types in embedded SQL
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Using host variables

 Data types in embedded SQL

To transfer information between a program and the database server, every piece of data must have a data type. You can create a host variable with any one of the supported types.

Only a limited number of C data types are supported as host variables. Also, certain host variable types do not have a corresponding C type.

Macros defined in the sqlca.h header file can be used to declare a host variable of type VARCHAR, FIXCHAR, BINARY, DECIMAL, or SQLDATETIME. These macros are used as follows:

EXEC SQL BEGIN DECLARE SECTION;

DECL_VARCHAR( 10 ) v_varchar;

DECL_FIXCHAR( 10 ) v_fixchar;

DECL_BINARY( 4000 ) v_binary;

DECL_DECIMAL( 10, 2 ) v_packed_decimal;

DECL_DATETIME v_datetime;

EXEC SQL END DECLARE SECTION;

The preprocessor recognizes these macros within a declaration section and treats the variable as the appropriate type.

The following data types are supported by the embedded SQL programming interface:

•	16-bit signed integer.

short int i;

unsigned short int i;

•	32-bit signed integer.

long int l;

unsigned long int l;

•	4-byte floating point number.

float f;

•	8-byte floating point number.

double d;

•	Packed decimal number.

DECL_DECIMAL(p,s)

typedef struct TYPE_DECIMAL {

char array[1];

} TYPE_DECIMAL;

•	NULL-terminated blank-padded character string.

char a[n];   /* n > 1 */

char *a;     /* n = 2049 */

Because the C-language array must also hold the NULL terminator, a char a[n] data type maps to a CHAR(n - 1) SQL data type, which can hold n - 1 characters.

Pointers to char, WCHAR, TCHAR
The SQL preprocessor assumes that a pointer to char points to a character array of size 2049 bytes and that this array can safely hold 2048 characters, plus the NULL terminator. In other words, a char* data type maps to a CHAR(2048) SQL type. If that is not the case, your application may corrupt memory. If you are using a 16-bit compiler, requiring 2049 bytes can make the program stack overflow. Instead, use a declared array, even as a parameter to a function, to let the SQL preprocessor know the size of the array. WCHAR and TCHAR behave similarly to char.

•	NULL terminated UNICODE or wide character string.

Each character occupies two bytes of space and so may contain UNICODE characters.

WCHAR a[n];   /* n > 1 */

•	NULL terminated system-dependent character string.

A TCHAR is equivalent to a WCHAR for systems that use UNICODE (for example, Windows CE) for their character set; otherwise, a TCHAR is equivalent to a char. The TCHAR data type is designed to support character strings in either kind of system automatically.

TCHAR a[n];   /* n > 1 */

•	Fixed-length blank padded character string.

char a;              /* n  = 1 */

DECL_FIXCHAR(n) a;   /* n >= 1 */

•	Variable-length character string with a two-byte length field.

When supplying information to the database server, you must set the length field. When fetching information from the database server, the server sets the length field (not padded).

DECL_VARCHAR(n) a;   /* n >= 1 */

typedef struct VARCHAR {

unsigned short int len;

TCHAR array[1];

} VARCHAR;

•	Variable-length binary data with a two-byte length field.

When supplying information to the database server, you must set the length field. When fetching information from the database server, the server sets the length field.

DECL_BINARY(n) a;   /* n >= 1 */

typedef struct BINARY {

unsigned short int len;

unsigned char array[1];

} BINARY;

•	SQLDATETIME structure with fields for each part of a timestamp.

DECL_DATETIME a;

typedef struct SQLDATETIME {

unsigned short year;  /* e.g., 1992 */

unsigned char month;  /* 0-11 */

unsigned char day_of_week;  /* 0-6, 0 = Sunday */

unsigned short day_of_year;  /* 0-365 */

unsigned char day;  /* 1-31 */

unsigned char hour;  /* 0-23 */

unsigned char minute;  /* 0-59 */

unsigned char second;  /* 0-59 */

unsigned long microsecond;  /* 0-999999 */

} SQLDATETIME;

The SQLDATETIME structure can be used to retrieve fields of DATE, TIME, and TIMESTAMP type (or anything that can be converted to one of these). Often, applications have their own formats and date manipulation code. Fetching data in this structure makes it easier for a programmer to manipulate this data. Note that DATE, TIME and TIMESTAMP fields can also be fetched and updated with any character type.

If you use a SQLDATETIME structure to enter a date, time, or timestamp into the database via, the day_of_year and day_of_week members are ignored.

  For more information, see the DATE_FORMAT, TIME_FORMAT, TIMESTAMP_FORMAT, and DATE_ORDER database options in Database Options. While these options cannot be set during execution of an UltraLite program, their values are identical to the settings in the reference database used to generate the program.

The structures are defined in the sqlca.h file. The VARCHAR, BINARY, and TYPE_DECIMAL types contain a one-character array and are thus not useful for declaring host variables, but they are useful for allocating variables dynamically or typecasting other variables.

DATE and TIME database types

There are no corresponding embedded SQL interface data types for the various DATE and TIME database types. These database types are fetched and updated either using the SQLDATETIME structure or using character strings.

There are no embedded SQL interface data types for LONG VARCHAR and LONG BINARY database types.


Host variable usage
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Using host variables

 Host variable usage

Host variables can be used in the following circumstances:

•	In a SELECT, INSERT, UPDATE, or DELETE statement in any place where a number or string constant is allowed.

•	In the INTO clause of a SELECT or FETCH statement.

•	In CONNECT, DISCONNECT, and SET CONNECT statements, a host variable can be used in place of a user ID, password, connection name, or database environment name.

Host variables can never be used in place of a table name or a column name.


The scope of host variables
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Using host variables

 The scope of host variables

A host-variable declaration section can appear anywhere that C variables can normally be declared, including the parameter declaration section of a C function. The C variables have their normal scope (available within the block in which they are defined). However, since the SQL preprocessor does not scan C code, it does not respect C blocks.

The preprocessor assumes all host variables are global

As far as the SQL preprocessor is concerned, host variables are globally known in the source module following their declaration. Two host variables cannot have the same name. The only exception to this rule is that two host variables can have the same name if they have identical types (including any necessary lengths).

The best practice is to give each host variable a unique name.

Examples

•	Because the SQL preprocessor can not parse C code, it assumes that all host variables, no matter where they are declared, are known globally following their declaration.

// Example demonstrating poor coding

EXEC SQL BEGIN DECLARE SECTION;

long emp_id;

EXEC SQL END DECLARE SECTION;

long getManagerID( void )

{

EXEC SQL BEGIN DECLARE SECTION;

long manager_id = 0;

EXEC SQL END DECLARE SECTION;

EXEC SQL	SELECT manager_id

INTO :manager_id

FROM employee

WHERE emp_number = :emp_id;

return( manager_number );

}

void setManagerID( long manager_id )

{

EXEC SQL	UPDATE employee

SET manager_number = :manager_id

WHERE emp_number = :emp_id;

}

Although it works, the above code is confusing because the SQL preprocessor relies on the declaration inside getManagerID when processing the statement within setManagerID. You should rewrite this code as follows.

// Rewritten example

#if 0

// Declarations for the SQL preprocessor

EXEC SQL BEGIN DECLARE SECTION;

long emp_id;

long manager_id;

EXEC SQL END DECLARE SECTION;

#endif

long getManagerID( long emp_id )

{

long manager_id = 0;

EXEC SQL	SELECT manager_id

INTO :manager_id

FROM employee

WHERE emp_number = :emp_id;

return( manager_number );

}

void setManagerID( long emp_id, long manager_id )

{

EXEC SQL	UPDATE employee

SET manager_number = :manager_id

WHERE emp_number = :emp_id;

}

The SQL preprocessor sees the declaration of the host variables contained within the #if directive because it ignores these directives. On the other hand, it ignores the declarations within the procedures because they are not inside a DECLARE SECTION. Conversely, the C compiler ignores the declarations within the #if directive and uses those within the procedures.

These declarations work only because variables having the same name are declared to have exactly the same type.


Using expressions as host variables
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Using host variables

 Using expressions as host variables

Because host variables must be simple names, the SQL preprocessor does not recognize pointer or reference expressions. For example, the following statement does not work because the SQL preprocessor does not understand the dot operator. The same syntax has a different meaning in SQL.

// Incorrect statement:

EXEC SQL SELECT LAST sales_id INTO :mystruct.mymember;

Although the above syntax is not allowed, you can still use an expression with the following technique:

•	Wrap the SQL declaration section in an #if 0 preprocessor directive. The SQL preprocessor will read the declarations and use them for the rest of the module because it ignores preprocessor directives.

•	Define a macro with the same name as the host variable. Since the SQL declaration section is not seen by the C compiler because of the #if directive, no conflict will arise. Ensure that the macro evaluates to the same type host variable.

The following code demonstrates this technique to hide the host_value expression from the SQL preprocessor.

EXEC SQL INCLUDE SQLCA;

#include <sqlerr.h>

#include <stdio.h>

typedef struct my_struct {

long	host_field;

} my_struct;

#if 0

// Because it ignores #if preprocessing directives,

// SQLPP reads the following declaration.

EXEC SQL BEGIN DECLARE SECTION;

long    host_value;

EXEC SQL END DECLARE SECTION;

#endif

// Make C/C++ recognize the 'host_value' identifier

// as a macro that expands to a struct field.

#define host_value my_s.host_field

Since the SQLPP processor ignores directives for conditional compilation, host_value is treated as a long host variable and will emit that name when it is subsequently used as a host variable. The C/C++ compiler processes the emitted file and will substitute my_s.host_field for all such uses of that name.

With the above declarations in place, you can proceed to access host_field as follows.

void main( void )

{

my_struct	my_s;

db_init( &sqlca );

EXEC SQL CONNECT "DBA" IDENTIFIED BY "SQL";

EXEC SQL DECLARE my_table_cursor CURSOR FOR

SELECT int_col FROM my_table order by int_col;

EXEC SQL OPEN my_table_cursor;

for( ; ; ) {

// :host_value references my_s.host_field

EXEC SQL FETCH NEXT AllRows INTO :host_value;

if( SQLCODE == SQLE_NOTFOUND ) {

break;

}

printf( "%ld\n", my_s.host_field );

}

EXEC SQL CLOSE my_table_cursor;

EXEC SQL DISCONNECT;

db_fini( &sqlca );

}

You can use the same technique to use other lvalues as host variables.

•	pointer indirections

*ptr

p_struct->ptr

(*pp_struct)->ptr

•	array refererences

my_array[ i ]

•	arbitrarily complex lvalues


Using host variables in C++
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Using host variables

 Using host variables in C++

A similar situation arises when using host variables within C++ classes. It is frequently convenient to declare your class in a separate header file. This header file might contain, for example, the following declaration of my_class.

typedef	short	a_bool;

#define	TRUE	((a_bool)(1==1))

#define	FALSE	((a_bool)(0==1))

public class {

long  host_member;

my_class();	// Constructor

~my_class();	// Destructor

a_bool FetchNextRow( void );

// Fetch the next row into host_member

} my_class;

In this example, each method is implemented in an embedded SQL source file. Only simple variables can be used as host variables. The technique introduced in the preceding section can be used to access a data member of a class.

EXEC SQL INCLUDE SQLCA;

#include "my_class.hpp"

#if 0

// Because it ignores #if preprocessing directives,

// SQLPP reads the following declaration.

EXEC SQL BEGIN DECLARE SECTION;

long	this_host_member;

EXEC SQL END DECLARE SECTION;

#endif

// Macro used by the C++ compiler only.

#define this_host_member this->host_member

my_class::my_class()

{

EXEC SQL DECLARE my_table_cursor CURSOR FOR

SELECT int_col FROM my_table order by int_col;

EXEC SQL OPEN my_table_cursor;

}

my_class::~my_class()

{

EXEC SQL CLOSE my_table_cursor;

}

a_bool my_class::FetchNextRow( void )

{

// :this_host_member references this->host_member

EXEC SQL FETCH NEXT AllRows INTO :this_host_member;

return( SQLCODE != SQLE_NOTFOUND );

}

void main( void )

{

db_init( &sqlca );

EXEC SQL CONNECT "DBA" IDENTIFIED BY "SQL";

{

my_class mc;  // Created after connecting.

while( mc.FetchNextRow() ) {

printf( "%ld\n", mc.host_member );

}

}

EXEC SQL DISCONNECT;

db_fini( &sqlca );

}

The above example declares this_host_member for the SQL preprocessor, but the macro causes C++ to convert it to this->host_member. The preprocessor would otherwise not know the type of this variable. Many C/C++ compilers do not tolerate duplicate declarations. The #if directive hides the second declaration from the compiler, but leaves it visible to the SQL preprocessor.

While multiple declarations can be useful, you must ensure that each declaration assigns the same variable name to the same type. The preprocessor assumes that each host variable is globally known following its declaration because it can not fully parse the C language.


Indicator variables
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

 Indicator variables

An indicator variable is a C variable that holds supplementary information about a particular host variable. You can use a host variable when fetching or putting data. Use indicator variables to handle NULL values.

An indicator variable is a host variable of type short int. To detect or specify a NULL value, place the indicator variable immediately following a regular host variable in a SQL statement.

Example

•	For example, in the following INSERT statement, :ind_phone is an indicator variable.

EXEC SQL INSERT INTO Employee

VALUES (:employee_number, :employee_name,

:employee_initials, :employee_phone:ind_phone );

Indicator variable values

The following table provides a summary of indicator variable usage.

Indicator Value	Supplying Value to database	Receiving value from database
0	Host variable value	Fetched a non-NULL value.
-1	NULL value	Fetched a NULL value
 Using indicator variables to handle NULL


Using indicator variables to handle NULL
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Indicator variables

 Using indicator variables to handle NULL

Do not confuse the SQL concept of NULL with the C-language constant of the same name. In the SQL language, NULL represents either an unknown attribute or inapplicable information. The C-language constant represents a pointer value which does not point to a memory location.

When NULL is used in the Adaptive Server Anywhere documentation, it refers to the SQL database meaning given above. The C language constant is referred to as the null pointer (lower case).

NULL is not the same as any value of the column's defined type. Thus, in order to pass NULL values to the database or receive NULL results back, you require something beyond regular host variables. Indicator variables serve this purpose.

Using indicator variables when inserting NULL

An INSERT statement can include an indicator variable as follows:

EXEC SQL BEGIN DECLARE SECTION;

short int employee_number;

char employee_name[50];

char employee_initials[6];

char employee_phone[15];

short int ind_phone;

EXEC SQL END DECLARE SECTION;

/* set values of empnum, empname,

initials, and homephone */

if( /* phone number is known */ ) {

ind_phone =  0;

} else {

ind_phone = -1;  /* NULL */

}

EXEC SQL INSERT INTO Employee

VALUES (:employee_number, :employee_name,

:employee_initials, :employee_phone:ind_phone );

If the indicator variable has a value of -1, a NULL is written. If it has a value of 0, the actual value of employee_phone is written.

Using indicator variables when fetching NULL

Indicator variables are also used when receiving data from the database. They are used to indicate that a NULL value was fetched (indicator is negative). If a NULL value is fetched from the database and an indicator variable is not supplied, the SQLE_NO_INDICATOR error is generated.

 Errors and warnings are returned in the SQLCA structure, as described in The SQL Communication Area.


Fetching data
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

 Fetching data

Fetching data in embedded SQL is done using the SELECT statement. There are two cases:

1	The SELECT statement returns at most one row.

2	The SELECT statement may return multiple rows.

 Fetching one row

 Fetching multiple rows

 Optimizing query operation


Fetching one row
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Fetching data

 Fetching one row

A single row query retrieves at most one row from the database. A single-row query SELECT statement may have an INTO clause following the select list and before the FROM clause. The INTO clause contains a list of host variables to receive the value for each select list item. There must be the same number of host variables as there are select list items. The host variables may be accompanied by indicator variables to indicate NULL results.

When the SELECT statement is executed, the database server retrieves the results and places them in the host variables.

•	If the query selects more than one row, the database server returns the SQLE_TOO_MANY_RECORDS error.

•	If the query selects no rows, the SQLE_NOTFOUND warning is returned.

 Errors and warnings are returned in the SQLCA structure, as described in The SQL Communication Area.

Example

For example, the following code fragment returns 1 if a row from the employee table is successfully fetched, 0 if the row doesn't exist, and -1 if an error occurs.

EXEC SQL BEGIN DECLARE SECTION;

long int    emp_id;

char        name[41];

char        sex;

char        birthdate[15];

short int   ind_birthdate;

EXEC SQL END DECLARE SECTION;

int find_employee( long employee )

{

emp_id = employee;

EXEC SQL	SELECT emp_fname || ' ' || emp_lname,

sex, birth_date

INTO :name, :sex, birthdate:ind_birthdate

FROM "DBA".employee

WHERE emp_id = :emp_id;

if( SQLCODE == SQLE_NOTFOUND ) {

return( 0 );   /* employee not found */

} else if( SQLCODE < 0 ) {

return( -1 );  /* error */

} else {

return( 1 );   /* found */

}

}


Fetching multiple rows
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Fetching data

 Fetching multiple rows

You use a cursor to retrieve rows from a query that has multiple rows in its result set. A cursor is a handle or an identifier for the SQL query result set and a position within that result set.

  For an introduction to cursors, see Working with cursors.

♦ To manage a cursor in embedded SQL

1	Declare a cursor for a particular SELECT statement, using the DECLARE statement.

2	Open the cursor using the OPEN statement.

3	Retrieve rows from the cursor one at a time using the FETCH statement.

•	Fetch rows until the SQLE_NOTFOUND warning is returned.

 Error and warning codes are returned in the variable SQLCODE, defined in the SQL communications area structure.

4	Close the cursor, using the CLOSE statement.

Cursors in UltraLite applications are always opened using the WITH HOLD option. They are never closed automatically. You must close each cursor explicitly using the CLOSE statement.

The following is a simple example of cursor usage:

void print_employees( void )

{

int status;

EXEC SQL BEGIN DECLARE SECTION;

char name[50];

char sex;

char birthdate[15];

short int ind_birthdate;

EXEC SQL END DECLARE SECTION;

/* 1. Declare the cursor. */

EXEC SQL DECLARE C1 CURSOR FOR

SELECT emp_fname || ' ' || emp_lname,

sex, birth_date

FROM "DBA".employee

ORDER BY emp_fname, emp_lname;

/* 2. Open the cursor. */

EXEC SQL OPEN C1;

/* 3. Fetch each row from the cursor. */

for( ;; ) {

EXEC SQL FETCH C1 INTO :name, :sex,

:birthdate:ind_birthdate;

if( SQLCODE == SQLE_NOTFOUND ) {

break;  /* no more rows */

} else if( SQLCODE < 0 ) {

break;  /* the FETCH caused an error */

}

if( ind_birthdate < 0 ) {

strcpy( birthdate, "UNKNOWN" );

}

printf( "Name: %s Sex: %c Birthdate:

%s\n",name, sex, birthdate );

}

/* 4. Close the cursor. */

EXEC SQL CLOSE C1;

}

  For details of the FETCH statement, see FETCH statement.

Cursor positioning

A cursor is positioned in one of three places:

•	On a row

•	Before the first row

•	After the last row

Order of the rows in a cursor

You control the order of rows in a cursor by including an ORDER BY clause in the SELECT statements that defines that cursor. If you omit this clause, the order of the rows is unpredictable.

If you don't explicitly define an order, your only guarantee is that fetching repeatedly will return each row in the result set once and only once before SQLE_NOTFOUND is returned.

Order of rows in a cursor
  If the cursor must have a specific order, include an ORDER BY clause in the SELECT statement in the cursor definition. Without this clause, the ordering is unpredictable and can vary from one time to the next.

Repositioning a cursor

When you open a cursor, it is positioned before the first row. The FETCH statement automatically advances the cursor position. An attempt to FETCH beyond the last row results in an SQLE_NOTFOUND error, which can be used as a convenient signal to complete sequential processing of the rows.

You can also reposition the cursor to an absolute position relative to the start or the end of the query results, or move it relative to the current cursor position. There are special positioned versions of the UPDATE and DELETE statements that can be used to update or delete the row at the current position of the cursor. If the cursor is positioned before the first row or after the last row, an SQLE_NOTFOUND error is returned.

To avoid unpredictable results when using explicit positioning, you can include an ORDER BY clause in the SELECT statement that defines the cursor.

You can use the PUT statement to insert a row into a cursor.

Cursor positioning after updates

After updating any information that is being accessed by an open cursor, it is best to fetch and display the rows again. If the cursor is being used to display a single row, FETCH RELATIVE 0 will re-fetch the current row. When the current row has been deleted, the next row will be fetched from the cursor (or SQLE_NOTFOUND is returned if there are no more rows).

When a temporary table is used for the cursor, inserted rows in the underlying tables do not appear at all until that cursor is closed and reopened. It is difficult for most programmers to detect whether or not a temporary table is involved in a SELECT statement without examining the code generated by the SQL preprocessor or by becoming knowledgeable about the conditions under which temporary tables are used. Temporary tables can usually be avoided by having an index on the columns used in the ORDER BY clause.

  For more information about temporary tables, see Temporary tables used in query processing.

Inserts, updates and deletes to non-temporary tables may affect the cursor positioning. Because UltraLite materializes cursor rows one at a time (when temporary tables are not used), the data from a freshly inserted row (or the absence of data from a freshly deleted row) may affect subsequent FETCH operations. In the simple case where (parts of) rows are being selected from a single table, an inserted or updated row will appear in the result set for the cursor when it satisfies the selection criteria of the SELECT statement. Similarly, a freshly deleted row that previously contributed to the result set will no longer be within it.


Optimizing query operation
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Fetching data

 Optimizing query operation

Although some aspects of UltraLite applications are optimized automatically, you can improve the performance of your applications using the following techniques.

•	add an index    If you frequently retrieve information in a particular order, consider adding an index to your reference database. Primary keys are automatically indexed, but other columns are not. Particularly on slow devices, an index can improve performance dramatically.

•	add representative data    The Adaptive Server Anywhere optimizer automatically optimizes the performance of your queries. It chooses access plans using the information present in your reference database. To improve application performance, fill your reference database with data that is representative in size and distribution of the data you expect your application will hold once it is deployed.


The SQL Communication Area
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

 The SQL Communication Area

The SQL Communication Area (SQLCA) is an area of memory that is used for communicating statistics and errors from the application to the database and back to the application. The SQLCA is used as a handle for the application-to-database communication link. It is passed explicitly to all database library functions that communicate with the database. It is implicitly passed in all embedded SQL statements.

A global SQLCA variable is defined in the generated code. The preprocessor generates an external reference for the global SQLCA variable. The external reference is named sqlca and is of type SQLCA. The actual global variable is declared in the imports library.

The SQLCA type is defined by the sqlca.h header file, which is located in the h subdirectory of your installation directory.

SQLCA provides error codes

You reference the SQLCA to test for a particular error code. The sqlcode field contains an error code when a database request causes an error (see below). Some C macros are defined for referencing the sqlcode field and some other fields.

 Fields in the SQLCA

 SQLCA management for multi-threaded or reentrant code

 Using multiple SQLCAs


Fields in the SQLCA
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        The SQL Communication Area

 Fields in the SQLCA

The fields in the SQLCA have the following meanings:

•	sqlcaid    An 8-byte character field that contains the string SQLCA as an identification of the SQLCA structure. This field helps in debugging when you are looking at memory contents.

•	sqlcabc    A long integer that contains the length of the SQLCA structure (136 bytes).

•	sqlcode    A long integer that specifies the error code when the database detects an error on a request. Definitions for the error codes can be found in the header file sqlerr.h. The error code is 0 (zero) for a successful operation, positive for a warning and negative for an error.

You can access this field directly using the SQLCODE macro.

  For a list of error codes, see Database Error Messages.

•	sqlerrml    The length of the information in the sqlerrmc field.

UltraLite applications do not use this field.

•	sqlerrmc    May contain one or more character strings to be inserted into an error message. Some error messages contain a placeholder string (%1) which is replaced with the text in this field.

UltraLite applications do not use this field.

•	sqlerrp    Reserved.

•	sqlerrd    A utility array of long integers.

•	sqlwarn    Reserved.

UltraLite applications do not use this field.

•	sqlstate    The SQLSTATE status value.

UltraLite applications do not use this field.


SQLCA management for multi-threaded or reentrant code
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        The SQL Communication Area

 SQLCA management for multi-threaded or reentrant code

UltraLite applications should not be created where multiple threads access the database simultaneously, as multi-threading is not supported.


Using multiple SQLCAs
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        The SQL Communication Area

 Using multiple SQLCAs

♦ To manage multiple SQLCAs in your application:

1	1	Each SQLCA used in your program must be initialized with a call to db_init and cleaned up at the end with a call to db_fini.

  For more information, see db_init library function.

2	2	The embedded SQL statement SET SQLCA is used to tell the SQL preprocessor to use a different SQLCA for database requests. Usually, a statement such as the following:

EXEC SQL SET SQLCA 'task_data->sqlca';

is used at the top of your program or in a header file to set the SQLCA reference to point at task specific data. This statement does not generate any code and thus has no performance impact. It changes the state within the preprocessor so that any reference to the SQLCA will use the given string.

  For information about creating SQLCAs, see SET SQLCA statement.

 Connection management with multiple SQLCAs


Connection management with multiple SQLCAs
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        The SQL Communication Area

          Using multiple SQLCAs

 Connection management with multiple SQLCAs

You do not need to use multiple SQLCAs to have more than one connection to a single database.

Each SQLCA can have one unnamed connection. Each SQLCA has an active or current connection. All operations on a given database connection must use the same SQLCA that was used when the connection was established.

  For more information, see SET CONNECTION statement.


Configuring file-based persistent storage
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

 Configuring file-based persistent storage

You can specify parameters to control the configuration of the UltraLite persistent storage mechanism.

On some platforms, the UltraLite database is stored in the file system. For a list of these platforms, see Database storage mechanism. For those platforms, you can use the UL_STORE_PARMS macro to configure the file name, and also the amount of memory used as a cache by the UltraLite database engine. The macro is placed in the header of your application source code so that it is visible to all db_init() calls.

The available parameters

The following parameters are available

•	cache_size    Defines the size of the cache. You can specify the size in units of bytes. Use the suffix k or K to indicate units of kilobytes and use the suffix M or m to indicate megabytes. For example, the following string sets the cache size to 128 Kb.

#define UL_STORE_PARMS UL_TEXT("cache_size=128k")

The default cache size for 16-bit architectures is 8 K. The default cache size for 32-bit architectures is 64 K. The minimum cache size is 4 K.

•	file_name    Defines the full pathname of the file-based persistent store. No substitutions are performed on this value. In addition, you must ensure that this directory exists when db_init is called. The directory is not created automatically.

#define UL_STORE_PARMS \	UL_TEXT("file_name=\\uldb\\my own name.udb" )

Under Windows CE, the filename must include the absolute path. Under Windows NT, Windows 95/98, DOS, and VxWorks, the path may either be absolute, or relative to the current directory.

Be sure to escape any backslash characters in the path.

•	reserve_size    Reserves file system space for storage of UltraLite persistent data.

The reserve_size parameter allows you to pre-allocate the file system space required for your UltraLite database without actually inserting any data. Reserving file system space can improve performance slightly and also prevent out of memory failures. By default, the persistent storage file only grows when required as the application updates the database.

Note that reserve_size reserves file system space, which includes the metadata in the persistent store file, and not just the raw data. The metadata overhead as well as data compression must be considered when deriving the required file system space from the amount of database data. Running the database with test data and observing the persistent store file size is recommended.

The reserve_size parameter reserves space by growing the persistent store file to the given reserve size on startup, regardless of whether the file previously existed. The file is never truncated.

Use the reserve_size parameter to pre-allocate space as follows:

#define UL_STORE_PARMS	 UL_TEXT( "reserve_size=2m" )

This example ensures that the persistent store file is at least 2 Mb upon startup.

Setting the storage parameters

To specify storage parameters, define the UL_STORE_PARMS macro in the header of your application source code so that it is visible to all db_init() calls. For example, the following statements set the cache size to 128 kb.

#undef  UL_STORE_PARMS

#define UL_STORE_PARMS  UL_TEXT("cache_size=128k")

. . .

db_init( &sqlca );

If you set the value using a constant string, as in this example, always enclose the parameter using the UL_TEXT macro to ensure that the character coding of the parameter is interpreted correctly.

Syntax

Set values within the text string using the syntax "parameter=value". To set more than one parameter, separate the clauses with semicolons; for example, "parameter=value;parameter=value;...". Duplicate semicolons are ignored, as are semicolons at either the start or end of the string. Spaces between the equals sign and the following semicolon are considered to be part of the value. In fact, all spaces are significant, except spaces at the start of the string and any spaces that immediately follow a semicolon.

Setting values programmatically

You can set UL_STORE_PARMS to a string, then set the value of that string programmatically before calling db_init, as in the following example. Note the use of the UL_TEXT macro and the _stprintf function to achieve proper character encoding.

char store_parms[32];

#undef  UL_STORE_PARMS

#define UL_STORE_PARMS  store_parms

. . .

/* Set cache_size to the correct number of bytes. */

. . .

_stprintf( store_parms, UL_TEXT("cache_size=%lu"),

cache_size );

db_init( &sqlca );


Library functions reference
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

 Library functions reference

The SQL preprocessor generates calls to functions in the runtime library or DLL. In addition to the calls generated by the SQL preprocessor, several routines are provided for the user to make database operations easier to perform. Prototypes for these functions are included by the EXEC SQL INCLUDE SQLCA command.

 db_init library function

 db_fini library function

 ULConduitStream library function

 ULHTTPStream library function

 ULPalmDBStream library function

 ULPalmExit library function

 ULPalmLaunch library function

 ULSerialStream library function

 ULSocketStream library function

 ULSynchronize library function


db_init library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 db_init library function

Function

To initialize the UltraLite runtime library.

Prototype

unsigned short db_init( struct sqlca *sqlca );

Description

This function must be called before any other library call is made, and before any embedded SQL command is executed. An exception to this rule is that on the Palm Computing Platform, the ULPalmLaunch function can be called before db_init. The resources that this library requires for your program are allocated and initialized on this call.

Use db_fini to free the resources at the end of your program.

If there are any errors during processing (for example, during initialization of the persistent store), they are returned in the SQLCA and 0 is returned. If there are no errors, a non-zero value is returned and you can begin using embedded SQL commands and functions.

In most cases, this function should be called only once (passing the address of the global sqlca variable defined in the sqlca.h header file). If you have multiple execution paths in your application, you can use more than one db_init call, as long as each one has a separate sqlca pointer. This separate SQLCA pointer can be a user-defined one, or could be a global SQLCA that has been freed using db_fini.

On the Palm Computing Platform, call db_init only when the application is started for the first time. For more information, see ULPalmLaunch library function.


db_fini library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 db_fini library function

Function

To free resources used by the UltraLite runtime library.

Prototype

unsigned short db_fini( struct sqlca *sqlca );

You must not make any other library calls or execute any embedded SQL commands after db_fini is called. If there are any errors during processing, they are returned in the SQLCA and 0 is returned. If there are no errors, a non-zero value is returned.

You need to call db_fini once for each SQLCA being used.

On the Palm Computing Platform, the database must be kept open when you leave the application. Use ULPalmExit to save the state of the application between sessions instead of calling db_fini.


ULConduitStream library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 ULConduitStream library function

Prototype

ul_stream_defn ULConduitStream( )

Description

Defines a stream under the Palm Computing Platform suitable for HotSync synchronization.

The ULConduitStream is recommended over ULPalmDBStream for most HotSync applications. If you are using ScoutSync, ULPalmDBStream generally provides faster performance.

See also

ULPalmDBStream library function

ULPalmExit library function

ULPalmLaunch library function


ULHTTPStream library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 ULHTTPStream library function

Prototype

ul_stream_defn ULHTTPStream( )

Description

Defines an UltraLite HTTP stream suitable for synchronization via HTTP.

The HTTP stream uses TCP/IP as its underlying transport. UltraLite applications act as Web browsers and MobiLink acts as a web server. UltraLite applications send POST requests to send data to the server and GET requests to read data from the server.

See also

ULSynchronize library function


ULPalmDBStream library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 ULPalmDBStream library function

Prototype

ul_stream_defn ULPalmDBStream( )

Description

Defines a stream under the Palm Computing Platform suitable for HotSync and Scout Sync.

The ULConduitStream is recommended over ULPalmDBStream for most HotSync applications. If you are using ScoutSync, ULPalmDBStream generally provides faster performance.

See also

ULConduitStream library function

ULPalmExit library function

ULPalmLaunch library function


ULPalmExit library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 ULPalmExit library function

Function

To save application state for UltraLite applications on the Palm Computing Platform. To write out an upload stream for HotSync or ScoutSync synchronization. This function is required by all UltraLite Palm applications.

Prototype

ul_bool ULPalmExit( SQLCA * sqlca, ul_synch_info * synch_info );

Arguments

sqlca    A pointer to the SQLCA.

  For information on the members of the synch_info structure, see Providing synchronization parameters.

Returns

The function returns a boolean value.

true    Success.

false    Failure.

Description

Call this function just before your application is closed, to save the state of the application.

This function saves the application state when the application is deactivated. For applications using HotSync or Scout Sync synchronization, it carries out the additional task of writing an upload stream. When the user uses HotSync or Scout Sync to synchronize data between their Palm device and a PC, the upload stream is read by the MobiLink HotSync conduit or the MobiLink Scout conduit respectively.

If you are using TCP/IP, HTTP, or serial synchronization, supply NULL values for the synch_info user_name, stream, and stream_parms members. This information is supplied instead in the call to ULSynchronize.

If you use HotSync or Scout Sync synchronization, supply ULConduitStream() or ULPalmDBStream() as the stream parameter. You must also specify the user_name parameter.

The MobiLink HotSync and ScoutSync conduits synchronize with the MobiLink synchronization server through a TCP/IP, HTTP, or serial stream using stream parameters. Specify the stream and stream parameters in the ul_synch_info structure. Alternatively, you may specify the stream and stream parameters via the ClientParms registry entry. If the ClientParms registry entry does not exist, a default setting of {stream=tcpip;host=localhost} is used.

Compatibility
The prototype for this function has changed in version 7.0. When upgrading applications to version 7.0 you must change your application to be able to compile.


ULPalmLaunch library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 ULPalmLaunch library function

Function

To restore application state for UltraLite applications on the Palm Computing Platform. To read and process a download stream for HotSync or ScoutSync synchronization. This function is required by all UltraLite Palm applications.

Prototype

UL_PALM_LAUNCH_RET ULPalmLaunch(
SQLCA * sqlca,
ul_synch_info * synch_info );

typedef enum {
LAUNCH_SUCCESS_FIRST,
LAUNCH_SUCCESS,
LAUNCH_FAIL
} UL_PALM_LAUNCH_RET;

Arguments

sqlca    A pointer to the SQLCA.

synch_info    A synchronization structure. For information on the members of this structure, see Providing synchronization parameters.

If you are using TCP/IP, HTTP or serial synchronization, supply a null value for the stream parameter.

Returns

A member of the UL_PALM_LAUNCH_RET enumeration. The return values have the following meanings:

•	LAUNCH_SUCCESS_FIRST    This value is returned the first time the application is successfully launched. In embedded SQL applications you should call db_init immediately after this return code is detected; in C++ API applications, you should open a database object.

•	LAUNCH_SUCCESS    This value is returned when an application is successfully launched, after the Palm user has been using other applications.

•	LAUNCH_FAIL    This value is returned when the launch fails.

Description

All UltraLite Palm applications need to use this function to handle the launch code in your application's PilotMain.

This function restores the application state when the application is activated. For applications using HotSync or Scout Sync synchronization, it carries out the additional task of processing the download stream prepared by the MobiLink HotSync conduit or MobiLink Scout conduit.

If you are using TCP/IP, HTTP or serial synchronization, supply a null value for the stream parameter in the ul_synch_info synchronization structure. This information is supplied instead in the call to ULSynchronize.

Examples

A typical embedded SQL example is

switch( ULPalmLaunch( &sqlca, &synch_info ) ){

case LAUNCH_SUCCESS_FIRST:

if( !db_init( &sqlca ) ){

// db_init failed: add error handling here

break;

}

// fall through

case LAUNCH_SUCCESS:

// do work here

break;

case LAUNCH_FAIL:

// error

break;

}


ULSerialStream library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 ULSerialStream library function

Prototype

ul_stream_defn ULSerialStream( )

Description

Defines an UltraLite serial stream suitable for synchronization via a serial port.

See also

ULSynchronize library function


ULSocketStream library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 ULSocketStream library function

Prototype

ul_stream_defn ULSocketStream( )

Description

Defines an UltraLite socket stream suitable for synchronization via TCP/IP.

See also

ULSynchronize library function


ULSynchronize library function
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 10.  The Embedded SQL Interface

        Library functions reference

 ULSynchronize library function

Function

To initiate synchronization in an UltraLite application.

Prototype

void ULSynchronize(
SQLCA * sqlca,
ul_synch_info * synch_info );

Arguments

sqlca    A pointer to the SQLCA.

synch_info    A synchronization structure. For information on the members of this structure, see Providing synchronization parameters.

Description

For TCP/IP, HTTP and serial synchronization, the ULSynchronize function initiates synchronization. Errors during synchronization that are not handled by the handle_error script are reported as SQL errors. Your application should test the SQLCode return value of this function.

Compatibility
The prototype for this function has changed in version 7.0. When upgrading applications to version 7.0 you must change your code for your application to compile.

See also

MobiLink synchronization server


CHAPTER 11.  Platform-Specific Development
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

 CHAPTER 11.  Platform-Specific Development

About this chapter

This chapter describes details of development, deployment and synchronization that are specific to each platform. These instructions assume familiarity with the general development process. They assist in building the CustDB sample application, included with your UltraLite software, on each of these platforms.

 Developing for the Palm Computing Platform

 Palm synchronization overview

 Understanding HotSync and ScoutSync synchronization

 Adding synchronization to Palm applications

 Configuring synchronization for Palm devices

 Developing for Windows CE

 Synchronization on Windows CE

 Developing for VxWorks

 Synchronization on the VxWorks platform

 Developing for DOS

 Synchronization on the DOS platform


Developing for the Palm Computing Platform
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Developing for the Palm Computing Platform

This section presents information for developers building UltraLite applications for use with the Palm Computing Platform.

Development environments

You can use one of two development environments to build UltraLite Palm applications:

•	Metrowerks CodeWarrior, version 5 and 6. See Developing UltraLite applications with Metrowerks CodeWarrior.

•	GCC PRC-Tools. This set of tools is based on the GNU compiler. See Developing UltraLite applications with GCC PRC-Tools.

  For more information on host platforms, see Supported platforms for C/C++ applications. For general information on development environments for the Palm, including more information on each of the supported host platforms, see the Palm Computing Platform Development Zone Web site.

Palm-specific notes

The information in this section concerning Palm development supplements the general information on UltraLite development provided Developing UltraLite Applications.

 Developing UltraLite applications with Metrowerks CodeWarrior

 Developing UltraLite applications with GCC PRC-Tools

 Launching and closing UltraLite applications

 Installing your application on the target device


Developing UltraLite applications with Metrowerks CodeWarrior
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

 Developing UltraLite applications with Metrowerks CodeWarrior

Supported host platforms for Palm Computing Platform UltraLite development are Metrowerks CodeWarrior versions 5 and 6.

The UltraLite runtime libraries for CodeWarrior are located in subdirectories of your SQL Anywhere installation directory:

UltraLite\Palm\68k\lib\cw5\ulrt.lib

UltraLite\Palm\68k\lib\cw6\ulrt.lib

A CodeWarrior plugin is supplied to make building UltraLite applications easier. This plugin is supplied in the UltraLite\Palm\68k\cwplugin directory.

 Installing the UltraLite plugin for CodeWarrior

 Creating UltraLite projects in CodeWarrior

 Converting an existing CodeWarrior project to an UltraLite application

 Using the UltraLite plugin for CodeWarrior

 Working with segments in CodeWarrior

 Building the CustDB sample application from CodeWarrior


Installing the UltraLite plugin for CodeWarrior
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Developing UltraLite applications with Metrowerks CodeWarrior

 Installing the UltraLite plugin for CodeWarrior

The files for the UltraLite plugin for CodeWarrior are placed on your disk during UltraLite installation, but the plugin is not available for use without an additional installation step.

♦ To install the UltraLite plugin for CodeWarrior:

1	Ensure that you are running CodeWarrior R5 at patch level 1 or higher, or CodeWarrior R6. You can obtain patches for CodeWarrior from the Metrowerks Web site.

2	From a command prompt, change to the palm\68k\cwplugin subdirectory of your UltraLite directory.

3	Run install.bat to copy the appropriate files into your CodeWarrior installation directory: The install.bat file takes two arguments:

•	Your CodeWarrior directory

•	Your CodeWarrior version. Version 5 is the default.

For example, the following command installs the plugin for CodeWarrior 6 in the directory c:\Program Files\CodeWarrior.

install "c:\Program Files\CodeWarrior" r6

You only need double quotes around the directory if the path has spaces.

Uninstalling the CodeWarrior plugin

There is also a file uninstall.bat, that you can use in the same way as install.bat to uninstall the UltraLite Plugin from CodeWarrior.


Creating UltraLite projects in CodeWarrior
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Developing UltraLite applications with Metrowerks CodeWarrior

 Creating UltraLite projects in CodeWarrior

This section describes how to use the UltraLite Plugin for CodeWarrior.

♦ To create an UltraLite project in CodeWarrior:

1	Start CodeWarrior.

2	Create a new project.

From the CodeWarrior menu, choose File [image] New. A tabbed dialog appears.

On the Projects dialog, choose one of the available choices, and choose a name and location for the project. Click OK.

3	Choose an UltraLite stationery.

The UltraLite plugin adds two choices to the stationery list, one for C++ API applications and one for embedded SQL applications.

Choose the development model you want to use and click OK to create the project.

This stationery is standard C stationery for embedded SQL, and standard C++ stationery for the C++ API, and contains almost-empty source files.

4	Configure the target settings for your project.

On your project window (.mcp), choose the Targets tab, and click the Settings icon on the toolbar. The Project Settings window opens.

In the tree on the left pane, choose Target [image] UltraLite preprocessor. You can enter the settings for your project, such as which reference database to use.

When you build your project by pressing F7, the sqlpp and ulgen utilities are invoked automatically to convert any .sqc files into .c or .cpp files. Also, the UltraLite headers and the runtime library are automatically added to the search paths.


Converting an existing CodeWarrior project to an UltraLite application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Developing UltraLite applications with Metrowerks CodeWarrior

 Converting an existing CodeWarrior project to an UltraLite application

If you install the UltraLite plugin into CodeWarrior, you will be asked to convert each existing project when you open it. In this conversion, CodeWarrior sets the default SQL preprocessor settings and saves them in the project file. This causes no disruption to projects that do not use the SQL preprocessor. If you want to further convert a project to invoke the SQL preprocessor automatically, you need to do the following:

1	Add a file mapping entry for .sqc and .ulg files to the File Mappings panel of the Target settings.

These files are of file type TEXT and the Compiler is UltraLite Preprocessor. All flags for these files should be unchecked.

2	Remove all .cpp files generated by the SQL preprocessor from the Files view. These files are automatically generated and re-added when the .sqc files are built.


Using the UltraLite plugin for CodeWarrior
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Developing UltraLite applications with Metrowerks CodeWarrior

 Using the UltraLite plugin for CodeWarrior

The UltraLite plugin for CodeWarrior integrates the UltraLite preprocessing steps (running the UltraLite generator and, for embedded SQL applications, running the SQL preprocessor) into the CodeWarrior compilation model. It ensures that the SQL preprocessor is run whenever you build a project after changing one of your .sqc files, and it ensures that the UltraLite generator is run after changing a .sqc file or after changing the UltraLite project name.

If you change a SQL statement in a C++ API UltraLite project, or if you alter a SQL Remote publication used in a C++ API project, you must manually touch the dummy uldatabase.ulg file to prompt the UltraLite generator to run.

  For an overview of the tasks the plugin carries out, see Configuring development tools for UltraLite development.

Using prefix files

A prefix file is a header file that is included by all source files in a Metrowerks CodeWarrior project. You should use ulpalmXX.h, where XX indicates the version of the Palm SDK you are using, from the h subdirectory of your SQL Anywhere Studio installation directory as your prefix file. The CodeWarrior plugin sets this for you automatically.

You can use ulpalmos.h as your prefix file if you do not want to differentiate between SDK versions.


Working with segments in CodeWarrior
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Developing UltraLite applications with Metrowerks CodeWarrior

 Working with segments in CodeWarrior

Application code for the Palm Computing Platform must be divided into segments, each of which must be less than 64K.

If you generate a database source code file that does not fit into a single segment, you must divide the code into multiple segments. In embedded SQL, you can do this by adding the following line at various places in the .sqc file:

#pragma segment segment-name

where segment-name is a unique name for the segment This forces application code after each #pragma line to be in a separate segment.

If you are using the C++ API, or if the application code generated from the .sqc file is still too large, you should define a new prefix file for your CodeWarrior project, instead of ulpalmXX.h (XX=30, 31, or 35), with the following contents:

#define UL_ENABLE_SEGMENTS

#include palmXX.h

This instructs the compiler to place each function in the generated application code in a separate segment.

You can use ulpalmos.h if you do not want to differentiate between SDK versions.

The first segment

You must ensure that PilotMain and all functions called in PilotMain are in the first segment. If necessary, you can add a line of the following form before your startup code:

#pragma segment segment-name

where segment-name is the name of your first segment.

  For more information on prefix files and segments, see your Palm developer documentation.


Building the CustDB sample application from CodeWarrior
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Developing UltraLite applications with Metrowerks CodeWarrior

 Building the CustDB sample application from CodeWarrior

CustDB is a simple sales-status application. It is located in the UltraLite samples directory of your installation. Generic files are located in the CustDB directory. Files specific to CodeWarrior for the Palm Computing Platform are located in the cw5 (CodeWarrior 5) or cw6 (CodeWarrior 6) subdirectory of CustDB.

  For a diagram of the sample database schema, see The UltraLite sample application.

♦ To build the sample application:

1	Start the CodeWarrior IDE.

2	Open the CustDB project file.

•	Choose File [image] Open.

•	In the Open dialog, change to the samples\custdb\cw5 or samples\custdb\cw6 subdirectory of your UltraLite installation directory, depending on your version of CodeWarrior.

•	Open the project file custdb.mcp.

Alternatively, you can select the target (embedded SQL or C++ API) from the project file.

3	From the Project menu, select Make to build the target application, which is custdb.prc.

You can use the UltraLite plugin to customize settings for your own application. For more information, see Developing UltraLite applications with Metrowerks CodeWarrior.


Developing UltraLite applications with GCC PRC-Tools
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

 Developing UltraLite applications with GCC PRC-Tools

You can use the GNU GCC PRC-Tools suite for the Palm Computing Platform to develop UltraLite applications. This section assumes that you are familiar with the installation and use of the GCC PRC-Tools, and provides UltraLite-specific tips and information.

  For information on the GCC PRC-Tools suite, see http://www.palm.com/devzone/tools/gcc/.

The UltraLite runtime library for PRC-Tools is located in subdirectories of your SQL Anywhere directory:

UltraLite\Palm\68k\lib\prctools20\libulrt.a

No transport-layer security using GCC tools
The Certicom transport-layer security is not available when using GCC tools.

 Working with segments in PRC Tools

 Building the CustDB sample application with PRC Tools


Working with segments in PRC Tools
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Developing UltraLite applications with GCC PRC-Tools

 Working with segments in PRC Tools

Application code for the Palm Computing Platform must be divided into separate segments. The gcc compiler requires that each of these segments be less than 32K.

The UltraLite generator includes instructions in the generated code that the gcc compiler can use to split the executable into segments named ULGnnn, where nnn is a set of unique numbers. The segment names ULRT1 to ULRT17 are reserved for the UltraLite runtime libraries.

When compiling your UltraLite application, you need to define the following two macros on the compiler command line:

•	UL_ENABLE_SEGMENTS

•	UL_ENABLE_GNU_SEGMENTS

  For an example, see the file build.bat in the UltraLite\Samples\CustDB\PRCTools20 subdirectory of your SQL Anywhere directory.

Providing segment information to the linker

The GNU link tools multilink and build-prc require a segment definition file containing the segment information. You can use the dbulseg command-line utility to generate this file. You should run the utility against each source file, and supply a name for the definition file. For example, the following command line:

dbulseg gensource.c project.def AppName CreatorID

creates a project.def definition file with the following content:

application{ "AppName" CreatorID }

multiple code{ ULRT1 ... ULRT17 ULG512 ULG513 ... }

where the ULG segment names are obtained from the generated source file gensource.c.

  For more information on the UltraLite segment utility, see UltraLite Segment utility.

The first segment

You must ensure that PilotMain and all functions called in PilotMain are in the first segment. The GNU PRC-Tools call this first segment .text. None of the

  For more information on prefix files and segments, see your Palm developer documentation.

Compiler issues

You should compile using the -DM68000 -mnoshort switches. The first option declares a symbol required to properly set the SQL_OS macro. The second option forces int data types to be four bytes (two is default).

When compiling source files that hold more than 32K of code partitioned into multiple segments, the compiler may generate jsr instructions unacceptable to the assembler. This happens when a function defined at the bottom of the source file makes an inter-segment call to a function defined at the top of the source file, with at least 32K of code in between. Normally, the offset of the jsr instruction is replaced during the relocation stage of the linker, but in this case, the error prevents the compilation from going any further.

The generated file for UltraLite is usually bigger than 32K, and almost every function is in a separate segment.

You can avoid this issue by using the -Wa,-J switch when compiling. This instructs the assembler to ignore any signed overflow errors.


Building the CustDB sample application with PRC Tools
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Developing UltraLite applications with GCC PRC-Tools

 Building the CustDB sample application with PRC Tools

CustDB is a simple sales-status application. It is located in the UltraLite samples directory of your installation. Generic files are located in the CustDB directory. Files specific to PRC Tools for the Palm Computing Platform are located in the prctools20 subdirectory of CustDB.

You must have the full set of PRC Tools installed before building the CustDB sample application, including the following:

•	Cygnus cygwin tools. The directory containing cygwin1.dll must be in your path.

•	GCC Tool chain for the Palm OS (PRC Tools 2.0). The multigen.exe utility must be in your path.

•	Palm SDK 3.5.

•	PilRC resource compiler tools. The pilrc.exe utility must be in your path.

♦ To build the sample application:

1	Open a command prompt window.

2	Change directory to the UltraLite\Samples\CustDB\prctools20 subdirectory of your SQL Anywhere directory.

3	Entering the following command:

build

The build.bat file contains instructions to build the UltraLite sample application.

Once you have built the sample application, you can use the Palm Desktop software deploy the custdb.prc executable to your target device.


Launching and closing UltraLite applications
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

 Launching and closing UltraLite applications

Applications under the Palm OS run under a single thread. To maintain the illusion that an application is running in the background after you close it, the application must save its internal state when the user switches to another application. When the application is launched again, it must restore its internal state.

During the period that an application is inactive, the Palm user may HotSync their device, using HotSync or the ScoutSync synchronization. If you choose to use HotSync or ScoutSync synchronization for your UltraLite application, its data must be synchronized along with that of other applications on the device.

This section describes how to handle launching and closing of an UltraLite Palm application.

Two Palm-specific UltraLite functions save and restore internal state information, and must be used by all UltraLite applications for the Palm Computing Platform. These functions also handle synchronization if you are using the HotSync or ScoutSync synchronization streams, but not if you are using TCP/IP, HTTP, or serial streams.

 Launching an UltraLite Palm application

 Closing an UltraLite Palm application


Launching an UltraLite Palm application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Launching and closing UltraLite applications

 Launching an UltraLite Palm application

Whenever your UltraLite application is launched, your code must call the function to restore state and (if using HotSync or ScoutSync) process the download synchronization stream.

For embedded SQL development, this function is ULPalmLaunch. For C++ API development, this function is the ULData.PalmLaunch() method.

If your application has never been run before, or was abnormally terminated the last time it was run, the function returns a value of LAUNCH_SUCCESS_FIRST. In this case, you must initialize the UltraLite data store. Otherwise, you must not initialize the data store.

  For more information, see ULPalmLaunch library function, and PalmLaunch method.

  For information on using the PalmLaunch function for synchronization, see Adding HotSync or ScoutSync synchronization to Palm applications.


Closing an UltraLite Palm application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

          Launching and closing UltraLite applications

 Closing an UltraLite Palm application

Whenever your UltraLite application is closed, and the user switches to another application, your code must call the function to save its state and (if using HotSync or ScoutSync) write out an upload synchronization stream.

Some kinds of data cannot be kept open during the time that you move away from an UltraLite application.

For embedded SQL development, this function is ULPalmExit. For C++ API development, this function is the ULData.PalmExit() method.

C++ API

For C++ API developers, the following considerations also apply:

•	Do not close any ULData or ULConnection objects. When the user returns to the application, call Reopen, first on the ULData and then on the ULConnection object.

•	For cursor objects, including instances of generated result set classes, you can do either of the following:

•	Ensure that the object is closed when the user switches away from the application, and call Open when you next need the object. If you choose this option, the current position is not restored.

•	Do not close the object when the user switches away, and call Reopen when you next need to access the object. The current position is then maintained, but the application takes more memory in the Palm when the user is using other applications.

•	For table objects, including instances of generated table classes, you cannot save a position. You must close table objects before a user moves away from the application, and Open them when the user needs them again. Do not use Reopen on table objects.

Embedded SQL

Do not call db_fini when the application is closed.

  For more information, see ULPalmExit library function, and PalmExit method.


Installing your application on the target device
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for the Palm Computing Platform

 Installing your application on the target device

Install your UltraLite application on your Palm device as you would any other Palm Computing Platform application.

♦ To install an application on a Palm device:

1	Open the Install Tool, included with your Palm Desktop Organizer Software.

2	Choose Add and locate your compiled application (.prc file).

3	Close the Install Tool.

4	HotSync to copy the application to your Palm device.

Preserving data when upgrading
When you upgrade an UltraLite application, the application database is automatically re-created with no data in any tables. To avoid losing data stored in your UltraLite database, synchronize your existing UltraLite application with the consolidated database before upgrading your application.


Palm synchronization overview
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Palm synchronization overview

UltraLite applications running on the Palm Computing Platform can synchronize using the following streams:

•	TCP/IP    Through the cradle or through a modem.

•	HTTP    Through the cradle or through a modem.

•	Serial    Direct serial port communication through the cradle.

•	HotSync    The Palm Computing Platform built-in synchronization method.

•	ScoutSync    The synchronization method developed by Riverbed Technologies, and licensed by Palm Computing for use in the Palm HotSync Server.

ScoutSync 3.0 is fully supported. ScoutSync 3.5 and HotSync Server 3.5 were not generally available at the time UltraLite 7.0 was released. UltraLite 7.0 has been tested with beta versions of ScoutSync 3.5 and HotSync Server 3.5.

  For more information regarding ScoutSync, see http://www.riverbedtech.com.

 Choosing a synchronization method


Choosing a synchronization method
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Palm synchronization overview

 Choosing a synchronization method

Each synchronization channel has its advantages and disadvantages.

•	Multiple applications    If you have more than one UltraLite application installed on a Palm device, they will all synchronize when you invoke HotSync or ScoutSync. To synchronize multiple applications through a TCP/IP, HTTP or serial connection, you must activate and synchronize each application in turn.

•	Performance    MobiLink synchronization using TCP/IP, HTTP, or serial is faster than the HotSync or ScoutSync ULPalmDBStream. The ULConduitStream addresses most performance issues in the HotSync architecture.

•	Convenience    Serial synchronization requires the MobiLink synchronization server to be installed on your PC. Other methods of synchronization do not require MobiLink synchronization server on the PC, instead, it can run on any machine on your network.

 Choosing a synchronization stream for HotSync and ScoutSync


Choosing a synchronization stream for HotSync and ScoutSync
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Palm synchronization overview

          Choosing a synchronization method

 Choosing a synchronization stream for HotSync and ScoutSync

There are two synchronization streams available for use with HotSync and ScoutSync: ULPalmDBStream and ULConduitStream. You cannot use both within a single application.

For most applications using HotSync, ULConduitStream provides much better performance. For most applications using ScoutSync, ULPalmDBStream provides better performance.

The main difference between the two streams is that ULConduitStream carries out most processing at the conduit running on the desktop or server, while for ULPalmDBStream much of the processing is carried out on the Palm device.

The ULConduitStream supports the ability to synchronize more than once without having to launch the Palm application between synchronizations, whereas this feature is not supported by ULPalmDBStream. Also, ULConduitStream handles errors during synchronization better, including abnormal termination of the communication stream.

When using ULConduitStream with ScoutSync, the entire Palm database must be transferred from the Palm device to the server, with potential performance penalties for databases of any significant size. Also, each synchronization request is processed serially, and so at times of high demand, there may be delay at clients waiting for ScoutSync server to process other ULConduitStream synchronization requests.

  For information on setting the synchronization parameters to choose the synchronization stream, see Setting synchronization parameters.


Understanding HotSync and ScoutSync synchronization
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Understanding HotSync and ScoutSync synchronization

UltraLite applications on Palm devices can synchronize over a TCP/IP, HTTP, or serial stream, in much the same manner as UltraLite applications on other platforms. They can also synchronize using the Palm-specific HotSync or ScoutSync synchronization streams, which operate in a different manner. This section describes the architecture of the HotSync and ScoutSync synchronization.

The diagrams below depict the sequence of events that occur during HotSync and ScoutSync synchronization using ULPalmDBStream. For ULConduitStream, more processing is passed on to the conduit.

1	When your UltraLite application is closed, it saves the state of your UltraLite application and writes an upload stream to the remote database on your Palm device.

Because of the time taken to write the download stream, you can expect a slight delay when switching away from your application if using ULPalmDBStream.

  For more information, see Closing an UltraLite Palm application.

2	When you synchronize your Palm device, HotSync or ScoutSync takes the upload stream and calls the MobiLink conduit to forward the uploads to the MobiLink synchronization server.

3	The MobiLink synchronization server integrates updates into the consolidated database and replaces the upload stream with a download stream. The download stream is then sent to the MobiLink conduit and subsequently to the Palm database.

4	When your application is launched, it checks for the previously saved state of your UltraLite application and for the download stream. It then integrates changes into the UltraLite database.

Because of the time taken to apply a download, you can expect a slight delay when you switch back to your application after performing a HotSync or ScoutSync synchronization if using ULPalmDBStream.

  For more information, see Launching an UltraLite Palm application.

 HotSync and ScoutSync architecture

 HotSync and ScoutSync synchronization step by step


HotSync and ScoutSync architecture
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Understanding HotSync and ScoutSync synchronization

 HotSync and ScoutSync architecture

The application code for HotSync and ScoutSync synchronization is identical except for the stream_parms member of the ul_synch_info structure. The synchronization architecture is different, however.

The following diagram depicts the ScoutSync architecture. The ScoutSync conduit is a DLL that runs on the same machine as the ScoutSync server. A separate instance of the conduit is instantiated by the ScoutSync server for each Palm device.

The following diagram depicts the HotSync architecture. In this case, a separate HotSync conduit is required for each application (as opposed to each device for ScoutSync). You can have multiple HotSync conduits on a single PC.


HotSync and ScoutSync synchronization step by step
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Understanding HotSync and ScoutSync synchronization

 HotSync and ScoutSync synchronization step by step

The following steps outline how to get HotSync or ScoutSync synchronization working.

♦ To set up HotSync or ScoutSync synchronization:

1	Start the MobiLink synchronization server:

The following command line is a useful form for development and testing. It must be entered all on one line:

dbmlsrv7.exe -vcrs

-c "dsn=UltraLite 7.0 Sample"

-ot path\output_file.txt

TCP/IP is the default communication protocol for the MobiLink synchronization server. The output file is useful to store informational messages.

2	Register your application to the HotSync Manager.

The following command, run on the machine where the HotSync Manager is running, is an example for the CustDB example:

dbcond7 "Syb2" -n CustDB

3	Start HotSync Manager.

For information, see the directions that come with your Palm device. If you registered your application while HotSync Manager was running, you should restart HotSync Manager.

4	In the source code for your UltraLite application call ULPalmExit() with parameters such as the following:

ul_synch_info info;

ULInitSynchInfo( &info );

info.stream = ULConduitStream();

info.stream_parms =

  UL_TEXT( "stream=tcpip;host=localhost" );

info.user_name = UL_TEXT( "50" );

info.version = UL_TEXT( "custdb" );

if( !ULPalmExit( &sqlca, &info ) ) {

  return( false );

}


Adding synchronization to Palm applications
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Adding synchronization to Palm applications

This section describes how to add synchronization to your Palm application.

  For information on the synchronization architecture for HotSync and ScoutSync, see Understanding HotSync and ScoutSync synchronization.

  For a general description of how to add synchronization to UltraLite applications, see Adding synchronization to your application.

 Adding HotSync or ScoutSync synchronization to Palm applications

 Adding TCP/IP, HTTP, or serial synchronization to Palm applications

 Using multiple synchronization methods


Adding HotSync or ScoutSync synchronization to Palm applications
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Adding synchronization to Palm applications

 Adding HotSync or ScoutSync synchronization to Palm applications

This section describes what you need to include in your UltraLite application code to synchronize using HotSync or ScoutSync. From the UltraLite application side, the procedure is very similar for these two synchronization streams.

See also

For an overview of HotSync and ScoutSync, see Understanding HotSync and ScoutSync synchronization.

For information on configuring HotSync and ScoutSync, see Configuring HotSync synchronization, and Configuring ScoutSync synchronization.

Synchronization functions

If you use HotSync or ScoutSync, then you synchronize by calling ULPalmLaunch or ULData.PalmLaunch when your application is launched, and ULPalmExit or ULData.PalmExit when your application is closed. The stream parameter for the ul_synch_info structure should be ULConduitStream() or ULPalmDBStream().

You do not use ULSynchronize or ULConnection.Synchronize for HotSync or ScoutSync synchronization.

  For more information, see Launching and closing UltraLite applications.

If there are uncommitted transactions when you close your Palm application, the upload stream is not built, and if you synchronize before reactivating the application, the conduit reports that synchronization fails because of uncommitted changes in the database.

Specifying the stream parameters

The synchronization stream parameters in the ul_synch_info structure control communication with the MobiLink synchronization server. For HotSync or ScoutSync synchronization, the UltraLite application does not communicate directly with a MobiLink synchronization server; it is the MobiLink HotSync or ScoutSync conduit instead.

You can supply synchronization stream parameters to govern the behavior of the MobiLink conduit in one of the following ways:

•	Supply the required information in the stream_parms member of ul_synch_info.

  For a list of available values, see Setting synchronization parameters.

•	Supply a null value for the stream_parms member. The MobiLink conduit then searches in the ClientParms registry entry on the machine where it is running for information on how to connect to the MobiLink synchronization server.

The stream and stream parameters in the registry entry are specified in the same format as in the ul_synch_info structure.

  For more information, see Configuration overview.

HotSync compatibility

In SQL Anywhere version 7.0, the MobiLink HotSync conduit and the MobiLink synchronization server no longer have to be on the same machine. Instead, the MobiLink HotSync conduit synchronizes with a MobiLink synchronization server, not necessarily on the same machine, using a synchronization stream.

Old clients can use the new conduit by setting the appropriate stream and stream parameters in the registry on the machine where the conduit is running. The stream and stream parameters cannot be specified in ULPalmExit.

  For instructions, see Configuring the conduit communication stream.


Adding TCP/IP, HTTP, or serial synchronization to Palm applications
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Adding synchronization to Palm applications

 Adding TCP/IP, HTTP, or serial synchronization to Palm applications

Palm devices can synchronize using TCP/IP, HTTP, or serial communication by setting the stream member of the ul_synch_info structure to the appropriate stream, and calling ULSynchronize (embedded SQL) or the ULConnection.Synchronize method (C++ API) to carry out the synchronization.

When using TCP/IP, HTTP, or serial synchronization, ULPalmLaunch and ULPalmExit save and restore the state of the application on exiting and activating the application, but do not participate in synchronization. These functions take the ul_synch_info structure as an argument, but in this case do not use it. You should set the stream member to NULL (the default) when calling ULPalmExit or ULPalmLaunch.

When using TCP/IP or HTTP synchronization from a Palm device, you must specify an explicit host name or IP number in the stream_parms member of the ul_synch_info structure. Specifying NULL defaults to localhost, which represents the device, not the host.

  For information on the ul_synch_info structure, see Setting synchronization parameters.


Using multiple synchronization methods
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Adding synchronization to Palm applications

 Using multiple synchronization methods

Switching between two or more synchronization techniques from a single UltraLite application is only convenient when using varied connection points for synchronization. For example, you may synchronize from both a laptop (HotSync or ScoutSync) and a serial connection station on a factory floor. Switching techniques to connect to the same machine is usually awkward.


Configuring synchronization for Palm devices
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Configuring synchronization for Palm devices

  For information on synchronization architecture for HTTP, TCP/IP, and serial communications, see Parts of the synchronization system..

This section describes how to configure the synchronization setup for UltraLite Palm applications.

 Configuring TCP/IP synchronization for the Palm Computing Platform

 Configuring HTTP synchronization for the Palm Computing platform

 Configuring serial synchronization for the Palm Computing platform

 Configuring HotSync synchronization

 Configuring ScoutSync synchronization


Configuring TCP/IP synchronization for the Palm Computing Platform
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

 Configuring TCP/IP synchronization for the Palm Computing Platform

There are two ways of using TCP/IP networking in a Palm device. In either case, you must connect to a Remote Access Service (RAS). The difference lies in how you make the connection to the RAS.

•	Use a modem to dial into an ISP    The Internet Service Provider (ISP) must provide access to a Remote Access Service (RAS). The components of the connection are as follows:

Application

<--> Palm Net Library

<--> Palm modem

<--> NT RAS

<--> TCP/IP network

•	Connect via the serial port to a Windows NT machine    The components of the connection are as follows:

Application

<--> Palm Net Library

<--> serial cable

<--> NT RAS

<--> TCP/IP network

When using TCP/IP, the MobiLink synchronization server can be any machine on the network that is accessible via TCP/IP.

Before synchronization, the following conditions must be satisfied:

1	The device must be in its cradle.

2	If you are using the serial port to connect to a Windows NT machine running RAS, the HotSync Manager and other applications that use the serial port must be shut down. Windows NT only allows one application to use a serial port at a time.

3	The MobiLink synchronization server must be started. By default, the MobiLink synchronization server listens on port 2439.

The MobiLink synchronization server must be started and listening on a serial port at the other end of the cable. If the cradle is connected to the COM1: port of the machine, start the MobiLink synchronization server as follows:

dbmlsrv7 -x serial{port=1} -c ...

4	The Palm device must have Network settings in place so that it can connect to the network. Modem settings are also required if using a modem to dial into an ISP.

 Configuring RAS TCP/IP synchronization via modem

 Configuring RAS TCP/IP synchronization via serial port connection

 Testing and troubleshooting


Configuring RAS TCP/IP synchronization via modem
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring TCP/IP synchronization for the Palm Computing Platform

 Configuring RAS TCP/IP synchronization via modem

To use this method, you must have access to a Remote Access Service when you dial in.

♦ To configure a Palm device for RAS TCP/IP via a modem:

1	Install the modem by plugging the Palm device into the modem module.

2	Go to the Preferences (Prefs) panel and choose Network from the dropdown list at the top right of screen.

3	Choose the Windows RAS service.

4	Set the dial-in username and password.

5	Set the phone number to the number at which the Remote Access Service can be reached. Obtain this number from your ISP.

6	Tap on Details.

7	Set the connection type (usually PPP).

8	Set the DNS and IP addresses as recommended by your network administrator.

9	Tap on Script and enter the script recommended by your ISP. This script will be similar to the following sample.

Wait For: Username:

Delay: 1

Send UserID:

Send CR:

Wait For: Password:

Delay: 1

Send Password:

Send CR:

Wait For: >

Delay: 1

Send: ppp

Send CR:

End:

Tap on OK until you are back to the Network Preferences.

At this point, you are ready to test your TCP/IP connection.


Configuring RAS TCP/IP synchronization via serial port connection
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring TCP/IP synchronization for the Palm Computing Platform

 Configuring RAS TCP/IP synchronization via serial port connection

This procedure involves actions both on Windows NT and on the Palm Computing device.

♦ To configure Windows NT for RAS TCP/IP via serial port:

1	From the Control Panel, open Modems. Make sure that a modem is defined for Dial-Up Networking Serial Cable between 2 PCs on the COM port to which the cradle is connected.

2	Set the speed for this modem to the baud rate you are using. The default is 19200.

3	Make sure TCP/IP protocol is installed. Select Start [image] Settings [image] Control Panel and double-click the Network icon. Click on the Protocols tab. If there is no TCP/IP entry, choose Add to install it.

4	Enable IP Forwarding (in the Routing tab of TCP/IP properties)

5	Under the Services tab, make sure that Remote Access Service is installed. If there is no entry for Remote Access Service, choose Add to install it.

In Remote Access Service Properties, add Dial Up Network serial cable between 2 pc's for that COM port if the cradle's COM port is not in the list of ports.

6	Configure this entry to receive calls. In the RAS Network properties set encryption settings to Allow any authentication including clear text. In the RAS Network properties allow only TCP/IP client.

7	Configure TCP/IP. Allow clients to access the entire network. Assigning the TCP/IP addresses depends on your network. Contact your network administrator for details.

8	Add a user for dial-in access. Select Start [image] Programs [image] Admininstrative Tools [image] User Manager. Uncheck User Must Change Password at Next Logon. Choose the Dialin button, and grant dialin permission to user with No Call Back.

9	If the RAS COM port is the same one that HotSync Manager uses, shut down the HotSync Manager or any other applications that use the COM port.

10	Start the Remote Access Administrator. Select Start [image] Programs [image] Administrative Tools [image] Remote Access Admin.

11	Start the RAS service. Select Server [image] Start Remote Access Service. Choose to start the service on the local machine.

HotSync Manager or any other applications that use the serial port and the RAS service will not run at the same time. One must be shut down first for the other to run, as Windows NT prevents two different applications from accessing the same serial port. You have to stop the RAS service (Server [image] Stop Remote Access Service from the Remote Access Admin) before you can restart the HotSync Manager. Alternatively, you can use separate serial ports.

Once the RAS service is running, it is ready to receive connection requests via the serial port.

♦ To configure a Palm device for RAS TCP/IP via serial port:

1	Go to the Preferences (Prefs) panel and choose Network from the dropdown list at the top right of screen.

2	Choose the Windows RAS service.

3	Set the dial-in username and password.

4	Set the Palm to use the serial port.

•	For Palm OS 3.3 and above, select Direct serial.

•	For earlier versions of the Palm OS, set the phone number to 00 (zero zero). This is a special phone number that tells the Palm to use the serial port directly, instead of a modem.

5	Tap on Details.

6	Set the connection type (usually PPP).

7	Set the DNS and IP addresses as recommended by your network administrator.

8	Tap on Script and enter the following script:

Send: CLIENT

Send CR:

Delay: 1

Send: CLIENT

END

Tap on OK until you are back to the Network Preferences

At this point, you are ready to test your TCP/IP connection.


Testing and troubleshooting
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring TCP/IP synchronization for the Palm Computing Platform

 Testing and troubleshooting

♦ To test the connection:

1	via modem    Connect the Palm device to the modem and follow the instructions provided by your ISP for connecting to their network. Once connected, tap the Connect button in Prefs [image] Network on the Palm device.

2	via serial port    Ensure RAS is running on the Windows NT machine. Place the Palm device in the cradle and connect the cradle to the correct COM port on the Windows NT machine. Tap the Connect button in Prefs [image] Network on the Palm device.

With TCP/IP, there are two levels of service. At the minimum level, you can connect to another TCP/IP host using an IP number of the following form.

NNN.NNN.NNN.NNN

At the next level, when a DNS server is properly configured, you are able to connect to another host by name.

some_host_machine.any_company.com

Having a DNS service is more convenient, since most people are better at remembering a name than a number. As long as you have the minimum TCP/IP service, and an IP number, you can synchronize an UltraLite application using TCP/IP.

There are a number of steps you can take to troubleshoot TCP/IP connections on the Palm device.

•	Hitting the scroll down button on the Palm device during the connection phase displays the progress of the connection.

•	The connection log is accessible from the Network Preferences panel. Choose View Log from the Options menu to see information about the network connection. The log is an interactive utility for controlling and viewing your connection information. Enter ? for help.

•	There are several tools for testing a TCP/IP connection from the Palm. You can find most of them at the following locations:

http://www.roadcoders.com

http://www.palmcentral.com

There are also steps you can take for troubleshooting on Windows NT:

•	In the Remote Access Admin, double-click on the running server.

•	Select the appropriate port and choose Port Status. The Port Status dialog shows you the Line condition (connected or waiting for a call) and lets you watch the byte counts for both directions.


Configuring HTTP synchronization for the Palm Computing platform
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

 Configuring HTTP synchronization for the Palm Computing platform

To use HTTP synchronization, you must first configure RAS TCP/IP synchronization. For information on configuring RAS, see Configuring TCP/IP synchronization for the Palm Computing Platform.

When using HTTP, the MobiLink synchronization server can be any machine on the network that is accessible via HTTP.

♦ To synchronize using HTTP:

1	Place the Palm device in its cradle.

2	If you are using the serial port to connect to a Windows NT machine running RAS, shut down the HotSync Manager and other applications that use the serial port. Windows NT only allows one application to use a serial port at a time.

3	Start the MobiLink synchronization server. By default, the MobiLink synchronization server listens on port 2439.

4	Ensure that the network settings on the Palm device are configured so that it can connect to the network. Modem settings are also required if using a modem to dial into an ISP.

  For more information, see Configuring TCP/IP synchronization for the Palm Computing Platform.


Configuring serial synchronization for the Palm Computing platform
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

 Configuring serial synchronization for the Palm Computing platform

Controlling the baud rate

By default, data is synchronized at 19200 baud. To select another speed, specify the baud rate to MobiLink as in the following example:

dbmlsrv7 -x serial{port=1;baud=9600} -c ...

Specify the same baud rate in the ul_synch_info structure, as in the following example:

auto ul_synch_info synch_info;

ULSynchInit( &synch_info );

synch_info.stream = ULSerialStream();

synch_info.stream_parms = UL_TEXT( "baud=9600" );

  For a complete list of parameters, see Setting synchronization parameters.


Configuring HotSync synchronization
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

 Configuring HotSync synchronization

This section describes how to set up and configure the MobiLink HotSync conduit, which is required for HotSync synchronization of UltraLite applications.

  For an overview of HotSync synchronization, see HotSync and ScoutSync architecture.

 Configuration overview

 HotSync conduit files

 Adding the MobiLink conduit into HotSync manager

 Checking that installation is correct

 Configuring the conduit communication stream


Configuration overview
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring HotSync synchronization

 Configuration overview

During HotSync synchronization, the HotSync Manager starts the MobiLink HotSync conduit, dbhsync7.dll, which passes the upload stream on to a MobiLink synchronization server, and receives the download stream from the MobiLink synchronization server.

The MobiLink HotSync conduit synchronizes with the MobiLink synchronization server using one of TCP/IP, HTTP, or serial streams.

Depending on the demands of your installation, you may deploy only the MobiLink HotSync conduit onto the desktop machines of your users.

  For information on HotSync architecture, see HotSync and ScoutSync architecture.

♦ To install and configure the MobiLink HotSync conduit:

1	Place the conduit files on the user's machine.

  For instructions, see HotSync conduit files.

2	Add the MobiLink conduit to the HotSync Manager. The HotSync manager is then able to use the MobiLink conduit.

  For instructions, see Adding the MobiLink conduit into HotSync manager.

3	If you did not include a stream_parms parameter in your UltraLite ul_synch_info structure, enter these parameters from the HotSync manager.

  For instructions, see Configuring the conduit communication stream.

  For information on including stream_parms parameter in your UltraLite synchronization call, see Adding HotSync or ScoutSync synchronization to Palm applications.


HotSync conduit files
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring HotSync synchronization

 HotSync conduit files

The HotSync conduit consists of the following files:

•	dbhsync7.dll    The DLL that is called by the HotSync manager.

•	Stream dll    You need a DLL for the communication between the conduit and the MobiLink synchronization server. A separate DLL for each stream is provided:

•	For TCP/IP, use dbsock7.dll.

•	For HTTP, use dbsock7.dll and dbhttp7.dll.

•	For serial communication, use dbser7.dll.

These files should be in the same directory, in your system path. When you install SQL Anywhere Studio, they are installed into the win32 subdirectory of your installation directory.

If you use encryption for this communication, you also need to supply the encryption DLL dbencod7.dll.


Adding the MobiLink conduit into HotSync manager
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring HotSync synchronization

 Adding the MobiLink conduit into HotSync manager

UltraLite includes a command-line conduit installation utility named dbcond7.exe to make a set of registry entries for the HotSync manager to be able to use the MobiLink conduit. This utility requires the following files:

•	dbcond7.exe

•	dbcond7.dll

•	condmgr.dll

The dbcond7.exe and dbcond7.dll must be in the same directory. The SQL Anywhere Studio installation places them in the win32 subdirectory of your installation directory. The condmgr.dll file must be in a subdirectory named condmgr relative to the other two files.

♦ To add the MobiLink HotSync conduit into HotSync manager:

1	Ensure the HotSync conduit files and the files for the conduit installation utility are in place.

2	Run the conduit installation utility, providing the creator ID of the Palm application, and a name that HotSync will use to identify the conduit. For example, the following command installs a conduit for the application with creator ID Syb2, named CustDB. These are the settings for the CustDB sample application:

dbcond7 "Syb2" -n CustDB

  For full syntax of the conduit installation utility, including the options to use when uninstalling a conduit, see HotSync conduit installation utility.


Checking that installation is correct
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring HotSync synchronization

 Checking that installation is correct

♦ To check that the HotSync conduit is properly installed

1	Set the Windows NT environment variable UL_DEBUG_CONDUIT to any value.

2	Shut down and restart the HotSync manager.

3	If the MobiLink conduit is properly installed, two dialog boxes appear. If no dialog appears, the conduit is not properly installed.

4	Unset the Windows NT environment variable.

5	Shut down and restart the HotSync manager.

MobiLink must be started before using HotSync
Before using HotSync, the MobiLink synchronization server must be started and be ready to accept connections from the MobiLink HotSync conduit.


Configuring the conduit communication stream
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring HotSync synchronization

 Configuring the conduit communication stream

The conduit needs to communicate with a MobiLink synchronization server to pass upload and download streams between the UltraLite application and the consolidated database. You can provide the information needed by the conduit to locate the MobiLink synchronization server in a stream_parms member of the UltraLite ul_synch_info structure supplied to PalmExit. If you did not specify a non-null stream_parms value, you can enter the required parameters from the HotSync manager.

If you have Palm Desktop software installed, the Adaptive Server Anywhere installation creates registry entries for the CustDB sample application. You can use these entries as a starting point for your own application.

  For information on stream_parms, see Adding HotSync or ScoutSync synchronization to Palm applications.

♦ To configure the HotSync conduit to communicate with a MobiLink synchronization server:

1	Right-click the HotSync Manager icon in the system tray, and choose Custom from the popup menu.

2	Select your MobiLink conduit from the list of conduit names, and click Change.

3	Enter a set of stream parameters in the text box. These parameters are the same as those in a stream_parms parameter. For example:

stream=tcpip;host=localhost

  For more information, see Setting synchronization parameters.

4	Click OK to complete the entry. The HotSync conduit is now ready to use.

Registry location

The stream parameters are stored in the registry. The location depends on the version of the Palm Computing Platform software you are using. They are made under the HKEY_CURRENT_USER\Software\U.S. Robotics or the HKEY_CURRENT_USER\Software\Palm Computing folder.

  For more detailed information on installing and configuring a conduit, see the Palm Computing Conduit Development Kit Version 3.0.

Location of synchronization log files

The HotSync Manager uses log files to record actions. HotSync writes log information in the user-specific subdirectory User\HotSync.log of your Pilot directory. Here, HotSync records when each synchronization takes place and whether each installed conduit worked as expected.


Configuring ScoutSync synchronization
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

 Configuring ScoutSync synchronization

ScoutSync technology is similar to HotSync. ScoutSync technology allows multiple users to simultaneously synchronize multiple Palm devices with the consolidated database. ScoutSync technology is used in the Palm HotSync Server.

ScoutSync synchronization is initiated from the Palm ScoutSync client, not directly from the UltraLite application. The ScoutSync client communicates with the ScoutSync server, which loads the MobiLink ScoutSync conduit. Each instance of the conduit manages all applications on a single Palm device. Each application can specify its own synchronization conduit. For MobiLink synchronization, the conduit is the MobiLink ScoutSync conduit.

The MobiLink ScoutSync conduit is a COM object. Since a ScoutSync conduit is based on COM, it can be installed on any machine and not only the one running the ScoutSync Application server.

 Configuring the MobiLink ScoutSync conduit

 Setting up for ScoutSync synchronization

 Configuring the ScoutSync Application Server

 Configuring the ScoutSync Client on the Palm device

 Configuring RAS TCP/IP synchronization

 Using ScoutSync for the first time

 Configuring the MobiLink ScoutSync conduit for use with HotSync Manager

 Location of synchronization log files


Configuring the MobiLink ScoutSync conduit
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring ScoutSync synchronization

 Configuring the MobiLink ScoutSync conduit

During ScoutSync synchronization, the ScoutSync Application Server starts the conduit, dbscout7.dll, which passes the upload stream on to a MobiLink synchronization server, and receives the download stream from the MobiLink synchronization server.

The MobiLink ScoutSync conduit synchronizes with MobiLink synchronization server using one of TCP/IP, HTTP, or serial streams. You specify the stream and stream parameters in your UltraLite application PalmExit call or in the ClientParms registry entry.

Registry location

Registry entries are located under HKEY_LOCAL_MACHINE\SOFTWARE\Sybase\UltraLite\ScoutSync\ Creator ID, where Creator ID is the Creator ID of the Palm application. Each application having a different Creator ID will have its own folder.

MobiLink must be started before using ScoutSync
Before performing ScoutSync, the MobiLink synchronization server must be running and be ready to accept connections from the MobiLink ScoutSync conduit.


Setting up for ScoutSync synchronization
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring ScoutSync synchronization

 Setting up for ScoutSync synchronization

In order to perform ScoutSync synchronization, you must perform the following:

•	Configure the ScoutSync Application Server:

•	Setup the MobiLink ScoutSync conduit.

•	Setup a user profile.

•	Configure the ScoutSync Client on the Palm device.

•	Configure RAS for ScoutSync Client to access ScoutSync Application Server via TCP/IP.

•	Optionally configure the MobiLink ScoutSync conduit to work with HotSync manager.


Configuring the ScoutSync Application Server
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring ScoutSync synchronization

 Configuring the ScoutSync Application Server

The following steps cover installation of the ScoutSync conduit on the ScoutSync Application Server.

  For information on the COM properties of the MobiLink ScoutSync conduit and for instructions on how to install it on another machine, see the ScoutSync Multi-Threaded Server Version 3.0 Administrator's Guide.

♦ To setup the MobiLink ScoutSync conduit:

1	Register dbscout7.dll using the following command:

regsvr32 dbscout7.dll

A message box appears, indicating that the registration was successful.

2	Select Start [image] Settings [image] Control Panel [image] Services [image] ScoutSync Service and ensure that ScoutSync is already started.

3	Select Start [image] Programs [image] ScoutSync 3.0 [image] ScoutSync Management Console 3.0 to start the ScoutSync Management console.

4	Connect to the ScoutSync server by selecting Tools [image] Connect to Server in the ScoutSync Management console.

5	Add a new conduit in the ScoutSync Management console. Click the New Conduit button. Alternatively, you can right click on Conduits under Sync Services in the hierarchy tree and select New Conduit. Enter a conduit name ULSync, and set the Conduit Prog ID to ULSctSyn.ULSSCond. Select PalmSyncService under Supported Services.

♦ To setup a user profile:

1	Add a new user profile. Click the New User Profiles button. Alternatively, you can right click on User Profiles in the hierarchy tree and select New User Profile. Click on the User Info Tab and enter a profile name, ULSyncProfile.

2	Click on the Conduits Tab. Select ULSync and click Add. ULSync will be added to the Assigned list.


Configuring the ScoutSync Client on the Palm device
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring ScoutSync synchronization

 Configuring the ScoutSync Client on the Palm device

♦ Configuring the ScoutSync Client on the Palm device

1	Install Scout.prc and ScoutUpdateClient.prc, available under the ScoutSync\Server\Services\PalmSyncService\clients directory of your main Riverbed directory, on the Palm device.

  For information on how to install an application onto the Palm device, see Installing your application on the target device.

2	Configure the ScoutSync Client Preferences settings on the Palm device as described in the following steps. Begin by tapping the Applications silk-screen icon to open the Applications Launcher.

3	Tap the ScoutSync icon to display the main ScoutSync screen.

4	Tap the Preference button located at the bottom of the ScoutSync screen. The ScoutSync Preferences screen appears.

5	Enter the ScoutSync Server Name, Port Number and Profile. The default connection port is 8025 and should not be changed unless instructed to do so by your system administrator.

6	Tap the word Unassigned in the Password field to display the Password box. Enter a password and tap the OK button, if applicable. The word "Assigned" displays after you have entered a password.

7	Tap the More button to display the Advanced Preferences screen.

•	Check the Start Sync On App Launch box to synchronize on application launch.

•	Check the Close Connection After Sync box to close the network connection after a synchronization.

•	Check the Notify About Errors During Sync box to be notified about errors.

•	Check the Check Modem Status Before Sync box if you are using a Novatel Minstrel modem.

8	Tap the OK button on the Advanced Preferences screen to submit your changes.

9	Tap the OK button on the ScoutSync Preferences screen to submit your changes.


Configuring RAS TCP/IP synchronization
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring ScoutSync synchronization

 Configuring RAS TCP/IP synchronization

♦ To configure RAS for ScoutSync Client to access ScoutSync Application Server via TCP/IP

•	For step by step instructions, refer to Configuring RAS TCP/IP synchronization via serial port connection.


Using ScoutSync for the first time
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring ScoutSync synchronization

 Using ScoutSync for the first time

After ScoutSync has been set up, follow these step by step instructions to perform ScoutSync synchronization:

1	Launch the ScoutUpdateClient program on the Palm device. Click on the Update ScoutSync Client button to log onto the ScoutSync server and update your client.

2	Launch the ScoutSync program on the Palm and tap on the ScoutSync icon. An initial ScoutSync is required to download the list of conduits.

1	From the ScoutSync program, tap on the Conduit List icon. You should see the entry ULSync. Make sure that this entry is checked.

Now you are ready to perform ScoutSynchronization from your Palm device.


Configuring the MobiLink ScoutSync conduit for use with HotSync Manager
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring ScoutSync synchronization

 Configuring the MobiLink ScoutSync conduit for use with HotSync Manager

Using the ScoutSync Desktop HotSync Extender (ScoutSync DHE), a ScoutSync conduit can work with HotSync. The ScoutSync DHE is a HotSync conduit that translates between the HotSync API and the ScoutSync API. In this configuration, a ScoutSync server is not needed. The following process is not mandatory but may be useful for some deployments.

♦ To use the ScoutSync Desktop HotSync Extender

1	In order to use the ScoutSync Desktop HotSync Extender, you must first setup the utility as follows:

•	Switch off the Palm HotSync manager if it is currently running.

•	Copy ScoutDHEConduit30.dll and ScoutDHESetup.exe to the Palm install directory.

•	 Open a DOS command prompt and change to the Palm install directory. Execute the following command to register the dll:

regsvr32 ScoutDHEConduit30.dll

A dialog box will appear indicating that the registration was successful.

2	Run the ScoutDHESetup executable from the Palm install directory.

When adding a new entry, ensure that the following fields are entered correctly:

•	Creator ID    Enter the appropriate creator ID.

•	Name    Enter the name of the application, CustDB.

•	ScoutSync Conduit    Enter ULSync.

•	Prog ID    Enter ULSctSyn.ULSSCond.


Location of synchronization log files
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Configuring synchronization for Palm devices

          Configuring ScoutSync synchronization

 Location of synchronization log files

ScoutSync uses log files to record their actions:

•	By default, ScoutSync writes log information into the file session.log in the subdirectory ScoutSync\Server\Users\profile of your main Riverbed directory, where profile is the name of your user profile. Here, ScoutSync records when each synchronization takes place.


Developing for Windows CE
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Developing for Windows CE

This section contains instructions pertaining to building UltraLite applications for use under Microsoft Windows CE.

  For a list of supported host platforms and development tools for Windows CE development, and for a list of supported target Windows CE platforms, see Supported platforms for C/C++ applications.

You can test your applications under an emulator on most Windows CE target platforms.

 Choosing how to link the runtime library

 Preparing for Windows CE development

 Building the CustDB sample application

 Storing persistent data

 Deploying Windows CE applications


Choosing how to link the runtime library
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for Windows CE

 Choosing how to link the runtime library

Windows CE supports dynamic link libraries. At link time, you have the option of linking your UltraLite application to the runtime DLL using an imports library, or statically linking your application using the UltraLite runtime library.

If you have a single UltraLite application on your target device, a statically linked library uses less memory. If you have multiple UltraLite applications on your target device, using the DLL may be more economical in memory use.

If you are repeatedly downloading UltraLite applications to a device, over a slow link, then you may want to use the DLL in order to minimize the size of the downloaded executable, after the initial download.

♦ To build and deploy an application using the UltraLite runtime DLL

1	Preprocess your code, then compile the output with UL_USE_DLL.

2	Link your application using the UltraLite imports library.

3	Copy both your application executable and the UltraLite runtime DLL to your target device.


Preparing for Windows CE development
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for Windows CE

 Preparing for Windows CE development

The following are guidelines for installing Visual C++ 6.0 for Windows CE.

•	Install using the Administrator account or the account that will use the tool as some installs set user environment variables.

•	Use default install directories, whenever possible.

•	Select typical or complete installs.

•	Reboot your machine after each install.

♦ To install a complete Windows CE development environment

1	Install Visual C++ 6.0 for Intel.

•	Let the install modify your environment and registry entries.

2	Install Windows CE Toolkit for Visual C++ 6.0

3	Install Windows CE Services Version 2.2 or later. The latest version is available on the Microsoft web site at the following URL: http://www.microsoft.com/WindowsCE/Products/download/wceserv.asp

4	Reapply Windows NT Service Pack 3 or 4, if necessary, as described in the Windows CE Toolkit readme.

5	Install the latest H/PC Pro SDK and/or the latest PsPC SDK. The latest version is available on the Microsoft Web site at the following URL: http://msdn.microsoft.com/cetools/platform/support.asp

UltraLite version 7.0 targets the latest retail version of Windows CE, namely, Windows CE 2.11.


Building the CustDB sample application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for Windows CE

 Building the CustDB sample application

CustDB is a simple sales-status application. It is located in the UltraLite samples directory of your Adaptive Server Anywhere installation. Generic files are located in the CustDB directory. Files specific to Windows CE are located in the ce subdirectory of CustDB.

  For a diagram of the sample database schema, see The UltraLite sample application.

♦ To build the CustDB sample application

1	Start Visual Studio.

From your desktop in the standard fashion.

2	Open the project.

Open the CECustDB.dsw project file located in the Adaptive Server Anywhere UltraLite\samples\custdb\vc6\CECustDB directory.

3	Build the application.

Press F7 or select Build [image] Build CECustDB.exe

•	Your include path must contain the directory $(ASANY7)\h. The Adaptive Server Anywhere setup program sets the environment variable ASANY7 to your Adaptive Server Anywhere installation directory.

•	You must include $(ASANY7)\UltraLite\ce\mips\lib\ulrt.lib in your linker settings. This library is for a MIPS based CE device. Files for other platforms are in other directories under the ce directory.

•	Select your device using Build [image] Set Active WCE Configuration and Build [image] Set Active Configuration.

These settings are made for you by the Adaptive Server Anywhere setup program, for the CustDB application. For your own projects, you need to make sure the settings are correct.

4	Download the application to the device.

Select Build [image] Update Remote output file.

5	Start the synchronization server on the Windows NT machine.

From the Start menu, select Programs [image] Sybase SQL Anywhere 7 [image] UltraLite [image] UltraLite Sample Database to start the consolidated database server.

To start the MobiLink synchronization server, select Programs [image] Sybase SQL Anywhere 7 [image] Synchronization [image] MobiLink synchronization server sample.

6	Run your application. application.

Press Ctrl+F5 or select Build [image] Execute CustDB.exe

Folder locations and environment variables
The sample project uses environment variables wherever possible. It may be necessary to adjust the project in order for the application to build properly. If you experience problems, try searching for missing files in the MS VC++ folder and adding the appropriate directory settings.

The build process uses the SQL preprocessor, sqlpp, to preprocess the file CustDB.sqc into the file CustDB.c. This one-step process is useful in smaller UltraLite applications where all the embedded SQL can be confined to one source module. In larger UltraLite applications, you need to use multiple sqlpp invocations followed by one ulgen command to create the customized remote database.

  For more information, see Pre-processing your embedded SQL files.


Storing persistent data
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for Windows CE

 Storing persistent data

The UltraLite database is stored in the Windows CE file system. The default file is \UltraLiteDB\ul_<project>.udb, with project being truncated to eight characters. You can override this choice using the file_name parameter which specifies the full pathname of the file-based persistent store.

The UltraLite runtime carries out no substitutions on the file_name parameter. If a directory has to be created in order for the file name to be valid, the application must ensure that any directories are created before calling db_init.

As an example, you could make use of a flash memory storage card by scanning for storage cards and prefixing a name by the appropriate directory name for the storage card. For example,

file_name = "\\Storage Card\\My Documents\\flash.udb"

Example

The following sample embedded SQL code sets the file_name parameter:

#undef UL_STORE_PARMS

#define UL_STORE_PARMS UL_TEXT(

"file_name=\\uldb\\my own name.udb;cache_size=128k" )

...

db_init( &sqlca );


Deploying Windows CE applications
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for Windows CE

 Deploying Windows CE applications

♦ To build and deploy an application using the UltraLite runtime DLL

1	Preprocess your code, then compile the output with UL_USE_DLL.

2	Link your application using the UltraLite imports library.

3	Copy both your application executable and the UltraLite runtime DLL to your target device.


Synchronization on Windows CE
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Synchronization on Windows CE

A Windows CE program controls when synchronization occurs, so the application will usually provide a menu item or GUI control so that the user can request synchronization.

UltraLite for Windows CE supports synchronization over a TCP/IP connection, using TCP/IP or HTTP streams. The device uses the desktop peer that the CE device is physically connected to through the cradle as a default host.

The user_name and stream_parms parameters must be surrounded by the UL_TEXT() macro for Windows CE when initializing, since the compilation environment is Unicode wide characters.

  For information on adding synchronization to your application, see Adding synchronization.


Developing for VxWorks
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Developing for VxWorks

The following instructions pertain to writing and building UltraLite applications for use with the VxWorks platform.

  For a list of supported host platforms and development tools for VxWorks development, and for a list of supported target VxWorks platforms, see Supported platforms for C/C++ applications.

Installation directory
Tornado/VxWorks development tools may not support the use of directories with spaces in the name. As UltraLite header and include files are installed under the Adaptive Server Anywhere installation directory, which by default has spaces, you may wish to reinstall. An alternative is to reset your ASANY7 environment variable to use the short form of the directory name (c:\progra~1\...)

 Features and limitations

 Building the CustDB sample application

 Downloading the sample application to the device

 Running the sample application

 Building your UltraLite VxWorks application

 Storing persistent data


Features and limitations
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for VxWorks

 Features and limitations

Follow the VxWorks Programmer's Guide, Tornado User's Guide as well as BSP-specific documentation for instructions on setting up your system and troubleshooting.

However, you should also note the following when developing UltraLite applications for the VxWorks platform.

Synchronization

You may use TCP/IP for UltraLite synchronization. The TCP/IP components are typically included and initialized by default in VxWorks.

Resolving host names

The default VxWorks configuration does not include resolving of host names via DNS. Therefore, if you use a host name to specify the location of the MobiLink synchronization server for TCP/IP synchronization, you must define INCLUDE_DNS_RESOLVER and associated macros when building VxWorks. However, if you use only the IP number to specify your host machine, you do not need to include DNS support. Without DNS support, you may get a warning regarding an undefined _resolvGetHostByName symbol, but this warning will not affect the running or synchronization of your application as long as only an IP number is used.

Persistent storage

UltraLite requires a dosFs (MS-DOS-compatible file system) device or a functionally equivalent device to store the persistent data file. UltraLite defaults to using a device named ULDEV:. You can configure a storage device with this name and it will be used to store persistent data for the application, or you can override the default filename and specify a different device.

Persistent storage for CustDB sample

If a ULDEV: device does not exist when you run the CustDB sample, the application creates a ULDEV: device using a RAM disk and dosFs file system. The VxWorks RAM disk driver component is required, and you can include the component by defining INCLUDE_RAMDRV when building VxWorks.

  For more information on persistent data storage, see Storing persistent data.


Building the CustDB sample application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for VxWorks

 Building the CustDB sample application

The following are general guidelines for building the sample application included in your Adaptive Server Anywhere installation.

  For instructions on how to build your own UltraLite application, see Building your UltraLite VxWorks application.

CustDB is a simple sales-status application. It has already been built into an executable custdb.out that is located in the UltraLite\vxw\386 subdirectory. Other files specific to the VxWorks platform are located in the UltraLite\samples\CustDB\vxw directory. The gnuvxw.bat file in this subdirectory is a batch file used to build the sample application in embedded SQL or C++ API form, and the custio.c file contains the source code for the user interface of the sample application. The sample application uses standard I/O via printf() and getchar().

  For a diagram of the sample database schema, see The UltraLite sample application.

Although the sample application has already been built into an executable, you can build it yourself by doing the following:

♦ To build the sample application

1	Open a Windows NT Command Prompt window.

2	Run torvars.bat (included with Tornado) to set up the environment to include the Tornado compiler and environment variables. Minimally, you must set your WIND_BASE environment variable.

3	Change to the subdirectory CustDB\vxw, located in the Adaptive Server Anywhere UltraLite\samples directory.

cd "%ASANY7%\UltraLite\samples\custdb\vxw"

4	Run gnuvxw.bat to generate an embedded SQL executable with name custdb.out, or a C++ API executable with the name custdbapi.out.

This command runs the SQL preprocessor (sqlpp.exe) to preprocess the embedded SQL source file custdb.sqc and to generate source code that implements the SQL in the application.


Downloading the sample application to the device
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for VxWorks

 Downloading the sample application to the device

Download the sample application module using the Tornado shell.

Downloading the sample application

The CustDB sample application has been built into an executable custdb.out, located in the UltraLite\vxw\386 subdirectory. You can download this file to VxWorks using the following Tornado shell command:

ld(0,0,"c:/sybase/sa7/ultralite/vxw/386/custdb.out");


Running the sample application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for VxWorks

 Running the sample application

To run the CustDB sample application after downloading, call the custDB function by typing custDB() at the Tornado Shell prompt.

 Viewing the data in the sample application


Viewing the data in the sample application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for VxWorks

          Running the sample application

 Viewing the data in the sample application

When you start the CustDB sample application, the application prompts you for a method of synchronization. Press r if you wish to synchronize via serial communications, t if you wish to synchronize via TCP/IP and d if you wish to use the default method. The default method of synchronization for the sample application is TCP/IP to localhost. Note that the default VxWorks configuration does not automatically map localhost to your host machine and you may have to specify the name or IP address of your machine directly, after typing T.

The application subsequently prompts you for an employee ID. Enter a value of 50. The application also allows values of 51, 52, or 53. After synchronization, a set of customers, products, and orders are downloaded to your target machine.

  For a diagram of the sample database schema, see The UltraLite sample application.

  For information about synchronization, see Synchronization on the VxWorks platform.

Here are some actions you can perform with the sample application:

•	Scroll through the outstanding orders    The application holds information about a set of orders. Scroll forward through the orders by pressing f and scroll backward by pressing b. For each order, this includes the ID number, the customer, the product, the quantity, and other information. Also included are a status column and a notes column, which you can modify from the application. You can approve, deny, add as well as delete an order.

Only unapproved orders for the customers that you list in the ulEmpCust table are downloaded to the application. The sample application does not receive all the orders listed in the ULOrder table in the consolidated database. You control which information is sent to your application using synchronization scripts.

•	Display a list of customers    The UltraLite application holds the complete list of customers from the consolidated database. To see this list, press c.

•	Display a list of products    The UltraLite application holds the complete list of products from the consolidated database. To see this list, press p.

•	Synchronize with the consolidated database    Press s to synchronize with the consolidated database.

•	Display help    Press ? to display a list that indicates which key to press for each task.

Enter keys in lower case
Enter keys in lower case when you perform actions with the sample application.


Building your UltraLite VxWorks application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for VxWorks

 Building your UltraLite VxWorks application

The following are general guidelines for building your own UltraLite application.

  For instructions on how to build the sample application included in your Adaptive Server Anywhere installation, see Building the CustDB sample application.

♦ To build an UltraLite VxWorks application:

1	Start the Adaptive Server Anywhere personal database server, specifying your reference database and a cache size of at least 10 Mb.

2	Preprocess your embedded SQL files using the SQL preprocessor sqlpp. When sqlpp is invoked, a C/C++ source file is generated for each .sqc file.

If you have only one embedded SQL source file, sqlpp automatically runs the UltraLite analyzer in addition to preprocessing the SQL file. The analyzer generates more C/C++ code to implement your application database. You may also skip step 3.

  For more information, refer to Pre-processing your embedded SQL files.

3	Run the UltraLite generator ulgen to perform code generation. The generator creates a C/C++ source file for each project.

  For more information, see Generating the UltraLite data access code.

4	Set up the environment to include the Tornado compiler and environment variables by running torvars.bat.

5	Invoke cc386, the cross compiler for the Intel x86 BSP, to compile all source files. This process will generate a .o file for each C/C++ file. Note that C++ files require use of the munch tool.

  For more information, refer to cross-development in the Tornado User's Guide.

6	Link all the object files along with the runtime library libulrt.a as follows:

ld386 -o myapp.out myapp.o util.o -r -lulrt -L %ASANY7%\ultralite\vxw\386\lib

The runtime library libulrt.a is located in the UltraLite\vxw\386\lib subdirectory. myapp.out will include the .o files (generated by the cc386 compiler) as well as the necessary modules acquired from the runtime library.

Note
ld will look for libulrt.a when -lulrt is specified.

Preserving data when upgrading

When you upgrade an existing UltraLite application, the application database is automatically re-created with no data in any tables. To avoid losing data stored in your UltraLite database, synchronize your existing UltraLite application with the consolidated database before upgrading your application.


Storing persistent data
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for VxWorks

 Storing persistent data

UltraLite requires a dosFs (MS-DOS-compatible file system) device or a functionally equivalent device to store the persistent data. UltraLite defaults to using a device named ULDEV:. Unless you override the default persistent storage filename, this device must exist before db_init is called.

The following lines illustrate how to create such a device using a RAM disk and dosFs file system:

pBlkDev = ramDevCreate( 0, 512, 2048, 2048, 0 );

pVolDesc = dosFsMkfs( "ULDEV:", pBlkDev );

By default, the UltraLite runtime saves persistent data to the file ULDEV:/ul_<project_name>.udb, where the filename ul_<project_name> is truncated to 8 characters.

Overriding the default filename

Rather than using the default filename, you may wish to save persistent data to a file with the name of your choice. Specify the full pathname of this file by using the file_name parameter. Add the following code to your embedded SQL source file:

#undef UL_STORE_PARMS

#define UL_STORE_PARMS UL_TEXT(

"file_name=/dev1/mydir/myfile.udb")

...

db_init(&sqlca);

You must ensure that the directories in the pathname are created before db_init is called.

Defining the cache size

You can also set the size of the file cache, used to improve performance of persistent data storage, in the UL_STORE_PARMS macro. The following code sets the cache size to 128 kb:

#define UL_STORE_PARMS \

UL_TEXT( "file_name=/dev1/mydir/myfile.udb;cache_size=128k" )

Reserving file system space for storage of UltraLite persistent data

The reserve_size parameter allows you to pre-allocate the file system space required for your UltraLite database without actually inserting any data.

Use the reserve_size parameter to pre-allocate space as follows:

#define UL_STORE_PARMS	 UL_TEXT( "reserve_size=2m" )

This example ensures that the persistent store file is at least 2 Mb upon startup.

  For more information on persistent-storage parameters, see Configuring file-based persistent storage.

Persistent Storage for CustDB sample

If a ULDEV: device does not exist when you run the CustDB sample, the application will create a ULDEV: device using a RAM disk and dosFs file system. The VxWorks RAM disk driver component is required, and you can include the component by defining INCLUDE_RAMDRV when building VxWorks.


Synchronization on the VxWorks platform
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Synchronization on the VxWorks platform

The VxWorks UltraLite applications can synchronize via TCP/IP.

  For information on synchronization architecture for TCP/IP and serial communications, see Parts of the synchronization system.

To synchronize a VxWorks UltraLite application using a TCP/IP socket connection, call ULSynchronize with the ULSocketStream() stream. The following embedded SQL example illustrates the arguments:

auto ul_synch_info synch_info;

ULInitSynchInfo( &synch_info );

synch_info.user_name = UL_TEXT( "50" );

synch_info.version = UL_TEXT( "custdb" );

synch_info.stream = ULSocketStream();

synch_info.stream_parms =

UL_TEXT("host=localhost");

ULSynchronize( &synch_info );

When using TCP/IP sockets, the MobiLink synchronization server can be any machine on the network that is accessible via TCP/IP. Before ULSynchronize is called, the MobiLink synchronization server must be started as follows:

dbmlsrv7 -c "DSN=UltraLite Sample;UID=dba;PWD=sql" ...

By default, the MobiLink synchronization server listens on port 2439.

Synchronization for CustDB sample application

TCP/IP is the default method of synchronization for the CustDB sample application. In addition, UltraLite specifies localhost as the hostname by default. Note that the default VxWorks configuration does not automatically map localhost to your host machine and you may need to specify the name or IP address of your machine explicitly.

Transport-layer security on VxWorks

You can use transport-layer security on VxWorks on Intel x86 chips and on the Windows VxSim emulator.

  For information on transport-layer security, see Transport-layer security. For information on synchronization parameters, see Setting synchronization parameters.

You must ensure that the time is set properly on the client VxWorks device, as certificate dates are checked during synchronization. The time is not set automatically on VxWorks devices. You can set the time on the device by using the clock_settime() function. When the time is incorrect, MobiLink returns the message Error: Incomplete upload stream.


Developing for DOS
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Developing for DOS

The following instructions pertain to writing and building UltraLite applications for use with the DOS Platform.

  For a list of supported host platforms and development tools for DOS development, and for a list of supported target DOS platforms, see Supported platforms for C/C++ applications.

 Features and limitations

 Building the CustDB sample application

 Running the sample application

 Storing persistent data

 Building your UltraLite application

 Downloading an application to the device


Features and limitations
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for DOS

 Features and limitations

Storage

On DOS, the UltraLite database is file system based, and persistent data is stored to a hard drive.

  For more information on file-based database storage, see Database storage mechanism.

Specifying storage parameters

Specify parameters to control the configuration of the UltraLite persistent storage mechanism. You can define the file cache size, reserve file system space for storing persistent data, and select the path and file name of the file-based persistent data store.

To specify storage parameters, define the UL_STORE_PARMS macro in the header of your application source code. The following statements set the cache size to 128 kb, store persistent data to the file /mydir/myfile.udb, and ensures that the persistent store file is at least 2 Mb upon startup:

#undef UL_STORE_PARMS

#define UL_STORE_PARMS

UL_TEXT(

"file_name=/mydir/myfile.udb;cache_size=128k;

reserve_size=2m" )

...

db_init( &sqlca );

You must ensure that the directories in the pathname are created before db_init is called.

  For more information on persistent-storage parameters, see Configuring file-based persistent storage.

Data type limitations

Visual C++ 1.52c is a 16-bit compiler that does not support 64-bit integers and you cannot use the BIGINT SQL data type in your UltraLite database.


Building the CustDB sample application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for DOS

 Building the CustDB sample application

The following are general guidelines for building the sample application included in your Adaptive Server Anywhere installation. For instructions on how to build your own UltraLite application, see Building your UltraLite application.

CustDB is a simple sales-status application. It has been built into an executable custdb.exe that is located in the UltraLite\dos\x86 subdirectory. Other files specific to the DOS platform are located in the UltraLite\samples\CustDB\dos directory. The msdos.bat file in this subdirectory is a batch file used to build the sample application, and the custio.c file contains the source code for the user interface of the sample application. The sample application uses standard I/O such as printf() and getchar().

  For a diagram of the sample database schema, see The UltraLite sample application.

Although the sample application has already been built into an executable, you can build it yourself by doing the following:

♦ To build the sample application

1	Start a DOS command prompt.

2	Change to the subdirectory CustDB\dos, located in the Adaptive Server Anywhere UltraLite\samples directory.

cd "%ASANY7%\UltraLite\samples\CustDB\dos"

3	You must add the following environment variables to your PC:

•	MSVC. Set this variable to the directory in which you installed Visual C++ v.1.52c.

•	PCTCP. Set this variable to the directory in which you installed FTP.

4	Run msdos.bat to generate an executable with name custdb.exe.

This command runs the SQL preprocessor (sqlpp.exe) to preprocess the embedded SQL source file custdb.sqc and to generate source code that implements the SQL in the application.


Running the sample application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for DOS

 Running the sample application

To run the CustDB sample application, call the custDB function by typing CustDB at the DOS command prompt.

 Viewing the data in the sample application


Viewing the data in the sample application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for DOS

          Running the sample application

 Viewing the data in the sample application

When you start the CustDB sample application, the application prompts you for the TCP/IP address of your host machine in order to start synchronization. The application subsequently prompts you for an employee ID. Enter a value of 50. The application also allows values of 51, 52, or 53. After synchronization, a set of customers, products, and orders are downloaded to your target machine.

  For a diagram of the sample database schema, see The UltraLite sample application.

  For information about synchronization, see Synchronization on the DOS platform.

Here are some actions you can perform with the sample application:

•	Scroll through the outstanding orders    The application holds information about a set of orders. Scroll forward through the orders by pressing f and scroll backward by pressing b. For each order, this includes the ID number, the customer, the product, the quantity, and other information. Also included are a status column and a notes column, which you can modify from the application. You can approve, deny, add as well as delete an order.

Only unapproved orders for the customers that you list in the ulEmpCust table are downloaded to the application. The sample application does not receive all the orders listed in the ULOrder table in the consolidated database. You control which information is sent to your application using synchronization scripts.

•	Display a list of customers    The UltraLite application holds the complete list of customers from the consolidated database. To see this list, press c.

•	Display a list of products    The UltraLite application holds the complete list of products from the consolidated database. To see this list, press p.

•	Synchronize with the consolidated database    Press s to synchronize with the consolidated database.

•	Display help    Press ? to display a list that indicates which key to press for each task.

Enter keys in lower case
Enter keys in lower case when you perform actions with the sample application.


Storing persistent data
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for DOS

 Storing persistent data

The UltraLite database is stored in the DOS file system. By default, the file is held in the working directory of the application. Its name is ul_<project>.udb, with project being truncated to eight characters You can override this choice using the file_name parameter, which specifies the full pathname of the file-based persistent store.

The UltraLite runtime carries out no substitutions on the file_name parameter. If a directory has to be created in order for the file name to be valid, the application must ensure that any directories are created before calling db_init.

As an example, you could make use of a flash memory storage card by scanning for storage cards and prefixing a name by the appropriate directory name for the storage card. For example,

file_name = "C:\\ULApp\\uldata.udb"

Example

The following sample code sets the file_name parameter:

#undef UL_STORE_PARMS

#define UL_STORE_PARMS UL_TEXT( "file_name=c:\\ulapp\\uldata.udb;cache_size=128k" )

...

db_init( &sqlca );


Building your UltraLite application
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for DOS

 Building your UltraLite application

The following are general guidelines for building your own UltraLite application. For instructions on how to build the sample application included in your Adaptive Server Anywhere installation, see Building the CustDB sample application.

♦ To build an UltraLite application

1	Start the Adaptive Server Anywhere personal database server, specifying your reference database and a cache size of at least 10 Mb.

2	Preprocess your embedded SQL files using the SQL preprocessor sqlpp. When sqlpp is invoked, a C/C++ source file is generated.

3	If you have only one embedded SQL source file, sqlpp automatically runs the UltraLite analyzer in addition to preprocessing the SQL file. The analyzer generates more C/C++ code to implement your application database. You may also skip step 3.

  For more information, see Pre-processing your embedded SQL files.

4	Run the UltraLite generator ulgen to perform code generation. The generator creates a C/C++ source file.

  For more information, see Generating the UltraLite data access code.

5	Use Microsoft Visual C++ to compile all source files.

6	Link all source files with runtime library ulrt.lib using Microsoft Visual C++. The runtime library ulrt.lib is located in the UltraLite\dos\x86\lib subdirectory. If you are using the FTP software, you must also link source files with the runtime libraries: ldomain.lib, lpc.lib, lsocket.lib, lnetlib.lib, and lconfig.lib. If you are building an UltraLite application for use on the Symbol device and synchronizing via TCP/IP, you must also link source files with the runtime library llibsock.lib from the Network Development Kit.

  For instructions on compiling and linking, refer to the Microsoft Visual C++ user's guide.

Preserving data when upgrading

When you upgrade an existing UltraLite application, the application database is automatically re-created with no data in any tables. To avoid losing data stored in your UltraLite database, synchronize your existing UltraLite application with the consolidated database before upgrading your application.


Downloading an application to the device
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Developing for DOS

 Downloading an application to the device

The UltraLite application can be installed on devices such as the Symbol handheld device. The installation process is device specific. For information on how to download your application to the target device, refer to the device user guide.


Synchronization on the DOS platform
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

 Synchronization on the DOS platform

Target devices can synchronize via TCP/IP communications. The following section discusses how to utilize this technique.

  For information on synchronization architecture for TCP/IP, see Parts of the synchronization system.

 Synchronization via TCP/IP


Synchronization via TCP/IP
  UltraLite  Developer's Guide

    PART 2. Developing UltraLite Applications in C/C++

      CHAPTER 11.  Platform-Specific Development

        Synchronization on the DOS platform

 Synchronization via TCP/IP

To synchronize a DOS UltraLite application using a TCP/IP socket connection, call ULSynchronize. To synchronize using the FTP software, supply the special ULFTPSocketStream() value, as follows:

auto ul_synch_info synch_info;

ULInitSynchInfo( &synch_info );

synch_info.user_name = UL_TEXT( "50" );

synch_info.version = UL_TEXT( "custdb" );

synch_info.stream = ULFTPSocketStream();

synch_info.stream_parms =

UL_TEXT("host=server-name");

ULSynchronize( &synch_info );

To synchronize a DOS UltraLite application for the Symbol device, supply the special ULSymbolSocketStream() value, as follows:

auto ul_synch_info synch_info;

ULInitSynchInfo( &synch_info );

synch_info.user_name = UL_TEXT( "50" );

synch_info.version = UL_TEXT( "custdb" );

synch_info.stream = ULSymbolSocketStream();

synch_info.stream_parms =

UL_TEXT("host=localhost");

ULSynchronize( &synch_info );

Always specify a host
When synchronizing by means of TCP/IP from the target device, you must specify an explicit host name or IP number. Specifying null does not work.

When using TCP/IP sockets, the MobiLink synchronization server can be any machine on the network that is accessible via TCP/IP. Before ULSynchronize is called,

1	Ensure the device has a connection to the machine running the MobiLink synchronization server. A connection may require placing the device in a cradle, or attaching a serial cable.

2	The MobiLink synchronization server must be started. By default, the MobiLink synchronization server listens on port 2439.

3	The target device must have Network and Modem settings in place so that it can connect to the network.


PART 3. Developing UltraLite Applications in Java
  UltraLite  Developer's Guide

 PART 3. Developing UltraLite Applications in Java

This part describes the development of applications written in Java.  	It explains how to write and build Java applications and provides a tutorial  	that guides you through the development process.

 CHAPTER 12.  An UltraLite Java Tutorial

 CHAPTER 13.  Developing UltraLite Java Applications


CHAPTER 12.  An UltraLite Java Tutorial
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

 CHAPTER 12.  An UltraLite Java Tutorial

About this chapter

This chapter provides a tutorial that guides you through the process of developing a Java UltraLite application. The first section describes how to build a very simple Java UltraLite application. The second section describes how to add synchronization to your application.

  For an overview of the development process and background information on the UltraLite database, see UltraLite Overview.

  For information on developing Java UltraLite Applications, see Developing UltraLite Java Applications.

 Introduction

 Lesson 1: Add SQL statements to your reference database

 Lesson 2: Run the UltraLite generator

 Lesson 3: Write the application code

 Lesson 4: Build and run the application

 Lesson 5: Add synchronization to your application

 Lesson 6: Undo the changes you have made


Introduction
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 12.  An UltraLite Java Tutorial

 Introduction

This tutorial describes how to construct a very simple application using UltraLite Java. The application is a command-line application, developed using the Sun JDK, which queries data in the ULProduct table of the UltraLite 7.0 Sample database.

In this tutorial, you create a Java source file, create a project in a reference database, and use these sources to build and run your application. The early lessons describe a version of the application without synchronization. Synchronization is added in a later lesson.

This tutorial assumes that you have UltraLite installed on Windows 95/98/NT. To follow the tutorial, you should have a Java Development Kit installed.

 Tutorial overview

 Create a directory to hold your files


Tutorial overview
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 12.  An UltraLite Java Tutorial

        Introduction

 Tutorial overview

In the first lesson, you write and build an application that carries out the following tasks.

1	Connects to an UltraLite database, consisting of a single table. The table is a subset of the ULProduct table of the UltraLite Sample database.

2	Inserts rows into the table. Initial data is usually added to an UltraLite application by synchronizing with a consolidated database. Synchronization is added later in the chapter.

3	Writes the rows of the table to standard output.

In order to build the application, you must carry out the following steps:

1	Create an Adaptive Server Anywhere reference database.

Here we use the UltraLite sample database (CustDB).

2	Add the SQL statements to be used in your application to the reference database.

3	Run the UltraLite generator to generate the Java code and also an additional source file for this UltraLite database.

The generator writes out a .java file holding the SQL statements, in a form you can use in your application, and a .java file holding the code that executes the queries.

4	Write source code that implements the logic of the application.

Here, the source code is a single file, named Sample.java.

5	Compile and run the application.

In the second lesson you add synchronization to your application.


Create a directory to hold your files
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 12.  An UltraLite Java Tutorial

        Introduction

 Create a directory to hold your files

In this tutorial, you will be creating a set of files, including source files and executable files. You should make a directory to hold these files. In addition, you should make a copy of the UltraLite sample database so that you can work on it, and be sure you still have the original sample database for other projects.

♦ To prepare a tutorial directory:

1	Create a directory to hold the files you will create. In the remainder of the tutorial, we assume that this directory is c:\JavaTutorial.

2	Make a backup copy of the UltraLite 7.0 Sample database into the tutorial directory. The UltraLite 7.0 Sample database is the file custdb.db, in the UltraLite\Samples\CustDB subdirectory of your SQL Anywhere installation directory. In this tutorial, we use the original UltraLite 7.0 Sample database, and at the end of the tutorial you can copy the untouched version from the APITutorial directory back into place.


Lesson 1: Add SQL statements to your reference database
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 12.  An UltraLite Java Tutorial

 Lesson 1: Add SQL statements to your reference database

The reference database for this tutorial is the UltraLite 7.0 Sample database. In a later step, you use this same directory as a consolidated database for synchronization. These two uses are separate, and in your work you may use different databases for the two roles.

Add the SQL statements to the reference database using the ul_add_statement stored procedure. In this simple application, use the following statements:

•	Insert    An INSERT statement adds an initial copy of the data into the ULProduct table. This statement is not needed when synchronization is added to the application.

•	Select    A SELECT statement queries the ULProduct table.

When you add a SQL statement, you must associate it with an UltraLite project. Here, we use a project name of Product. You must also add a name for the statement, which by convention is in upper case.

♦ To add the SQL statements to the reference database:

1	Start Sybase Central, and connect to the UltraLite 7.0 Sample data source.

2	Add a project to the database.

•	In Sybase Central, open the custdb database.

•	Open the UltraLite projects folder.

The folder contains one project already: the custapi project used for the sample application. You must create a new project.

•	Double-click Add UltraLite Project.

•	Enter Product as the project name, and click OK.

3	Add the INSERT statement to the Product project.

•	Double-click Product to open the project.

•	Double-click Add UltraLite Statement.

•	Enter InsertProduct as the statement name. Click Next.

•	Enter the statement text:

INSERT INTO ULProduct ( prod_id, price, prod_name)

VALUES (?,?,?)

The first argument is the project name, the second is the statement name, and the third is the SQL statement itself. The question marks in the SQL statement are placeholders, and you can supply values at runtime.

•	Click Finish to complete the operation.

This operation in Sybase Central is equivalent to executing the following stored procedure call:

call ul_add_statement( 'Product', 'InsertProduct',

   'INSERT INTO ULProduct( prod_id, price, prod_name)

    VALUES (?,?,?) ' )

4	Add the SELECT statement to the Product project.

•	From the Product project, double-click Add UltraLite Statement.

•	Enter SelectProduct as the statement name. Click Next.

•	Enter the statement text:

SELECT prod_id, prod_name, price FROM ULProduct

•	Click Finish to complete the operation.

This operation in Sybase Central is equivalent to executing the following stored procedure call:

call ul_add_statement( 'Product', 'SelectProduct',

  'SELECT prod_id, prod_name, price FROM ULProduct')

5	Close Sybase Central.

You have now added the SQL statements to the database, and you are ready to generate the UltraLite database.

  For more information, see ul_add_project system procedure, and ul_add_statement system procedure.


Lesson 2: Run the UltraLite generator
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 12.  An UltraLite Java Tutorial

 Lesson 2: Run the UltraLite generator

The UltraLite generator writes out two Java files. One contains the SQL statements, as an interface definition, which is here named ISampleSQL.java. You can use this interface definition in your main application code. The second file holds the code that implements the queries and the database, and is here named SampleDB.java.

♦ To generate the UltraLite database code:

1	Open a command prompt, and go to the JavaTutorial directory.

2	Run the UltraLite generator with the following arguments (all on one line):

ulgen -a -t java -c "dsn=UltraLite 7.0 Sample"

-j Product -s ISampleSQL -f SampleDB

The arguments have the following meanings:

•	-a    Generate SQL string names in upper case. The InsertProduct and SelectProduct statements come to INSERT_PRODUCT and SELECT_PRODUCT.

•	-t    The language of the generated code. Generate Java code instead of C code.

•	-c    The connection string to connect to the database.

•	-j    The UltraLite project name. This name corresponds to the project name you provided when you added the SQL statement to the database. The generator produces code only for those statements associated with this project.

•	-s    The name of the interface that contains the SQL statements as strings.

•	-f    The name of the file that holds the generated database code and query execution code.


Lesson 3: Write the application code
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 12.  An UltraLite Java Tutorial

 Lesson 3: Write the application code

The following code listing holds a very simple UltraLite application.

You can copy the code into a new file and save it as Sample.java in your c:\JavaTutorial directory, or open a new file and type the content.

// (1) Import required packages

import java.sql.*;

import ISampleSQL.*;

import com.sybase.asa.ultralite.jdbc.*;

import com.sybase.asa.ultralite.support.*;

// (2) Class implements the interface containing SQL statements

public class Sample implements ISampleSQL

{

  public static void main( String[] args )

  {

    try{

        // (3) Connect to the database

        java.util.Properties p = new

            java.util.Properties();

        p.put( "persist", "file" );

        SampleDB db = new SampleDB( p );

        Connection conn = db.connect();

        // (4) Initialize the database with data

        PreparedStatement pstmt1 =

            conn.prepareStatement( INSERT_PRODUCT );

        pstmt1.setInt(1, 1);

        pstmt1.setInt(2, 400);

        pstmt1.setString(3, "4x8 Drywall x100");

        int rows1=pstmt1.executeUpdate();

        pstmt1.setInt(1, 2);

        pstmt1.setInt(2, 3000);

        pstmt1.setString(3, "8' 2x4 Studs x1000");

        int rows2=pstmt1.executeUpdate();

        // (5) Query the data and write out the results

        Statement stmt = conn.createStatement();

        ResultSet result = stmt.executeQuery(

             SELECT_PRODUCT );

        while( result.next() ) {

            int id = result.getInt( 1 );

            String name = result.getString( 2 );

            int price = result.getInt( 3 );

            System.out.println ( name +

                " \tId=" + id +

                " \tPrice=" + price );

        }

        // (6) Close the connection to end

        conn.close();

    } catch (SQLException e) {

        Support.printException( e );

    }

  }

}

Explanation of the sample program

Although too simple to be useful, this example contains elements that must be present in all Java programs used for database access. The following describes the key elements in the sample program. Use these steps as a guide when creating your own Java UltraLite application.

The numbered steps correspond to the numbered comments in the source code.

1	Import required packages.

The sample program utilizes JDBC interfaces and classes and therefore must import this package. It also requires the UltraLite runtime classes, and the generated interface that contains the SQL statement strings.

2	Define the class.

The SQL statements used in the application are stored in a separate file, as an interface. The class must declare that it implements the interface to be able to use the SQL statements for the project. The class names are based on the statement names you provided when adding the statements to the database.

3	Connect to the database.

The connection is established using an instance of the database class. The database name must match the name of the generated Java class (in this case SampleDB). The file value of the persist Properties object states that the database should be persistent.

4	Insert sample data.

In a production application, you would generally not insert sample data. Instead, you would obtain an initial copy of data by synchronization. In the early stages of development, it can simplify your work to directly insert data.

•	Create a PreparedStatement object using the prepareStatement() method.

•	To execute SQL commands, you must create a Statement or PreparedStatement object. Use a Statement object to execute simple SQL commands without any parameters and a PreparedStatement object to execute SQL commands with parameters. The sample program first creates a PreparedStatement object to execute an insert command:

PreparedStatement pstmt1 =

conn.prepareStatement( INSERT_PRODUCT );

The prepareStatement method takes a SQL string as an argument; this SQL string is included from the generated interface.

5	Execute a select SQL command using a Statement object

•	Create a Statement object using the createStatement() method.

Unlike the PreparedStatement object, you do not need to supply a SQL statement when you create a Statement object. Therefore, a single Statement object can be used to execute more than one SQL statement.

Statement stmt = conn.createStatement();

•	Execute your SQL query.

Use the executeQuery() method to execute a select query. A select statement returns a ResultSet object.

•	Implement a loop to sequentially obtain query results.

The ResultSet object maintains a cursor that initially points just before the first row. The cursor is incremented by one row each time the next() method is called. The next() method returns a true value when the cursor moves to a row with data and returns a false value when it has moved beyond the last row.

while(result.next()) {

...

}

•	Retrieve query results using the getxxx() methods.

Supply the column number as an argument to these methods. The sample program uses the getInt() method to retrieve the product ID and price from the first and second columns respectively, and the getString() method to retrieve the product name from the third.

int id = result.getInt( 1 );

int price = result.getInt( 2 );

String name = result.getString( 3 );

6	End your Java UltraLite program

•	Close the connection to the database, using the Connection.close() method:

conn.close();


Lesson 4: Build and run the application
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 12.  An UltraLite Java Tutorial

 Lesson 4: Build and run the application

After you have created a source file Sample.java using the sample code in the previous section, you are ready to build your UltraLite application.

♦ To build your application:

1	Start the Adaptive Server Anywhere personal database server.

By starting the database server, the UltraLite generator has access to your reference database. Start the database server from the Start menu:

Start [image] Programs [image] Sybase SQL Anywhere 7 [image] UltraLite [image] UltraLite Sample database.

2	Compile your Java source files.

Include the following locations in your classpath:

•	The current directory (use a dot in your classpath).

•	The Java runtime classes. For JDK 1.2, include the jre\lib\rt.jar file in your classpath. For JDK 1.1, include the classes.zip file from your Java installation.

•	The UltraLite runtime classes. These classes are in the following location

%ASANY7%\UltraLite\java\lib\ulrt.jar

where ASANY7 represents your SQL Anywhere directory.

Use the javac function of the Java development kit as follows:

javac *.java

You are now ready to run your application.

♦ To run your application:

1	Go to a command prompt in the Javatutorial directory.

2	Include the same classes in the classpath as in the earlier step.

3	Enter the following command to run the application

java Sample

The list of two items is written out to the screen, and the application terminates.

You have now built and run your first UltraLite Java application. The next step is to add synchronization to the application.


Lesson 5: Add synchronization to your application
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 12.  An UltraLite Java Tutorial

 Lesson 5: Add synchronization to your application

Once you have tested that your program is functioning properly, you can remove the lines of code that manually insert data into the ULProduct table. Replace these statements with a call to the JdbcConnection.synchronize() function to synchronize the remote database with the consolidated database. This process will fill the tables with data and you can subsequently execute a select query.

Adding synchronization actually simplifies the code. Your initial version of Sample.java uses the following lines to insert data into your UltraLite database.

PreparedStatement pstmt1 = conn.prepareStatement( ADD_PRODUCT_1 );

pstmt1.setInt(1, 1);

pstmt1.setInt(2, 400);

pstmt1.setString(3, "4x8 Drywall x100");

int rows1=pstmt1.executeUpdate();

pstmt1.setInt(1, 2);

pstmt1.setInt(2, 3000);

pstmt1.setString(3, "8' 2x4 Studs x1000");

int rows2=pstmt1.executeUpdate();

This code is included to provide an initial set of data for your application. In a production application, you would not insert an initial copy of your data from source code, but would carry out a synchronization.

♦ To add synchronization to your application:

1	Replace the hard-coded inserts with a synchronization call.

•	Delete the instructions listed above, which insert code.

•	Add the following line in their place:

UlSynchOptions synch_opts = new UlSynchOptions();

synch_opts.setUserName( "50" );

synch_opts.setScriptVersion( "custdb" );

synch_opts.setStream( new UlSocketStream() );

synch_opts.setStreamParms( "host=localhost" );

( (JdbcConnection)conn ).synchronize( synch_opts );

The ULSocketStream argument instructs the application to synchronize over TCP/IP, to a MobiLink server on the current machine (localhost), using a MobiLink user name of 50.

2	Compile and link your application.

Enter the following command, with a CLASSPATH that includes the current directory, the UltraLite runtime classes, and the Java runtime classes:

javac *.java

3	Start the MobiLink synchronization server running against the sample database.

From a command prompt in your JavaTutorial directory, enter the following command:

start dbmlsrv7 -c "dsn=UltraLite 7.0 Sample"

4	Run your application.

From a command prompt in your JavaTutorial directory, enter the following command:

java Sample

The application connects, synchronizes to receive data, and writes out information to the command line. The output is as follows:

Connecting to server:port = localhost(a.b.c.d):2439

4x8 Drywall x100        Id=1    Price=400

8' 2x4 Studs x1000      Id=2    Price=3000

Drywall Screws 10lb     Id=3    Price=40

Joint Compound 100lb    Id=4    Price=75

Joint Tape x25x500      Id=5    Price=100

Putty Knife x25         Id=6    Price=400

8' 2x10 Supports x 200  Id=7    Price=3000

400 Grit Sandpaper      Id=8    Price=75

Screwmaster Drill       Id=9    Price=40

200 Grit Sandpaper      Id=10   Price=100

In this lesson, you have added synchronization to a simple UltraLite application.

  For more information on the JdbcConnection.synchronize() function, see Adding synchronization to your application.


Lesson 6: Undo the changes you have made
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 12.  An UltraLite Java Tutorial

 Lesson 6: Undo the changes you have made

To complete the tutorial, you should shut down the MobiLink synchronization server and restore the UltraLite 7.0 Sample database.

♦ To finish the tutorial:

1	Close down the MobiLink synchronization server.

2	Restore the UltraLite 7.0 Sample database.

•	Delete the custdb.db and custdb.log files in the UltraLite\samples\custdb subdirectory of your SQL Anywhere directory.

•	Copy the custdb.db file from your Javatutorial directory to the UltraLite\samples\custdb directory.

3	Delete the UltraLite database.

•	The UltraLite database is in the same directory as the jar file, and has a .udb extension. The application will initialize a new database next time the application is run.


CHAPTER 13.  Developing UltraLite Java Applications
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

 CHAPTER 13.  Developing UltraLite Java Applications

About this chapter

This chapter provides details of the UltraLite development process that are specific to Java. It explains how to write UltraLite applications using Java and provides instructions on building and deploying a Java UltraLite application.

Before you begin

This chapter assumes that you are familiar with Java programming and JDBC at an elementary level. You can learn about Java from the book Thinking in Java, included with SQL Anywhere Studio in PDF format.

 Introduction

 The UltraLite Java sample application

 Connecting to and configuring your UltraLite database

 Including SQL statements in UltraLite Java applications

 Adding synchronization to your application

 UltraLite Java development notes

 Building UltraLite Java applications


Introduction
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

 Introduction

UltraLite applications can be written in the Java language using JDBC for database access.

The UltraLite development process for Java is similar to that for other development models. For a description, see Developing UltraLite applications.

This chapter describes only those aspects of application development that are specific to UltraLite Java applications. It assumes an elementary familiarity with Java and JDBC.


The UltraLite Java sample application
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

 The UltraLite Java sample application

This section describes how to compile and run the UltraLite Java version of the CustDB sample application.

The sample application is provided in compiled form in the UltraLite\java subdirectory of your SQL Anywhere directory.

The applet version of the sample uses the Sun appletviewer to view the file custdb.html, which contains a simple <APPLET> tag.

The appletviewer security restrictions require the applet to be downloaded from a Web server, rather than to be run off the file system, for socket connections to be permitted and synchronization to succeed.

The runapplet.bat file that start the applet also starts up a small Web server configured to serve up the required files. You can use your own Web server instead, but you must then copy custdb.jar and ulrt.jar into the right directories on the server.

The application version of CustDB persists its data to a file, while the applet version does not use persistence.

  For a walkthrough of the C/C++ version of the application, which has very similar features, see Tutorial: A Sample UltraLite Application.

 The UltraLite Java sample code

 Building the UltraLite Java sample

 Running the UltraLite Java sample


The UltraLite Java sample code
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        The UltraLite Java sample application

 The UltraLite Java sample code

The code for the UltraLite Java sample application is held in the Ultralite\Samples\CustDB\java subdirectory of your SQL Anywhere directory.

The directory holds the following files:

•	Data access code    The file CustDB.java holds the UltraLite-specific data access logic. The SQL statements are stored in SQL.sql.

•	User interface code    The files DialogDelOrder.java, Dialogs.java, DialogNewOrder.java, and DialogUserID.java all hold user interface features.

•	Batch files to build the application    The files build.bat and clean.bat compile the application and delete all files except the source files, respectively.

•	Files to run the sample as an application    The Application.java file contains instructions necessary for running the example as a Java application, and run.bat runs the sample application.

•	Files to run the sample as an applet    The Applet.java file contains instructions necessary for running the example as a Java applet, and runapplet.bat runs the sample applet, using custdb.html as the Web page.

Applets require a Web server. The files MiniWebServer.java and StopWebServer.java implement a Web server, for use with the applet.


Building the UltraLite Java sample
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        The UltraLite Java sample application

 Building the UltraLite Java sample

This section describes how to build the UltraLite Java sample application for the Sun Java 2 environment. You can also build the sample application for JDK 1.1, using version 1.1.4 or later. For this case, the batch file names have 11 appended to their names (build11, run11, runapplet11).

♦ To build the UltraLite Java sample:

1	Ensure you have the right JDK.

You must have JDK 1.2 to build the sample application, and the JDK tools must be in your path.

2	Open a command prompt.

3	Change to the UltraLite\samples\CustDB\java subdirectory of your SQL Anywhere directory.

4	Build the sample.

From the command prompt, enter the following command:

build

The build procedure carries out the following operations:

•	Loads the SQL statements into the UltraLite sample database.

This step uses Interactive SQL, the SQL.sql file, and relies on the UltraLite 7.0 Sample data source.

•	Generates the Java database class custdb.Database.

This step uses the UltraLite generator and the UltraLite 7.0 Sample data source.

•	Compiles the Java files.

This step uses the JDK compiler (javac) and jar utility.


Running the UltraLite Java sample
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        The UltraLite Java sample application

 Running the UltraLite Java sample

You can run the sample application as a Java application or as an applet. In either case, you need to prepare to run the sample by starting the MobiLink synchronization server running on the same machine that the application is running on.

♦ To prepare to run the sample:

•	Start the MobiLink synchronization server running on the UltraLite sample database.

From the Start menu, choose Programs [image] Sybase SQL Anywhere 7 [image] Synchronization [image] MobiLink Synchronization Server Sample.

♦ To run the sample as an application:

1	Open a command prompt in the UltraLite\samples\CustDB\java directory.

2	Enter the following command:

run

The application starts and the Enter ID dialog is displayed.

3	Enter the employee ID.

Enter an employee ID of 50, and click OK.

The UltraLite Customer Demonstration window is displayed. If you have run the sample as either an application or applet before, there is data in the database.

4	If there is no data in the database, synchronize.

From the Actions menu, choose Synchronize. The application synchronizes, and the window displays an order.

You can now carry out operations on the data in the database.

  For more information on the sample database and the UltraLite features it demonstrates, see Tutorial: A Sample UltraLite Application.

♦ To run the sample as an applet:

1	Open a command prompt in the UltraLite\samples\CustDB\java directory.

2	Enter the following command:

runapplet

The batch file carries out the following operations:

•	Starts a mini Web server, which serves the applet to the client.

•	Starts the appletviewer as the client, using custdb.html as its Web page.

•	The applet starts and a field to enter an employee ID is displayed.

3	Enter the employee ID.

Enter an employee ID of 50, and click OK.

The UltraLite Customer Demonstration window is displayed. The first time you run the sample, there is no data in the database. If you have run the sample as either an application or applet before, there is data in the database.

4	If there is no data in the database, synchronize.

From the Actions menu, choose Synchronize. The application synchronizes, and the window displays an order.

You can now carry out operations on the data in the database.

  For more information on the sample database and the UltraLite features it demonstrates, see Tutorial: A Sample UltraLite Application.

Resetting the sample

You can delete all compiled files, the sample database, and the generated code by running the clean.bat file.


Connecting to and configuring your UltraLite database
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

 Connecting to and configuring your UltraLite database

This section describes how to connect to an UltraLite database. It describes the recommended UltraLite method for connecting to your database, and also how you can use the standard JDBC connection model to connect.

Connections to UltraLite databases have no user IDs or passwords. For more information, see User IDs in UltraLite databases.

UltraLite Java databases can be persistent (stored in a file when the application closes) or transient (the database vanishes when the application is closed). By default, they are transient.

You configure the persistence of your UltraLite database when connecting to it. This section describes how to configure your UltraLite database.

 Using the UltraLite JdbcDatabase.connect method

 Loading and registering the JDBC driver

 Connecting to the database using JDBC

 UltraLite JDBC URLs

 Using Properties to store connection information

 Connecting to multiple databases

 Configuring the UltraLite Java database


Using the UltraLite JdbcDatabase.connect method
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Connecting to and configuring your UltraLite database

 Using the UltraLite JdbcDatabase.connect method

The generated UltraLite database code is in the form of a class that extends JdbcDatabase, which has a connect method that establishes a connection.

The following example illustrates typical code, for a generated database class called SampleDB:

try {

SampleDB db = new SampleDB();

java.sql.Connection conn = db.connect();

} catch( SQLException e ){

// error processing here

}

If you wish to use a persistent database, the characteristics are specified on the connection as a Properties object. The following example illustrates typical code:

java.util.Properties p = new java.utils.Properties();

p.put( "persist", "file" );

p.put( "persistfile", "c:\\dbdir\\database.udb" );

SampleDB db = new SampleDB( p );

java.sql.Connection conn = db.connect( );

The Properties are used on the database constructor. You cannot change the persistence model of the database between connections.

The two properties specify that the database is persistent, and is stored in the file c:\dbdir\database.udb.

  For more information on database persistence, see Configuring the UltraLite Java database.


Loading and registering the JDBC driver
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Connecting to and configuring your UltraLite database

 Loading and registering the JDBC driver

The UltraLite JdbcDatabase.connect() method discussed in the previous section provides the simplest method of connecting to an UltraLite database. However, you can also establish a connection in the standard JDBC manner, and this section describes how to do so.

UltraLite applications connect to their database using a JDBC driver, which is included in the UltraLite runtime classes (ulrt.jar). You must load and register the JDBC driver in your application before connecting to the database. Use the Class.forName() method to load the driver. This method takes the driver package name as its argument:

Class.forName( "com.sybase.asa.ultralite.jdbc.JdbcDriver");

The JDBC driver automatically registers itself when it is loaded.

Loading multiple drivers

Although there is typically only one driver registered in each application, you can load multiple drivers in one application. Load each driver using the same methods as above. The DriverManager decides which driver to use when connecting to the database.

getDriver method

The DriverManager.getDriver(url) method returns the Driver for the specified URL.

Error handling

To handle the case where the driver cannot be found, catch ClassNotFoundException as follows:

try{

Class.forName(

"com.sybase.asa.ultralite.jdbc.JdbcDriver");

} catch(ClassNotFoundException e){

System.out.println( "Exception: " + e.getMessage() );

e.printStackTrace();

}


Connecting to the database using JDBC
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Connecting to and configuring your UltraLite database

 Connecting to the database using JDBC

Once the driver is declared, you can connect to the database using the standard JDBC DriverManager.getConnection method.

getConnection prototypes

The JDBC DriverManager.getConnection method has several prototypes. These take the following arguments:

DriverManager.getConnection( String url, Properties info )

DriverManager.getConnection( String url )

The UltraLite driver supports each of these prototypes. The arguments are discussed in the following sections.

Driver Manager

The DriverManager class maintains a list of the Driver classes that are currently loaded. It asks each driver in the list if it is capable of connecting to the URL. Once such a driver is found, the DriverManager attempts to use it to connect to the database.

Error handling

To handle the case where a connection cannot be made, catch the SQLException as follows:

try{

Class.forName(

"com.sybase.asa.ultralite.jdbc.JdbcDriver");

Connection conn = DriverManager.getConnection(

"jdbc:ultralite:asademo" );

} catch(SQLException e){

System.out.println( "Exception: " + e.getMessage() );

e.printStackTrace();

}


UltraLite JDBC URLs
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Connecting to and configuring your UltraLite database

 UltraLite JDBC URLs

The URL is a required argument to the DriverManager.getConnection method used to connect to UltraLite databases.

  For an overview of connection methods, see Connecting to the database using JDBC.

The syntax for UltraLite JDBC URLs is as follows:

jdbc:ultralite:[database:persist:persistfile]

The components are all case sensitive, and have the following meanings:

•	jdbc    Identifies the driver as a JDBC driver. This is mandatory.

•	ultralite    Identifies the driver as the UltraLite driver. This is mandatory.

•	database    The class name for the database. It is required and must be a fully-qualified name: if the database class is in a package, you must include the package name.

For example, the URL jdbc:ultralite:MyProject causes a class named MyProject to be loaded.

As Java classes share their name with the .java file in which they are defined, this component is the same as the output file parameter from the UltraLite generator.

  For more information, see The UltraLite generator.

•	persist    Specifies whether or not the database should be persistent. By default, it is transient.

  For more information, see Configuring the UltraLite Java database.

•	persistfile    For persistent databases, specifies the filename.

  For more information, see Configuring the UltraLite Java database.


Using Properties to store connection information
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Connecting to and configuring your UltraLite database

 Using Properties to store connection information

You can use a Properties object to store connection information, and supply this object as an argument to getConnection along with the URL.

  For an overview of connection methods, see Connecting to the database using JDBC.

The following components of the URL, described in UltraLite JDBC URLs, can be supplied either as part of the URL or as a member of a Properties object.

•	persist

•	persistfile

•	The jdbc:ultralite components must be supplied in the URL.


Connecting to multiple databases
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Connecting to and configuring your UltraLite database

 Connecting to multiple databases

UltraLite Java applications can connect to more than one database, unlike UltraLite C/C++ applications.

To connect to more than one database, simply create more than one connection object.


Configuring the UltraLite Java database
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Connecting to and configuring your UltraLite database

 Configuring the UltraLite Java database

You can configure the following aspects of the UltraLite Java database:

•	Whether the database is transient or persistent.

•	If the database is persistent, you can supply a filename.

•	If the database is transient, you can supply a URL for an initializing database.

Transient and persistent databases

By default, UltraLite Java databases are transient: they are initialized when the database object is instantiated, and vanish when the application closes down. The next time the application starts, it must reinitialize a database.

You can make UltraLite Java databases persistent by storing them in a file. You do this by specifying the persist and persistfile elements of the JDBC URL, or by supplying persist and persistfile Properties to the database connect method.

Initializing transient databases

The database for C/C++ UltraLite applications is initialized on the first synchronization call. For UltraLite Java applications that use a transient database, there is an alternative method of initializing the database. The URL for an UltraLite database that is used as the initial database is supplied in the  persistfile component to the URL.

Configuring the database

The database configuration components of the URL are therefore as follows:

•	persist    This can take one of the following values:

•	none    In this case, the database is transient. It is stored in memory while the application runs, but vanishes once the application terminates.

•	file    In this case, the database is stored as a file. The default filename is database.udb, where database is the database class name.

The default setting is none.

•	persistfile    The meaning of this component depends on the setting for persist.

•	If the persist component has a value of none, the persistfile component is a URL for an UltraLite database file that is used to initialize the database.

Both the schema and the data from the URL are used to initialize the application database, but there is no further connection between the two. Any changes made by your application apply only to the transient database, not to the initializing database.

The following JDBC URL is an example:

jdbc:ultralite:transient:none:http://www.address.com/transient.udb

You can prepare the initializing database with an application that uses the persistent form of the URL to create the database, synchronize, and exit.

•	If the persist component has a value of file, the persistfile component is a filename for the persistent UltraLite database. The filename should include any extension (such as .udb) that you wish to use.


Including SQL statements in UltraLite Java applications
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

 Including SQL statements in UltraLite Java applications

This section describes how to add SQL statements to your UltraLite application.

  For information on SQL features that can and cannot be used in UltraLite application, see SQL features and limitations of UltraLite applications.

The SQL statements to be used in your application must be added to the reference database. The UltraLite generator writes out an interface that defines these SQL statements as public static final strings. You invoke the statements in your application by implementing the interface and referencing the SQL statement by its identifier, or by referencing it directly from the interface.

Defining the SQL statements for your application

The SQL statements to be included in the UltraLite application, and the structure of the UltraLite database itself, are defined by adding the SQL statements to the reference database for your application.

  For information on reference databases, see Preparing a reference database.

Defining projects

Each SQL statement stored in the reference database is associated with a project. A project is a name, defined in the reference database, which groups the SQL statements for one application. You can store SQL statements for multiple applications in a single reference database by defining multiple projects.

  For information on creating projects, see Creating an UltraLite project.

Adding statements to your project

The data access statements you are going to use in your UltraLite application must be added to your project.

  For information on adding SQL statements to your database, see Adding SQL statements to an UltraLite project.


Adding synchronization to your application
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

 Adding synchronization to your application

This section describes how to initiate synchronization from an UltraLite Java application.

The synchronization logic that keeps UltraLite applications up to date with the consolidated database is not held in the application itself. Synchronization scripts stored in the consolidated database, together with the MobiLink synchronization server and the UltraLite runtime library, control how changes are processed when they are uploaded and determines which changes are to be downloaded.

Call the JdbcConnection.synchronize() method to initiate synchronization in an UltraLite application. The synchronization process can only work if the device running the UltraLite application is able to communicate with the synchronization server. For some platforms, this means that the device needs to be physically connected by placing it in its cradle or by attaching it to a server computer using a cable. You need to add error handling code to your application in case the synchronization cannot be carried out.

  UltraLite Java applications synchronize in a very similar fashion to other UltraLite applications. For general information about synchronization, see Adding synchronization to your application.

 Initializing the synchronization options

 Initiating synchronization

 Monitoring and canceling synchronization

 Implementing the UlSynchObserver interface

 Using the progress viewer


Initializing the synchronization options
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Adding synchronization to your application

 Initializing the synchronization options

The details of any synchronization, including the URL of the MobiLink synchronization server, the script version to use, the MobiLink user ID, and so on, are all held in a UlSynchOptions object.

Before synchronizing, initialize the synchronization parameters as follows:

UlSynchOptions synch_options = new UlSynchOptions();

The UlSynchOptions() object has the following methods to set and get its fields:

•	getUserName and setUserName

•	getScriptVersion and setScriptVersion

•	getStream and setStream

•	getStreamParms and setStreamParms.

Notes

The synchronization streams for UltraLite Java applications are objects, and are set by their constructors. The available streams are as follows:

•	UlSocketStream    TCP/IP synchronization

•	UlHTTPStream    HTTP synchronization

The following line sets the stream to TCP/IP:

synch_opts.setStream( new UlSocketStream() );

Transport-layer security, accessible from C/C++ UltraLite applications, is not yet available from UltraLite Java applications.

  For more information, see Setting synchronization parameters.


Initiating synchronization
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Adding synchronization to your application

 Initiating synchronization

Once you have initialized the synchronization parameters, and set them to the values needed for your application, you can initiate synchronization using the JdbcConnection.synchronize() method.

The method takes a UlSynchOptions object as argument. The set of calls needed to synchronize is as follows:

UlSynchOptions opts = new UlSynchOptions;

opts.setUserName( "50" );

opts.setScriptVersion( "default" );

opts.setStream( new UlSocketStream() );

opts.setStreamParms( "host=123.45.678.90" );

conn.synchronize( opts );


Monitoring and canceling synchronization
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Adding synchronization to your application

 Monitoring and canceling synchronization

UltraLite provides the following features for monitoring synchronization:

•	The UlSynchObserver interface for monitoring synchronization progress and for canceling synchronization.

•	A progress indicator component that implements the interface, which you can add to your application.

Monitoring synchronization

To monitor synchronization from an UltraLite Java application, you write a class that implements the UlSynchObserver interface. This interface contains a single method:

void updateSynchronizationStatus( UlSynchStatus status )

The overall process for monitoring synchronization is as follows:

•	Register your UlSynchObserver object using the UlSynchOptions class.

•	Call the synchronize() method to synchronize.

•	The updateSynchronizationStatus method of your observer class is called whenever the synchronization state changes. The following section describes the synchronization state.

Example

Here is a typical sequence of instructions for synchronization. In this example, the class MyObserver implements the UlSynchObserver interface:

UlSynchObserver observer = new MyObserver ();

UlSynchOptions opts = new UlSynchOptions();

// set options

opts.setUserName( "mluser" );

opts.setPassword( "mlpwd" );

opts.setStream( new UlSocketStream() );

opts.setStreamParms( "localhost" );

opts.setObserver( observer );

opts.setUserData( myDataObject );

// synchronize

conn.synchronize( opts );


Implementing the UlSynchObserver interface
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Adding synchronization to your application

 Implementing the UlSynchObserver interface

In the class that implements UlSynchObserver, the UlSynchStatus object holds synchronization information. This object is filled by UltraLite with synchronization status information each time your updateSynchronizationStatus method is called.

UlSynchStatus methods

The UlSynchStatus object has the following methods:

int getState()

int getTableCount()

int getTableIndex()

Object getUserData()

UlSynchOptions getSynchOptions()

UlSqlStmt getStatement()

int getErrorCode()

boolean isOKToContinue()

void cancelSynchronization()

These methods have the following meanings:

•	getState    Returns a constant indicating the state of the synchronization. The constant is one of the following values:

•	STARTING    No synchronization actions have yet been taken.

•	CONNECTING    The synchronization stream has been built, but not yet opened.

•	SENDING_HEADER    The synchronization stream has been opened, and the header is about to be sent.

•	SENDING_TABLE    A table is being sent.

•	RECEIVING_UPLOAD_ACK    An acknowledgement that the upload is complete is being received.

•	RECEIVING_TABLE    A table is being received.

•	SENDING_DOWNLOAD_ACK    An acknowledgement that download is complete is being sent.

•	DISCONNECTING    The synchronization stream is about to be closed.

•	DONE    Synchronization has completed successfully.

•	ERROR    Synchronization has completed, but with an error.

  For a description of the synchronization process, see The synchronization process.

•	getTableCount    Returns the number of tables being synchronized. For each table there is a sending and receiving phase.

•	getTableIndex    Returns the current table index for sending and receiving, starting at 0.

•	getUserData    Returns the user data object.

•	getSynchOptions    Returns the UlSynchOptions object.

•	getStatement    Returns the statement that called the synchronization. The statement is an internal UltraLite statement, and this method is unlikely to be of practical use, but is included for completion.

•	getErrorCode    When the synchronization state is set to ERROR, this method returns a diagnostic error code.

•	isOKToContinue    This is set to false when cancelSynchronization is called. Otherwise, it is true.

•	cancelSynchronization    The SQL exception SQLE_INTERRUPTED is set, and the synchronization stops as if a communications error had occurred. The observer is always called with either the DONE or ERROR state so that it can do proper cleanup.

Example

The following code snippet illustrates a very simple observer:

void updateSynchronizationStatus( UlSynchStatus status )

{

    int state = status.getState();

    System.out.println( "Sync status: " + state );

    if( state == UlSynchStatus.SENDING_TABLE ||

       state == UlSynchStatus.RECEIVING_TABLE ){

          System.out.println( "send/receive table " +

          ( status.getTableIndex() + 1 ) +

            " of " + status.getTableCount() );

    }

}


Using the progress viewer
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Adding synchronization to your application

 Using the progress viewer

The UltraLite runtime library includes two progress viewer classes, which provide an implementation of synchronization monitoring, together with the ability for end users to cancel synchronization. The progress viewer classes are as follows:

•	com.sybase.asa.ultralite.ui.SynchProgressViewer    A heavyweight AWT version.

•	com.sybase.asa.ultralite.ui.JSynchProgressViewer    A Swing version of the viewer that respects the Swing threading model.

The two classes are used identically. The viewer displays a modal or modeless dialog, which shows a series of messages and a progress bar. Both the messages and the bar are updated during synchronization. The viewer also provides a Cancel button. If the user clicks the Cancel button, synchronization stops and the SQL exception SQLE_INTERRUPTED is thrown.

Threading issues

In a Java application, all events occur on a single thread called the event thread. Also, all user interface objects are created on the event thread, even if the application is on a different thread at the time. There is only one event thread in an application.

The event thread must never block. Consequently, you should not perform long operations on the event thread, as this leads to painting aberrations. Even calling the show() method on a modal dialog suspends execution of the event thread. You must therefore avoid calling the synchronize() method on the event thread.

Displaying a modal viewer

The following code snippet illustrates how to invoke a modal instance of the viewer. The import statement uses the AWT version:

import com.sybase.asa.ultralite.ui.SynchProgressViewer;

// create a frame to display a dialog

java.awt.Frame frame = ...;

// get UltraLite connection

Connection conn = ...;

// set synchronization options

UlSynchOptions options = new UlSynchOptions();

options.setUserName( "my_user" );

...

// create the viewer

SynchProgressViewer viewer = new SynchProgressViewer( frame );

viewer.synchronize( frame, options );

// execution stops here until synchronization is complete

When invoked in this manner, the viewer carries out the following operations:

1	registers itself as a synchronization observer,

2	spawns a thread to do the synchronization,

3	displays itself, blocking the current thread.

4	When synchronization finishes, the observer callback disposes of the dialog, which lets the thread continue.

Displaying a modeless viewer

The following code snippet illustrates how to invoke a modeless instance of the viewer:

SynchProgressViewer viewer = new SynchProgressViewer( frame, false );

options.setObserver( viewer );

conn.synchronize( options );

In this case, you must ensure that the synchronization occurs on a thread other than the event thread, so that the viewer is not blocked.

Notes

•	All messages come from the SynchProgressViewerResources resource bundle.

•	The viewer implements the UlSynchObserver interface so it can hook into the synchronization process.

•	The CustDB sample application includes a progress viewer. The CustDB sample code is in the UltraLite\samples\CustDB\java subdirectory of your SQL Anywhere directory.


UltraLite Java development notes
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

 UltraLite Java development notes

This section provides notes for development of UltraLite Java applications.

 Using JDBC in UltraLite

 Creating UltraLite Java applets

 UltraLite and threads


Using JDBC in UltraLite
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        UltraLite Java development notes

 Using JDBC in UltraLite

The following are features and limitations specific to the development of JDBC UltraLite applications.

The UltraLite API is modeled on JDBC 1.2, with the addition of two ResultSet methods from JDBC 2.0:

•	absolute()

•	relative()

The following features are incompatible with the UltraLite development model and are not supported by UltraLite.

•	There is only limited support for metadata access (system table access). Therefore, you cannot use the DatabaseMetaData Interface. Metadata access is limited to the number and type of columns.

•	Java objects cannot be stored in the database

•	There is no support for stored procedures or stored functions.

•	Only static SQL statements are supported and they must be added to the database so that the UltraLite generator can generate them.

 Unsupported JDBC methods


Unsupported JDBC methods
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        UltraLite Java development notes

          Using JDBC in UltraLite

 Unsupported JDBC methods

UltraLite does not support the following JDBC methods. An attempt to use any of the following methods results in a SQLException with a vendor code indicating that the feature is not supported in UltraLite.

For the Connection interface

•	getCatalog

•	getMetaData

•	getTransactionIsolation

•	setCatalog

•	setTransactionIsolation

For the ResultSet interface

•	findColumn

•	getAsciiStream( String )

•	getBigDecimal( String, int )

•	getBinaryStream( String )

•	getBoolean( String )

•	getByte( String )

•	getDate( String )

•	getDouble( String )

•	getFloat( String )

•	getInt( String )

•	getLong( String )

•	getMetaData

•	getObject( String )

•	getShort( String )

•	getString( String )

•	getTime( String )

•	getTimestamp( String )

•	getUnicodeStream( String )

For the Statement interface

•	cancel

•	getMaxFieldSize

•	getMaxRows

•	setMaxFieldSize

•	setMaxRows


Creating UltraLite Java applets
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        UltraLite Java development notes

 Creating UltraLite Java applets

If you create your JDBC program as an applet, your application can only synchronize with the machine from which the applet is loaded, which is usually the same as the HTML.

Including an applet in an HTML page

The following is a sample HTML page used to create an UltraLite applet:

<html>

<head>

</head>

<body bgcolor="FFFF00">

<applet code="CustDbApplet.class" width=440 	height=188 archive="custdb.zip,ulrt.jar" >

</applet>

</body>

</html>

The applet tag specifies the following:

•	The class that the applet starts:

code="CustDbApplet.class"

•	The size of the window in the web browser to display the applet to.

width=440 height=188

•	The zip files that are necessary in order to run the applet.

archive="custdb.zip,ulrt.jar"

In this case, the custdb.zip file and the UltraLite runtime zip file are necessary in order to run the UltraLite CustDB sample application.


UltraLite and threads
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        UltraLite Java development notes

 UltraLite and threads

UltraLite is not thread-safe, and any multi-threaded Java application must ensure that the single-threaded nature of UltraLite is treated safely.


Building UltraLite Java applications
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

 Building UltraLite Java applications

This section covers the following subjects:

•	Generating UltraLite Java classes

•	Compiling UltraLite Java applications

 Generating UltraLite Java classes

 Compiling UltraLite Java applications

 Deploying Java applications


Generating UltraLite Java classes
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Building UltraLite Java applications

 Generating UltraLite Java classes

When you have prepared a reference database, defined an UltraLite project for your application, and added SQL statements to define your data access features, all the information the generator needs is inside your reference database.

  For general information on the UltraLite generator, see Generating the UltraLite data access code. For command-line options, see The UltraLite generator.

The generator output is a Java source file with a filename of your choice. Depending on the design of your database and the sophistication of the database functionality your application requires, this file can vary greatly in both size and content.

There are several ways to customize the UltraLite generator output, depending on the nature of your application.

Overview

You generate the classes by running the UltraLite generator against the reference database.

♦ To run the UltraLite generator:

•	Enter the following command at a command-prompt:

ulgen -c "connection-string" options

where options depend on the specifics of your project.

Common command-line combinations

When you are generating Java code, there are several options you may want to specify:

•	-t java    Generate Java code. The generator is the same tool used for C/C++ development, so this option is required for all Java use.

•	-i    Some Java compilers do not support inner classes correctly, and so the default behavior of the generator is not to generate Java code that includes inner classes. If you wish to take advantage of a compiler that does support inner classes, use this option.

•	-p    It is common to include your generated classes in a package, which may include other classes from your application. You can use this switch to instruct the generator to include a package name for the classes in the generated files

•	-s    In addition to the code for executing the SQL statements, generate the SQL statements themselves as an interface. Without this option, the strings are written out as members of the database class itself.

•	-a    Make SQL string names upper case. If you choose the -a option, the identifier used in the generated file to represent each SQL statement is derived from the name you gave the statement when you added it to the database. It is a common convention in Java to use upper case letters to represent constants. As the SQL string names are constants in your Java code, you should use this option to generate string identifiers that conform to the common convention.

Example

•	The following command (which should be all on one line) generates code that represents the SQL statements in the CustDemo project, and the required database schema, with output in the file uldemo.java.

ulgen -c "dsn=Ultralite 7.0 Sample;uid=dba;pwd=sql"

-a -t java -s IStatements CustDemo uldemo.java


Compiling UltraLite Java applications
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Building UltraLite Java applications

 Compiling UltraLite Java applications

♦ To compile the generated file:

1	Set your classpath

When you compile your UltraLite Java application, the Java compiler must have access to the following classes:

•	The Java runtime classes.

•	The UltraLite runtime classes

•	The target classes (usually in the current directory).

The following classpath gives access to these classes.

%JAVA_HOME%\jre\lib\rt.jar;%ASANY7%\ultralite\java\lib\ulrt.jar;.

where JAVA_HOME represents your Java installation directory, and ASANY7 represents your SQL Anywhere installation directory.

For JDK 1.1 development, ulrt.jar is in a jdk11\lib subdirectory of the UltraLite\java directory.

2	Compile the classes.

With the classpath set as in step one, use javac and enter the following command (on a single line):

javac file.java

The compiler creates the class files for file.java.

The compilation step produces a number of class files. You must include all the generated .class files in your deployment.


Deploying Java applications
  UltraLite  Developer's Guide

    PART 3. Developing UltraLite Applications in Java

      CHAPTER 13.  Developing UltraLite Java Applications

        Building UltraLite Java applications

 Deploying Java applications

Your UltraLite application consists of the following:

•	Class files you created to implement your application.

•	Generated class files.

•	The Java core classes (rt.jar).

•	UltraLite runtime JAR file (ulrt.jar).

Your UltraLite application can be deployed in whatever manner is appropriate. You may wish to package together these class files in a JAR file, for ease of deployment.

Your UltraLite application automatically initializes its own database the first time it is invoked. At first, your database will contain no data. You can add data explicitly using INSERT statements in your application, or you can import data from a consolidated database through synchronization. Explicit INSERT statements are especially useful when developing prototypes.

  For more information, see Adding synchronization to your application.


PART 4. Reference
  UltraLite  Developer's Guide

 PART 4. Reference

This part provides reference material that applies to more than one 	of the UltraLite development models.

 CHAPTER 14.  UltraLite Reference


CHAPTER 14.  UltraLite Reference
  UltraLite  Developer's Guide

    PART 4. Reference

 CHAPTER 14.  UltraLite Reference

About this chapter

This chapter provides reference information about the UltraLite utility programs, the Embedded SQL library functions, and the synchronization scripts.

 Stored procedures

 HotSync conduit installation utility

 The SQL preprocessor

 The UltraLite generator

 The UltraLite segment utility

 Ultralite utility


Stored procedures
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

 Stored procedures

This section describes system stored procedures in the Adaptive Server Anywhere reference database, which can be used to add SQL statements to a project.

For each SQL statement added in this way, the UltraLite generator defines a C++ or Java class.

These system procedures are owned by the built-in user ID dbo.

 ul_add_statement system procedure

 ul_add_project system procedure

 ul_delete_project system procedure

 ul_delete_statement system procedure


ul_add_statement system procedure
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

        Stored procedures

 ul_add_statement system procedure

Function

Adds a SQL statement to an UltraLite project.

Syntax

ul_add_statement (in @project char(128),
in @name char(128),
in @statement text  )

Permissions

DBA authority required

Side effects

None

See also

ul_add_project system procedure

ul_delete_statement system procedure

Description

Adds or modifies a statement to an UltraLite project.

project    The UltraLite project to which the statement should be added. The UltraLite generator defines classes for all statements in a project at one time.

name    The name of the statement. This name is used in the generated classes.

statement    A string containing the SQL statement.

If a statement of the same name in the same project exists, it is updated with the new syntax. If project does not exist, it is created.

Examples

The following call adds a statement to the TestSQL project:

call ul_add_statement(

'TestSQL', 'TestQuery',

'select prod_id, price, prod_name from ulproduct where price < ?' )


ul_add_project system procedure
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

        Stored procedures

 ul_add_project system procedure

Function

Creates an UltraLite project.

Syntax

ul_add_project (in @project char(128) )

Permissions

DBA authority required

Side effects

None

See also

ul_delete_statement system procedure

Description

Adds an UltraLite project to the database. The project acts as a container for the SQL statements in an application, and the project name is supplied on the UltraLite generator command line so that it can define classes for all statements in the project.

project    The UltraLite project name.

Examples

The following call adds a project named Product to the database:

call ul_add_project( 'Product' )


ul_delete_project system procedure
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

        Stored procedures

 ul_delete_project system procedure

Function

Removes an UltraLite project from a database.

Syntax

ul_delete_project (in @project char(128) )

Permissions

DBA authority required

Side effects

None

See also

ul_add_project system procedure

ul_delete_statement system procedure

Description

Removes an UltraLite project from the database.

project    The UltraLite project to be deleted from the database.

Examples

The following call deletes the Product project:

call ul_delete_project( 'Product' )


ul_delete_statement system procedure
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

        Stored procedures

 ul_delete_statement system procedure

Function

Removes a SQL statement from an UltraLite project.

Syntax

ul_delete_statement (in @project char(128),
in @name char(128) )

Permissions

DBA authority required

Side effects

None

See also

ul_add_project system procedure

ul_add_statement system procedure

Description

Removes a statement from an UltraLite project.

project    The UltraLite project from which the statement should be removed.

name    The name of the statement. This name is used in the generated classes.

Examples

The following call removes a statement from the Product project:

call ul_delete_statement( 'Product', 'AddProd' )


HotSync conduit installation utility
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

 HotSync conduit installation utility

The utility installs or removes a HotSync conduit onto the current machine.

Syntax

dbcond7 [ switches ] id

Switch	Description
id	The creator ID of the application to use the conduit
-n name	The name displayed by the HotSync manager.
-x	Remove the conduit for the specified creator ID
Description

Install a HotSync conduit onto the current machine. The HotSync manager must be installed in order for this to be run.

Switches

id    The application user ID who is to use the conduit. If a conduit already exists for the specified creatorID, it is replaced by the new conduit. This is a required option.

-n name    The name displayed by the HotSync manager. This is also the name of the subdirectory where the conduit stores data. Do not use this option together with -x. The default value is MobiLink conduit.

-x    Remove the conduit for the named creatorID.  If -x is not specified, a conduit is installed.


The SQL preprocessor
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

 The SQL preprocessor

The SQL preprocessor processes a C or C++ program containing embedded SQL, before the compiler is run.

Syntax

sqlpp [ switches ] sql-filename [ output-filename ]

Switch	Description
-c "keyword=value;...."	Supply database connection parameters for your reference database
-e level	Flag non-conforming SQL syntax as an error
-h line-width	Limit the maximum line length of output
-n	Line numbers
-o operating-sys	Target operating system: WIN32, WINNT, NETWARE, or UNIX
-p project-name	UltraLite project name
-q	Quiet mode—do not print banner
-s string-len	Maximum string length for the compiler
-w level	Flag non-conforming SQL syntax as a warning
-x	Change multi-byte SQL strings to escape sequences.
-z sequence	Specify collation sequence
See also

Application development using Embedded SQL

Description

The SQL preprocessor processes a C or C++ source file that contains embedded SQL, before the compiler is run. This preprocessor translates the SQL statements in the input-file into C/C++. It writes the result to the output-file. The normal extension for source files containing embedded SQL is sqc. The default output filename is the sql-filename base name with an extension of c. However, if the sql-filename already has the .c extension, the default output extension is .cc.

When preprocessing files that are part of an UltraLite application, the SQL preprocessor requires access to an Adaptive Server Anywhere reference database. You must supply the connection parameters for the reference database using the -c option.

If you specify no project name, the SQL preprocessor also runs the UltraLite generator and appends additional code to the generated C/C++ source file. This code contains a C/C++ language description of your database schema as well as the implementation of the SQL statements in the application.

Switches

-c    Required when preprocessing files that are part of an UltraLite application. The connection string must give the SQL preprocessor access to read and modify your reference database.

-e level    This option flags any Embedded SQL that is not part of a specified set of SQL/92 as an error.

The allowed values of level and their meanings are as follows:

•	e    flag syntax that is not entry-level SQL/92 syntax

•	i    flag syntax that is not intermediate-level SQL/92 syntax

•	f    flag syntax that is not full-SQL/92 syntax

•	t    flag non-standard host variable types

•	u    flag features not supported by UltraLite

•	w    allow all supported syntax

-h num    Limits the maximum length of lines output by sqlpp to NUM characters. The continuation character is a backslash (\), and the minimum value of NUM is ten.

-n    Generate line number information in the C file. This consists of #line directives in the appropriate places in the generated C code. If your compiler supports the #line directive, this switch will make the compiler report errors on line numbers in the sql-filename, as opposed to reporting errors on line numbers in the C/C++ output file. Also, the #line directives will indirectly be used by the source-level debugger so that you can debug while viewing the sql-filename.

Target operating system (-o)    Specify the target operating system. Note that this option must match the operating system where you will run the program. A reference to a special symbol will be generated in your program. This symbol is defined in the interface library. If you use the wrong operating system specification or the wrong library, an error will be detected by the linker. The supported operating systems are:

•	WIN32    32-bit Microsoft Windows (Windows 95/98, Windows CE)

•	WINNT    Microsoft Windows NT

•	NETWARE    Novell NetWare

•	UNIX    UNIX

-p project-name    Identifies the UltraLite project to which the embedded SQL files belong. Applies only when processing files that are part of an UltraLite application.

-q    Operate quietly. Do not print the banner.

-s string-len    Set the maximum size string that the preprocessor will put into the C file. Strings longer than this value will be initialized using a list of characters ('a','b','c', etc). Most C compilers have a limit on the size of string literal they can handle. This option is used to set that upper limit. The default value is 500.

-w level    This option flags any Embedded SQL that is not part of a specified set of SQL/92 as a warning.

The allowed values of level and their meanings are as follows:

•	e    flag syntax that is not entry-level SQL/92 syntax

•	i    flag syntax that is not intermediate-level SQL/92 syntax

•	f    flag syntax that is not full-SQL/92 syntax

•	t    flag non-standard host variable types

•	u    flag features not supported by UltraLite

•	w    allow all supported syntax

-x    Change multi-byte strings to escape sequences so that they can pass through compilers.

-z sequence    This option specifies the collation sequence or filename. For a listing of the available collation sequences, type dbinit -l at the command prompt.


The UltraLite generator
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

 The UltraLite generator

The UltraLite generator, using the Analyzer classes, implements your application database and generates additional C/C++ or Java source files, which must be compiled and linked into your application.

Syntax

ulgen [ switches ] [ project [ output-filename ] ]

Switch	Description
-a	Uppercase SQL string names [ Java ]
-c "keyword=value;..."	Supply database connection parameters for your reference database
-e	Replace SQL strings with generated constants [ Java ]
-f filename	Output file name
-g	Do not display warnings
-i	Generate inner classes [ Java ]
-j project-name	Project name
-p package-name	Package name for generated classes [ Java ]
-q	Do not print the banner
-r filename	The file containing the trusted root certificates
-s filename	Generate a list of SQL strings in an interface definition [ Java ]
-t target	Target language. Must be one of the following: • c • c++ • java
-u pub-name	The publication to use (C++ API only)
Description

The UltraLite generator creates code that you compile and make part of an UltraLite application. Its output is based on the schema of the Adaptive Server Anywhere reference database and the specific SQL statements or tables that you use in your embedded SQL source files.

You must ensure that all your statements and tables are defined in the dbo.ul_statement table before running the generator. You do this as follows:

•	In embedded SQL, run the SQL preprocessor on each file.

•	In the C/C++ API and Java, add statements to the database using ul_add_statement, and/or define SQL Remote publications in the database.

In this table, statements are associated with projects. By specifying a project name on the generator command line, you determine which statements are included in your generated database.

You can include multiple projects, and also mix projects with a publication, on the generator command line. You must run the generator only once for each generated database.

If you do not specify an output file name, the generated code is written to a file with a name of project. It is recommended that you specify an output file name using the -f command-line switch.

Switches

project    The project name determines the set of statements that are to be included in the generated database. For a more precise specification of the filename, use the -j option.

output-filename    The name for the generated file, without extension. For a more precise specification of the filename, use the -f option.

In Java, this name is also the database name, which you must supply on connection.

-a    If you are developing a Java application, the names of the SQL statements in the project are used as constants in your application. By convention, constants are upper case, with underscore characters between words. The -a option makes the names of SQL statements fit this convention by uppercasing the characters and inserting an underscore whenever an uppercase character in the original name is found if not already preceded by an underscore or an uppercase character. For example, a statement named MyStatement becomes MY_STATEMENT, and a statement named AStatement becomes ASTATEMENT.

The generated names have spaces and non-alphanumeric characters replaced with an underscore, regardless of whether -a is used.

-c connection-string    The connection string must give the generator permission to read and modify your reference database. This parameter is required.

-e    The SQL strings in the generated database are replaced by smaller, generated strings. This option is useful when you are trying to reduce the footprint of a database with a lot of statements.

-f filename    This is the recommended way to specify the output file. Do not specify an extension.

-g    Suppress the display of warning messages. Error messages are still displayed.

The UltraLite generator provides warnings to indicate that some generated code may, under some circumstances, cause problems.

-i    By default, generated classes are written as top-level non-public classes except for the main database class. If you use -i, the generated classes are written as inner classes. If you use this option, you must use a Java compiler that can correctly compile inner classes.

-j project-name    This is the recommended way to specify the project. You can specify multiple projects using this switch.

-p package-name    A package name for generated files when generating Java output.

-q     Do not display output messages.

-r filename    The file containing the trusted root certificates used for secure synchronization using Certicom security software.

The generator embeds these trusted roots into the UltraLite application. When the application receives a certificate chain from a MobiLink synchronization server, it checks if its root is among the trusted roots, and only accepts a connection if it is.

The generator checks the expiry dates of all the certificates in the trusted root certificate file and issues the following warning for any certificate that expires in less than 6 months (180 days):

Warning: Certificate will expire in %1 days"

The generator issues a Certificate has expired error for any certificate that has already expired.

  For more information, see Setting synchronization parameters, and Transport-layer security.

-s filename    Generate an interface that contains the SQL statements as constants. This option is for use with Java only. The interface file has a format similar to the following example:

package com.sybase.test;

public interface EmpTestSQL {

    String EMPLOYEE = "select emp_fname, emp_lname

from employee where emp_id = ?";

    String UPDATE_EMPLOYEE = "update employee

set emp_fname = ?, emp_lname = ?

where emp_id = ?";

}

Do not supply the .java extension in filename. The -a option controls the case of the statement names.

-t target    Specifies the kind and extension of the generated file.

•	If you are using Java, you must use a target of java. If you are using embedded SQL or the C++ API, you can use a target of either c or c++. Which one you choose decides the extension of the file name, and has nothing to do with whether you are using the C++ API or embedded SQL.

•	If you specify c++, the following files are generated:

•	filename.cpp    The code for the generated API.

•	filename.h    A header file. You do not need to look at this file.

•	filename.hpp    The C++ API definition for your application.

•	If you specify a target of c, filename.c is generated.

-u pub-name    If you are generating a C++ API for a publication, specify the publication name with the -u switch.


The UltraLite segment utility
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

 The UltraLite segment utility

The UltraLite segment utility is for use when building applications for the Palm Computing Platform using the GCC PRC-Tools tool chain.

Syntax

dbulseg generated-source-file definition-file AppName CreatorID

Switch	Description
generated-source-file	The name of the source code file written by the UltraLite generator.
definition-file	The name of the definition file to be written out. It should end in the extension .def.
AppName	The name of the application.
CreatorID	The application creator ID
Description

The GCC PRC-Tools suite requires a set of segment identifiers in a definition file. The dbulseg utility reads the UltraLite generated code (in file generated-source-file) and writes out the definition file definition-file.

The segment definition file also includes the Palm application name and application creator ID. These Palm-specific identifiers must be supplied in the command line.

Example

The command line included in the build.bat file that compiles the UltraLite CustDB sample application is as follows:

dbulseg custdb.c custdb.def CustDB Syb2

The resulting output file is as follows:

application { "CustDB" Syb2 }

multiple code { ULRT1 ULRT2 ULRT3 ULRT4 ULRT5 ULRT6

ULRT7 ULRT8 ULRT9 ULRT10 ULRT11 ULRT12 ULRT13 ULRT14

ULRT15 ULRT16 ULRT17 ULG512 ULG513 ULG514 ULG515 ULG516

ULG517 ULG518 ULG519 ULG520 ULG521 ULG522 ULG523 ULG524

ULG525 ULG526 ULG527 ULG528 ULG529 ULG530 ULG531 ULG532

ULG131 }

The file contents are on two lines: the second line is wrapped for display purposes.

See also

Working with segments in PRC Tools


Ultralite utility
  UltraLite  Developer's Guide

    PART 4. Reference

      CHAPTER 14.  UltraLite Reference

 Ultralite utility

The UltraLite Utility deletes all of the data stored in an UltraLite application's remote database.

Description

A separate version of ULUtil is provided for each target platform. Versions for each processor are installed into the following directory:

%ASANY%\ultralite\platform\processor

where platform is Palm, and the processor refers to the processor on which the machine is running.

ULUtil is useful in deployments where devices are shared between different users. When a different user gets a device, they may want to clear out the previous user's data, to save storage space. Also, the previous user might want to clear out their data because it is confidential. Without ULUtil, the only way to clear out an application's data would be to delete and re-install the application.

Once ULUtil is installed on the device, you can delete an UltraLite application's data as follows:

1	Switch to ULUtil.

2	Select an application from the list of UltraLite Applications.

3	Tap the Delete button.