264
Cloudscape Developer’s Guide Cloudscape Version 3.0 December 15, 1999

Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Developer’s Guide

Cloudscape Version 3.0December 15, 1999

Page 2: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

d,

. All s.

Copyright © 1997-1999 Cloudscape, Inc., 180 Grand Ave., Suite 300, OaklanCA 94612. www.cloudscape.com.

All rights reserved. Java™ is a registered trademark of Sun Microsystems, Incother brand and product names are trademarks of their respective companie

Page 3: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Table of Contents

About This Document xv

Purpose of This Document xv

Audience xvi

How This Document Is Organized xvi

1 After Installing 1-1

The Installation Directory 1-1

Batch Files and Shell Scripts 1-3

Cloudscape and JVMs 1-4

Incompatibility Between Pre-1.1.6 and 1.2 Databases 1-4

Setting the Class Path for Developing Applications 1-5

Upgrades 1-5

Recommended Steps Before Upgrading 1-6

Upgrading a Database 1-7

Synchronization Databases and Upgrades 1-7

UNIX-Specific Issues 1-7

Configuring File Descriptors 1-7

Scripts 1-8

2 JDBC Applications and the Cloudscape Technology 2-1

Application Development Overview 2-1

Cloudscape Basics 2-3

Cloudscape JDBC Driver 2-3

Cloudscape JDBC Database Connection URL 2-4

iii

Page 4: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Clouds

iv

Cloudscape System 2-5

One Cloudscape per System 2-6

Booting 2-7

Shutting Down the System 2-8

Defining the System Directory 2-9

The Information (Error) Log 2-9

cloudscape.properties 2-9

Double-Booting System Behavior 2-9

Recommended Practice 2-11

A Cloudscape Database 2-12

The Database Directory 2-12

Single Database Shutdown 2-14

Storage and Recovery 2-14

Log on Separate Device 2-15

Database Pages 2-15

Database-Wide Properties 2-15

Version 3.0 Database Limitations 2-15

Connecting to Databases 2-16

Standard Connections—Connecting to Databases in the File System 2-17

Within the System 2-17

Outside the System Directory 2-17

Conventions for Specifying the Database Path 2-18

Special Database Access 2-18

From the Class Path 2-18

From a Jar or Zip File 2-19

Examples 2-20

Working with the Database Connection URL Attributes 2-21

Shutting Down Cloudscape or an Individual Database 2-22

Creating and Accessing a Database 2-23

Accessing an Existing Database 2-23

As the Subprotocol 2-23

Using the databaseName Attribute 2-23

Turning Off Auto-Commit 2-24

cape Developer’s Guide

Page 5: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

v

Getting a Nested Connection 2-24

Providing a User Name and Password 2-24

Encrypting a Database When You Create It 2-24

Booting an Encrypted Database 2-25

Upgrading a Database 2-25

Specifying Attributes in a Properties Object 2-25

Cloudscape Embedded Basics 2-26

Embedded Cloudscape JDBC Driver 2-26

Standard Cloudscape JDBC Database Connection URL 2-26

Starting Cloudscape as an Embedded Database 2-28

Working with Database Threads in an Embedded Environment 2-29

3 Deploying Cloudscape Applications 3-1

Deployment Issues 3-1

Deployment Options 3-1

Embedded Deployment Application Overview 3-2

Client/Server Deployment Application Overview 3-3

Synchronization Application Overview 3-4

Choosing a Deployment Option 3-5

Deploying Java Classes for Use as Java Data Types 3-6

Java Data Type Deployment, Embedded Environment 3-7

Java Data Type Deployment, Client/Server Environment 3-7

Deployment Cheat Sheets 3-8

Deploying Cloudscape in an Embedded Environment 3-8

Embedded Systems and Properties 3-9

Deploying Client/Server Applications 3-10

Deploying Cloudsync Systems 3-10

Creating Cloudscape Databases for Read-Only Use 3-12

Creating and Preparing the Database for Read-Only Use 3-12

Deploying the Database on the Read-Only Media 3-13

Transferring Read-Only Databases to Archive (Jar or Zip) Files 3-13

Accessing a Read-Only Database in a Zip/Jar 3-14

Accessing Databases-in-a-Jar in the Class Path 3-15

When Path Is Ambiguous with Databases in File System 3-16

Cloudscape Version 3.0

Page 6: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Clouds

vi

When Path Is Ambiguous Because of Databases in Class Path 3-16

Read-Only Databases and Upgrading 3-16

Databases on Read-Only Media and DatabaseMetaData 3-17

Loading Classes from a Database 3-17

Class Loading Overview 3-17

Create Jar Files for Your Application 3-18

Choose Between Database-Level and System-Level Class Loading 3-18

Add the Jar File or Files to the Database 3-19

Examples 3-19

Adding Jar Files 3-20

Removing Jar Files 3-20

Replacing Jar Files 3-20

Enable Database Class Loading with a Property 3-20

Force Cloudscape Class Loading for the Application 3-21

Class Loading: Database-Side Only vs. Database- and Application-Side 3-22

Enabling Cloudscape Class Loading for Database-Side Logic Execution 3-22

Class Path Class Loading for Application-Side Logic Execution 3-22

Cloudscape Class Loading for Client-Side Logic Execution 3-24

Code Your Applications the Way You Normally Would 3-25

Dynamic Changes to Jar Files or Database Jar Class Path 3-26

Requirements 3-26

Notes 3-26

4 Using Cloudscape’s Java Extensions 4-1

Java and SQL-J Integration 4-1

Referring to Classes Within SQL-J 4-2

Storing Java Objects in Cloudscape Tables 4-3

Defining a Column to Store a Java Data Type 4-3

Storing Objects in the Column 4-4

cape Developer’s Guide

Page 7: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

vii

Cloudscape Database Design Considerations 4-4

Retrieving and Updating Objects 4-5

Retrieving Objects 4-6

Updating Objects 4-6

Orderable Java Data Types 4-7

Invoking Methods and Accessing Fields 4-8

Executing Methods 4-8

Refining Search Conditions 4-9

Accessing Methods When Storing Subclasses 4-9

Invoking Methods on Classes Not Serialized in the Database 4-10

Creating an Instance of a Class on the Fly Using Built-in Types 4-11

Class Method Invocation and Class Field Access (Static Methods and Fields) 4-12

Method Invocation and Dynamic Parameters 4-12

Invoking Database-Side JDBC Methods 4-13

Other Java-Smart Syntax in SQL-J 4-14

Using Methods to Emulate SQL-92 Functions 4-15

SQL-J and Java Type Correspondence 4-15

Using the Cloudscape Types to Query the System Tables 4-17

Getting External Data: Using the Cloudscape Virtual Table Interface 4-19

5 Special Cloudscape Programming 5-1

Programming Database-Side JDBC Methods 5-1

Overview 5-2

Database-Side JDBC Methods and Nested Connections 5-2

GETCURRENTCONNECTION Built-In Method 5-3

current=true attribute 5-3

Requirements for Database-Side JDBC Methods Using Nested Connections 5-3

Nested Connections and Work Units 5-4

Example Method 5-4

Invoking the Example Method 5-5

Database-Side JDBC Methods Using Non-Nested Connections 5-6

Example Method Using New (not Nested) Connection 5-6

Cloudscape Version 3.0

Page 8: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Clouds

viii

Invoking the Example Method Using the CALL Command 5-6

Database-Side JDBC Methods and SQLExceptions 5-6

User-Defined SQLExceptions 5-8

Programming Serializable Classes 5-8

Requirements for Serialization 5-9

Serializable vs. Externalizable 5-9

Marking Fields as Transient 5-10

Modifying Classes (Java Versioning) 5-11

Compatible and Incompatible Changes 5-11

Using the serialVersionUID to Indicate Serializable Compatibility 5-12

Versioning Mini Tutorial 5-12

Other Kinds of Versioning 5-14

Serializable Objects and Input/Output Streams 5-16

Programming VTIs 5-16

Requirements and Options for VTI Classes 5-17

Implementing ResultSet 5-17

ResultSet and ResultSetMetaData Methods Used by Cloudscape 5-17

Providing the ResultSetMetaData at Compile Time 5-20

Compile Time vs. Execution Time 5-21

Rules for Parameters 5-21

Constant Parameters 5-21

Non-Constant Parameters 5-21

Providing Costing Information 5-22

Estimating the Cost 5-24

Templates for Creating VTIs 5-25

Built-In VTIs and Example VTIs 5-26

Programming User-Defined Aggregates 5-27

Developing the Java Classes that Perform the Aggregation 5-27

Programming Trigger Actions 5-30

Trigger Action Overview 5-31

Performing Referential Actions 5-31

Accessing Before and After Rows 5-32

cape Developer’s Guide

Page 9: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

ix

Examples 5-33

Triggers and Exceptions 5-38

Example of User-Defined SQLException 5-38

Exceptions in Triggers Actions 5-39

Aborting Statements and Transactions 5-40

Transactionally Independent Trigger Actions 5-40

Long-Running Trigger Actions 5-41

Programming Orderable Classes 5-41

Requirements for Orderable Java Data Types 5-42

Notes on compareTo Implementation 5-42

Notes on Implementing the equals and hashCode Methods 5-43

Comparison Operators and Objects of Different Types 5-44

One of the Java Data Types is Orderable 5-44

Neither Java Data Type Is Orderable 5-45

6 Controlling Cloudscape Application Behavior 6-1

The JDBC Connection and Transaction Model 6-1

Connections 6-2

Statements 6-2

ResultSets and Cursors 6-3

Nested Connections 6-3

Transactions 6-3

Transactions When Auto-Commit Is Disabled 6-4

Using Auto-Commit 6-4

Turning Off Auto-Commit 6-6

Explicitly Closing Statements, ResultSets, and Connections 6-6

Statement vs. Transaction Runtime Rollback 6-6

SQL-J and JDBC ResultSet/Cursor Mechanisms 6-7

Simple Non-Updatable ResultSets 6-7

Updatable Cursors 6-8

Requirements for Updatable Cursors 6-9

Naming or Accessing the Name of a Cursor 6-9

Updatable Cursors and Cloudconnector 6-9

Extended Updatable Cursor Example 6-10

Cloudscape Version 3.0

Page 10: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Clouds

x

ResultSets and Auto-Commit 6-11

Scrolling Insensitive ResultSets 6-12

Locking, Concurrency, and Isolation 6-13

Isolation Levels and Concurrency 6-13

Configuring Isolation Levels 6-16

Lock Granularity 6-17

Types and Scope of Locks in Cloudscape Systems 6-18

Types of Locks 6-18

Scope of Locks 6-18

Notes on Locking 6-20

Bulk Fetch and Row Locks 6-20

Locking Examples 6-21

Row-Level Locking, TRANSACTION_READ_COMMITTED 6-21

Row-Level Locking, TRANSACTION_SERIALIZABLE 6-22

Deadlocks 6-22

Avoiding Deadlocks 6-23

Deadlock Detection 6-24

Lock Wait Timeouts 6-25

Configuring Deadlock Detection and Lock Wait Timeouts 6-25

Debugging Deadlocks 6-27

Working with Multiple Connections to a Single Database 6-27

Deployment Options and Threading and Connection Modes 6-28

Multi-User Database Access 6-29

Multiple Connections from a Single Application 6-30

Working with Multiple Threads Sharing a Single Connection 6-30

Pitfalls of Sharing a Connection Among Threads 6-30

Reasons for Trying to Share a Connection or Statement Across Threads 6-32

Recommended Practices 6-32

Threads Sharing a Statement: A Case Study 6-33

Working with Cloudscape SQLExceptions in an Application 6-34

Information Provided in SQLExceptions 6-34

cape Developer’s Guide

Page 11: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

xi

7 Using Cloudscape as a J2EE Resource Manager 7-1

The Classes 7-2

How to Use Them 7-2

Getting a DataSource 7-3

Shutting Down or Creating a Database 7-3

Remote DataSources 7-5

8 Cloudscape and Security 8-1

Security Overview 8-1

Features 8-1

Configuring Security for Your Environment 8-3

Configuring Security in a Client/Server Environment 8-3

Configuring Security in an Embedded Environment 8-4

Configuring Security in a Synchronization System 8-4

Working with User Authentication 8-5

Overview 8-5

Caveat for Configuring Security 8-5

Enabling User Authentication 8-7

Defining Users 8-8

External Directory Service 8-8

LDAP Directory Service 8-9

Libraries 8-9

Setting Up Cloudscape to Use Your LDAP Directory Service 8-10

Guest Access to Search for DNs 8-10

Performance Issues 8-12

Windows NT Users 8-12

Restrictions 8-12

NIS Directory Service Plus (NIS+) 8-12

Libraries 8-12

Configuring Cloudscape for NIS+ User Authentication 8-13

JNDI-Specific Properties for External Directory Services 8-13

User-Defined Class 8-13

Built-in Cloudscape Users 8-17

Cloudscape Version 3.0

Page 12: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Clouds

xii

Database-Level Properties 8-18

System-Level Properties 8-18

Properties Summary 8-19

Programming Applications for Cloudscape User Authentication 8-19

Programming the Application to Provide the User and Password 8-20

Login Failure Exceptions 8-20

Users and Authorization Identifiers 8-21

Authorization Identifiers, User Authentication, and User Authorization 8-21

User Names and Schemas 8-22

Exceptions 8-22

User Authorization 8-23

Setting User Authorization 8-23

Database or System Access 8-23

Setting the Default Access Mode 8-23

Setting the Access Mode for Particular Users 8-24

Notes on User Authorization 8-24

Exceptions 8-25

About Read-Only and Full Access 8-25

Examples 8-26

Encrypting Databases on Disk 8-27

Overview 8-27

Libraries and JVM 8-28

Working with Encryption 8-28

Encrypting Databases on Creation 8-28

Booting an Encrypted Database 8-29

Changing the Boot Password 8-29

SSL 8-30

Notes on the Cloudscape Security Features 8-31

User Authentication and Authorization Examples 8-32

Client/Server Environment 8-32

Single-User, Embedded Environment 8-33

Extended Example 8-34

cape Developer’s Guide

Page 13: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

xiii

Synchronization Environment 8-37

9 Information for Tool Developers 9-1

Working with Metadata for Java Data Types 9-1

Offering Connection Choices to the User 9-2

The DriverPropertyInfo Array 9-3

databaseName 9-3

Example 9-4

Storing DatabaseMetaData Queries 9-5

10 SQL-J Tips 10-1

Performing Case-Insensitive Sorts 10-2

Retrieving the Database Connection URL 10-2

Using java.lang Methods as Functions 10-2

Getting Methods to Look and Work More Like Stored Procedures 10-3

Use the Cloudscape-Supplied Methods to Work with Bits 10-5

Working with Arrays 10-6

Managing External Resources 10-6

Access Data from Another DBMS with Cloudscape’s VTI 10-7

Working with Date/Time Formats 10-8

Supplying a Parameter Only Once 10-8

Defining a Sequence-Number Column 10-9

Generating Unique Keys 10-10

Using Literals to Save Keystrokes 10-11

Integrating External Libraries 10-11

Using Third-Party Tools 10-12

Accessing and Modifying System Properties 10-12

Tricks of the VALUES Clause 10-13

Multiple Rows 10-13

Mapping Column Values to Return Values 10-13

Creating Empty Queries 10-14

Inserting a Row of Nulls 10-14

Forcing Garbage Collection and Finalization 10-14

Using a Derived Table to Avoid Redundant Method Calls 10-14

Cloudscape Version 3.0

Page 14: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Clouds

xiv

Use RunTimeStatistics to Get an Approximate Row Count for a Table 10-15

Appendix AMapping of Functions to java.lang Methods A-1

Index IN-1

cape Developer’s Guide

Page 15: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

plete

About This Document

• “Purpose of This Document” on page xv

• “Audience” on page xvi

• “How This Document Is Organized” on page xvi

For general information about the Cloudscape documentation, such as a comlist of books, conventions, and further reading, see “Using the Cloudscape Documentation”.

Purpose of This DocumentThis book explains how to use the core Cloudscape technology and is for developers building Cloudscape applications. It describes basic Cloudscape concepts, such as how you create and access Cloudscape databases through JDBC methods, how you work with the Java extensions to SQL, and how you deploy Cloudscape applications.

Users working with Cloudscape synchronization will need additional information, which they will find in the Cloudscape Synchronization Guide. When using Cloudscape with a server framework, you will find that some minor instructions are different from those found in this book. Those details are in the Cloudscape Server and Administration Guide.

xv

Page 16: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

About This Document

Clouds

xvi

va™ See

AudienceThis book is intended for software developers who already know some SQL and Java. Cloudscape users who are not familiar with the SQL standard or the Japrogramming language will benefit from consulting books on those subjects. “Further Reading” on page -6 in Using the Cloudscape Documentation for suggestions.

How This Document Is OrganizedThis document includes the following chapters:

• Chapter 1, “After Installing”Explains the installation layout and upgrade issues.

• Chapter 2, “JDBC Applications and the Cloudscape Technology”Basic details for using Cloudscape, including loading the JDBC driver, specifying a database URL, and starting Cloudscape.

• Chapter 3, “Deploying Cloudscape Applications”An overview of different deployment scenarios, and tips for getting the details right when deploying applications.

• Chapter 4, “Using Cloudscape’s Java Extensions”Information about the Java extensions to SQL-J.

• Chapter 5, “Special Cloudscape Programming”Information about developing special Java methods and classes such as database-side JDBC methods, VTI classes, aggregates, and the like.

• Chapter 6, “Controlling Cloudscape Application Behavior”JDBC, cursors, locking and isolation levels, and multiple connections.

• Chapter 7, “Using Cloudscape as a J2EE Resource Manager”Information for programmers developing back-end components in a J2EE system.

• Chapter 8, “Cloudscape and Security”Security issues in embedded and client/server environments, including users, SSL, disk encryption, and read-only connections.

• Chapter 9, “Information for Tool Developers”Tips for tool designers.

• Chapter 10, “SQL-J Tips”Insiders’ tricks of the trade for using SQL-J.

cape Developer’s Guide

Page 17: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

How This Document Is Organized xvii

• Appendix A, “Mapping of Functions to java.lang Methods”Information on using static java.lang methods in Cloudscape.

• “Index”

Cloudscape Version 3.0

Page 18: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

About This Document

Clouds

xviii

cape Developer’s Guide

Page 19: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

ur

y

alled e

1 After Installing

This chapter provides reference information about the installation directory, JVMs, class path, upgrades, and platform-specific issues. It includes:

• “The Installation Directory” on page 1-1

• “Cloudscape and JVMs” on page 1-4

• “Setting the Class Path for Developing Applications” on page 1-5

• “Upgrades” on page 1-5

• “UNIX-Specific Issues” on page 1-7

See Getting Started with Cloudscape for basic product descriptions, information on getting started, directions for setting the path and the class path, and a description of the example applications and databases.

The Installation DirectoryThe installation program installs the Cloudscape software in a directory of yochoice, called in this document the cloudscape base directory.

NOTE: We recommend that you install the Cloudscape software in a directorcalled cloudscape.

Some versions of the installer automatically create an environment variable cCLOUDSCAPE_INSTALL and set its value to the path to the cloudscape basdirectory.

C:>echo %CLOUDSCAPE_INSTALL%

C:\cloudscape

1-1

Page 20: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

After Installing

Clouds

1-2

-

If your installer did not create and set the value of this variable, Getting Started with Cloudscape instructed you to create it and to set its value to the path to the directory in which you installed the Cloudscape software.

The installer for Cloudscape, the main component, installs all the files you need, including most of the documentation set and some example applications and a sample database. The installer for Cloudconnector installs additional libraries, batch files, and documentation for working with Cloudconnector. The installer for Cloudsync installs an additional Cloudscape library, an additional example program, and an additional book.

Figure 1-1 shows the layout of the cloudscape base directory.

Figure 1-1 The product installation. You specify the cloudscape base directory during the installation process—for example, C:\cloudscape.

Here are some details about the installation:

• index.html in the top-level directory is the top page for the on-line documentation.

base directory

index.html

release_notes.html

demo

doc

javadoc

lib

html

programs

databases

tree.html

frameworks

base installation

Cloudconnector installation

Cloudsync installation����yyyy

synchronization

methodalias

simple

tourstoursDB

embedded��yyRmiJdbc

cloudconnect

cloudscape.jar

tools.jar

client.jar

cloudsync.jar

readme.html

readme.html

gs.htm (Getting Started)

util

Core Booksand Cloudscape

Server Guide

Synchronization Guide

cape Developer’s Guide

Page 21: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

The Installation Directory 1-3

ilt

r

-e.

t

i-

r-pe; a-

s.

arted in

• release_notes.html, in the top-level cloudscape base directory, containsimportant last-minute information. Read it first.

• /demo contains some sample applications, useful scripts, and a prebudatabase.

- /databases includes a prebuilt sample database that you can browsefrom Cloudview.

- /programs includes sample applications, including Java programs fothe sample database toursDB, featured in Learning Cloudscape: The Tutorial. Many examples in this book refer to the toursDB sample data-base; you can cut and paste them from the book into either ij or theSQL window of Cloudview.

- /util/methodalias contains scripts for creating useful method aliases.

• /doc contains the on-line documentation (including this document).

• /frameworks contains the libraries, utilities, batch files, and documentation for a specific framework or environment in which to run Cloudscap

Cloudscape installs:

- /embedded/bin—batch files for working in an embedded environmen

- /RmiJdbc—batch files and libraries for working in a client/server envronment if you are using RmiJdbc.

Cloudconnector installs:

- /cloudconnect—batch files, libraries, documentation, examples, andother resources for working in a client/server environment if you areusing Cloudconnector.

• /javadoc contains the documented APIs for the public classes and intefaces. Typically, you use the JDBC interface to interact with Cloudscahowever, you can use some of these additional classes in certain situtions.

• /lib contains the Cloudscape libraries.

Batch Files and Shell Scripts

The /bin subdirectories in environment-specific directories in the frameworks directory contain scripts for running some of the Cloudscape tools and utilitie

NOTE: These scripts serve as examples to help users on all platforms get stwith these tools and utilities. However, they may require modification order to run properly even on Windows or UNIX platforms.

Cloudscape Version 3.0

Page 22: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

After Installing

Clouds

1-4

Some of these files have the same name. To customize your environment, put the appropriate directory first in your path. For example, to use ij in an embedded environment, put CLOUDSCAPE_INSTALL/frameworks/embedded/bin first in your path. To use ij in a client/server environment when working with Cloudconnector, put CLOUDSCAPE_INSTALL/frameworks/cloudconnect/bin first in your path. To use ij in a client/server environment when working with RmiJdbc, put CLOUDSCAPE_INSTALL/frameworks/RmiJdbc/bin first in your path instead.

For more information, see the appropriate directory:

• CLOUDSCAPE_INSTALL/frameworks/embedded/bin

• CLOUDSCAPE_INSTALL/frameworks/RmiJdbc/bin

• CLOUDSCAPE_INSTALL/frameworks/cloudconnect/bin

Cloudscape and JVMsCloudscape has been certified 100% Pure Java. For a list of JVMs with which it has been used, go to www.cloudscape.com/Engineering/vm.html.

Some JVMs are known to have defects; those defects, and workarounds, where known, are described on that Web page.

Incompatibility Between Pre-1.1.6 and 1.2 Databases

Cloudscape uses serialization in its system catalogs and when storing user objects. JDK 1.2 writes out serialized streams in a format different from that of JDK 1.1 releases. If you create a database, or manipulate it, using JDK 1.2, it can be used only with JDKs of version 1.1.6 and higher. JDK 1.1.6 and higher versions can read both formats of serialized streams.

cape Developer’s Guide

Page 23: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Setting the Class Path for Developing Applications 1-5

you

,

ape

s to r s and s:

Setting the Class Path for Developing ApplicationsThe installation program installs all the libraries you need to run Cloudscape and to develop applications that run against Cloudscape. Cloudscape libraries are located in the /lib subdirectory of the cloudscape base directory.

You must set the class path on your development machine to include the appropriate libraries.

Getting Started with Cloudscape explains how to set the class path in a development environment.

The Cloudscape libraries must be “in version” with one another. For example,cannot use cloudscape.jar version 3.0.0 and tools.jar version 3.0.1.

You can use Cloudscape’s sysinfo tool to check the version of Cloudscape products.

java COM.cloudscape.tools.sysinfo

The following excerpt from sysinfo’s output (near the end) indicates a problembecause there are two different version numbers:

-----------------Cloudscape Info-------------------

[d:\cloudscape\cloudscape.jar] version 3.0.0 #8648

[d:\cloudscape\tools.jar] version 3.0.1 #8688

[License Type] Development. Valid.

---------------------------------------------

In addition, you must not include both cloudscape.jar and cloudsync.jar in your class path.

If your code libraries get “out of sync” with each other, please contact Cloudsctechnical support for help in getting the proper versions.

UpgradesTo connect to a database created with a version of Cloudscape prior to 3.0, Cloudscape must upgrade that database. Upgrading involves writing changethe system tables, so it is not possible for databases on read-only media. (Foinformation about upgrading read-only databases, see “Read-Only DatabaseUpgrading” on page 3-16). The upgrade process makes the following change

Cloudscape Version 3.0

Page 24: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

After Installing

Clouds

1-6

te-i-

be

stem

e

ses

the

e run lete. e

n-

• recompiles all stored prepared statements

• adds a new system table

• replaces one system table

• adds new columns to some system tables and drops others

• adds log records

• updates the data dictionary version information

• removes any existing JDBC metadata stored prepared statements

If you have cloudscape.jdbc.metadataStoredPreparedStatements set to dynamic or onDatabaseCreation, existing metadata stored prepared staments are deleted during the upgrade. They will be re-created dynamcally as needed.

• For Cloudscape synchronization systems, DDL statements waiting toreplayed at targets are automatically upgraded during the refresh.

• For Cloudscape synchronization systems, adds indexes to existing sytables.

• For Cloudscape synchronization systems, sets some internal databasproperties.

NOTE: Be sure to read the Release Notes for information about Beta databaand upgrade.

Recommended Steps Before Upgrading

Upgrade happens the first time the new Cloudscape software connections toold database. Before connecting with the new software, perform the followingsteps:

1 Force a checkpoint with the 2.0.x release, so that recovery need not bduring the upgrade and to minimize the time for the upgrade to compTo accomplish this, connect to the database with a 2.0.x version of thCloudscape software and issue a shutdown request using the shut-down=true attribute on the database connection URL:

/* in a java program */

DriverManager.getConnection("jdbc:cloudscape:;shutdown=true");

Cloudscape tools always perform a shutdown in an embedded enviroment.

Opening a local connection to your database with the 3.0 version of Cloudview and then exiting causes the same command to be issued.

cape Developer’s Guide

Page 25: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

UNIX-Specific Issues 1-7

es.

, such f the

2 Back up your database. (Copy the entire system directory, including the entire database directory and the cloudscape.properties file if one exists, to a safe location.)

Once the database is upgraded to 3.0, it cannot be changed back to the 2.0 format.

Upgrading a Database

To upgrade a database, you must explicitly request an upgrade the first time you connect to it with Cloudscape Version 3.0. You explicitly request an upgrade with the database connection URL attribute upgrade=true. For example:

jdbc:cloudscape:toursDB;upgrade=true

Once the upgrade is completed, you cannot connect to the databases with an older version of Cloudscape.

You can find out the version of Cloudscape with the following command:

java COM.cloudscape.tools.sysinfo

NOTE: Note that this is the product version, not the database version. It uses information in the jar files, so verify that only one Cloudscape product’sjar files are in your class path when you run this tool.

Synchronization Databases and Upgrades

NEW: Cloudscape supports automatic upgrade for synchronization databas

UNIX-Specific Issues

Configuring File Descriptors

Cloudscape databases use a large number of files. Some operating systemsas Sun Solaris, limit the number of files an application can open at one time. Idefault is a low number, such as 64, you may run into unexpected IOExceptions

Cloudscape Version 3.0

Page 26: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

After Installing

Clouds

1-8

(wrapped in SQLExceptions). If your operating system lets you configure the number of file descriptors, set this number to a high value, such as 1024.

Scripts

Your installation contains executable script files that simplify invoking the Cloudscape tools. On UNIX systems, these files may need to have their default protections set to include execute privilege. A typical way to do this is with the command chmod +x *.ksh.

Consult the documentation for your operating system for system-specific details.

cape Developer’s Guide

Page 27: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

age

rams.

ent

C.

he

2 JDBC Applications and the Cloudscape Technology

This chapter describes the core Cloudscape functionality common to all the Cloudscape products. In addition, it details the most basic Cloudscape deployment, Cloudscape embedded in a Java application.

• “Application Development Overview” on page 2-1

• “Cloudscape Basics” on page 2-3

• “Cloudscape Embedded Basics” on page 2-26

• “Working with Database Threads in an Embedded Environment” on p2-29

Application Development OverviewCloudscape application developers use JDBC, the application programming interface that makes it possible to access relational databases from Java progThe JDBC API is part of the JDK and is not specific to, or provided by, Cloudscape. It consists of the java.sql package, which is a set of classes and interfaces that make it possible to access databases (from a number of differvendors, not just Cloudscape) from a Java application.

To develop Cloudscape applications successfully, you will need to learn JDBThis chapter does not teach you how to program with the JDBC API; JDBC programming is not specific to Cloudscape. Sun offers a tutorial for learning t

2-1

Page 28: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-2

BC

as the

:

a d -ISO el t

va rce

e QL

JDBC interface, JDBC Database Access with Java, Hamilton, Cattell, and Fisher, Addison-Wesley, 1997.

This chapter covers the details of application programming that are specific to Cloudscape applications. For example, all JDBC applications typically start their DBMS’s JDBC driver and use a database connection URL to connect to a database. This chapter gives you the details of how to start Cloudscape’s JDdriver and how to work with Cloudscape’s database connection URL to accomplish various tasks. It also covers essential Cloudscape concepts suchCloudscape system.

You will find reference information about the particulars of Cloudscape’s implementation of JDBC in the Cloudscape Reference Manual. In addition, Learning Cloudscape: The Tutorial walks you through some of the JDBC basics

• connecting to a database

• using statements and stored prepared statements

• working with result sets

• handling SQLExceptions

Cloudscape application developers should also learn SQL. SQL is the standard query language used with relational databases and is not tied to a particular programming language. (When it was originally created, SQL stood for structured query language, but it does not stand for anything nowadays.) No matter how particular RDBMS has been implemented, the user can design databases aninsert, modify, and retrieve data using the standard SQL statements and welldefined data types. SQL-92 is the version of SQL standardized by ANSI and in 1992; Cloudscape supports entry-level SQL-92 as well as some higher-levfeatures. Entry-level SQL-92 is a subset of full SQL-92 specified by ANSI andISO that is supported by nearly all major DBMSs today. This chapter does noteach you SQL. You will find reference information about the particulars of Cloudscape’s implementation of SQL in the Cloudscape Reference Manual. In addition, Learning Cloudscape: The Tutorial walks you through some SQL basics.

Cloudscape also implements a subset of the JDBC2.0 extensions and the JaTransaction API. This implementation allows Cloudscape to serve as a resoumanager in a J2EE-compliant system. For information, see the Cloudscape Reference Manual.

Cloudscape extends the power of SQL with Java. This topic is worth an entirchapter, so you will find information about Cloudscape’s Java extensions to Sin Chapter 4, “Using Cloudscape’s Java Extensions”, in this book.

cape Developer’s Guide

Page 29: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-3

ct

ich s ns

You may also want to look at the recommendations for further reading listed in “Further Reading” on page -6 in Using the Cloudscape Documentation.

Cloudscape BasicsThis section discusses the basics of the Cloudscape technology. It covers thefollowing topics:

• “Cloudscape JDBC Driver” on page 2-3

• “Cloudscape JDBC Database Connection URL” on page 2-4

• “Cloudscape System” on page 2-5

• “A Cloudscape Database” on page 2-12

• “Connecting to Databases” on page 2-16

Cloudscape JDBC Driver

Cloudscape comes with a local JDBC driver. Applications use JDBC to interawith a database. Applications must load the driver in order to work with the database.

In an embedded environment, loading the driver also starts Cloudscape. In aclient/server environment, starting the server framework starts the local JDBCdriver and Cloudscape. The application starts only the client JDBC driver, whhandles sending the information back and forth over the network. Applicationrunning in embedded mode use a different driver from that used by applicatiorunning in client/server mode.

In a Java application, you typically load the driver with the static Class.forName method or with the jdbc.drivers system property. For example:

Class.forName("COM.cloudscape.core.JDBCDriver").newInstance();

For detailed information about loading the Cloudscape JDBC driver, see “ java.sql.Driver” on page 6-3 in the Cloudscape Reference Manual. See also COM.cloudscape.util.DriverUtil.

Cloudscape Version 3.0

Page 30: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-4

ith 2-20. Data-

see

ou

e:

Cloudscape JDBC Database Connection URL

A Java application using the JDBC API establishes a connection to a database by obtaining a Connection object. The standard way to obtain a Connection object is to call the method DriverManager.getConnection, which takes a String containing a database connection URL (uniform resource locator). A JDBC database connection URL provides a way of identifying a database. It also allows you to perform a number of high-level tasks, such as creating a database or shutting down the system.

An application in an embedded environment uses a different database connection URL from that used by applications in a client/server environment.

However, all versions of the database connection URL (which you can use for tasks besides connecting to a database) have common features:

• you can specify the name of the database you want to connect to

• you can specify a number of attributes and values that allow you to accomplish tasks. For more information about what you can specify wthe Cloudscape database connection URL, see “Examples” on page For detailed reference about attributes and values, see “Cloudscape base Connection URL Syntax” on page 6-5 in the Cloudscape Reference Manual. For information about synchronization attributes and values, the Cloudscape Synchronization Guide.

For syntax of the database connection URL, see “Cloudscape Database Connection URL Syntax” on page 6-5 in the Cloudscape Reference Manual.

An example use of the database connection URL:

Connection conn=DriverManager.getConnection(

"jdbc:cloudscape:toursDB");

NOTE: In most cases, use the database connection URL within your application as an argument to DriverManager.getConnection. However, in a few rare cases, you can use the database connection URL and the attributes ywant as an argument to DriverManager.getConnection within an SQL-J statement. See “Shutting Down the System” on page 2-8. For exampl

-- shuts down the current database

CALL (CLASS java.sql.DriverManager).getConnection(

’jdbc:cloudscape:;current=true;shutdown=true’)

cape Developer’s Guide

Page 31: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-5

e

tial tem is ions.

Cloudscape System

A Cloudscape database exists within a system.

A Cloudscape system is a single instance of Cloudscape and the environment in which it runs. It consists of a system directory, zero or more databases, and a system-wide configuration. The system directory contains any persistent system-wide configuration parameters, or properties, specific to that system in a properties file called cloudscape.properties (see “cloudscape.properties” on page 2-9). This file is not automatically created; you must create it yourself.

It also usually contains an information log about activity in the most recent session of the Cloudscape system.

The Cloudscape system is not persistent; you must specify the location of thsystem directory at every startup.

However, the system—as well as its directory, which you name—is an essenpart of a running database or databases. Understanding the Cloudscape sysessential to successful development and deployment of Cloudscape applicat

Cloudscape Version 3.0

Page 32: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-6

he

e

two me

Figure 2-1 Cloudscape databases live in a system, which includes system-wide properties, an error log, and one or more databases.

The system directory can also contain an error log file called cloudscape.LOG (see “The Information (Error) Log” on page 2-9).

Each database within that system is contained in a subdirectory, which has tsame name as the database (see “A Cloudscape Database” on page 2-12).

You can use a property (see “cloudscape.service” on page 5-53 in Tuning Cloudscape) to include databases in other directories or in subdirectories of thsystem directory in the current system when you start it up.

In addition, if you connect to a database outside the current system, it automatically becomes part of the current system.

One Cloudscape per System

You could potentially have two instances of Cloudscape running on the samemachine at the same time, but each instance must run in a different system; separate instances of Cloudscape should not access databases within the sa

Cloudscape

AccountingDB

SalesDBcloudscape.properties

cloudscape.system.home(value of this system variable tells Cloudscapethe name of your system directory)

cloudscape.LOG

cape Developer’s Guide

Page 33: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-7

ing nect

some

e in the u use

ctive

g:

the

system. For example, in an embedded environment, an application that accesses Cloudscape databases starts up the local JDBC driver, which starts up an instance of Cloudscape. In an embedded system, do not run both ij and Cloudview (or two ijs, or two Cloudviews, or any two applications) in the same system or on the same database at the same time; severe database corruption can result. See “Double-Booting System Behavior” on page 2-9.

In a client/server environment, you do not have to worry about two client applications corrupting a database. In a client/server environment, client applications start up the remote JDBC driver and connect to an already runnserver. The server framework is designed to allow multiple applications to conto the same database.

Booting

The default configuration for Cloudscape is that Cloudscape boots a database when an application first makes a connection to it. When Cloudscape boots adatabase, it checks to see if recovery needs to be run on the database, so inunusual cases booting may take some time.

You can also configure your system to automatically boot all databases in thesystem when it starts up; see “cloudscape.system.bootAll” on page 5-72 in Tuning Cloudscape. That is the recommended configuration when you use Cloudscapa client/server environment. Because of the time needed to boot a database,number of databases in the system directory affects startup performance if yothat configuration.

Once a database has been booted within a Cloudscape system, it remains auntil the Cloudscape system has been shut down or until you shut down the database individually.

When Cloudscape boots a database, it prints a message in the information lo

Wed May 20 14:31:38 PDT 1998:

Booting Cloudscape Version 2.0.0 instance 80000000-00d0-8bdf-

d115-000a0a0b2d00 on database at directory

C:\cloudscape\demo\databases\toursDB

The number of databases running in a Cloudscape system is limited only by amount of memory available in the JVM.

Cloudscape Version 3.0

Page 34: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-8

se

log:

t

that

tart

scape

ting it

Shutting Down the System

In an embedded environment, when an application shuts down, it should first shut down Cloudscape.

If the application that started the embedded Cloudscape quits but leaves the JVM running, Cloudscape continues to run and is available for database connections.

In an embedded system, the application shuts down Cloudscape by issuing the following JDBC call:

DriverManager.getConnection(’jdbc:cloudscape:;shutdown=true’);

To shut down the system within an SQL-J statement, you can use the following:

CALL (CLASS java.sql.Driver).getConnection(

’jdbc:cloudscape:;shutdown=true’)

Shutdown commands always raise SQLExceptions. See “Shutting Down Cloudscape or an Individual Database” on page 2-22.

When Cloudscape runs as a database server, it typically runs continuously. Uonly the prescribed utility for shutting it down. See the Cloudscape Server and Administration Guide for more details.

When a Cloudscape system shuts down, a message goes to the information

Wed May 20 14:31:54 PDT 1998:

Shutting down Cloudscape instance 80000001-00d0-8bdf-d115-

000a0a0b2d00

Typically, an application using an embedded Cloudscape engine shuts downCloudscape just before shutting itself down. However, an application can shudown Cloudscape and later restart it in the same JVM session. To restart Cloudscape successfully, the JVM needs to unload COM.cloudscape.core.JDBCDriver, so that it can reload it when it restarts Cloudscape. (Loading the local driver starts Cloudscape.)

You cannot explicitly request that the JVM unload a class, but you can ensurethe JDBCDriver class is unloaded by using a System.gc() to force it to garbage collect classes that are no longer needed. Running with -nogc or -noclassgc definitely prevents the class from being unloaded and makes you unable to resCloudscape in the same JVM.

It is also possible to shut down a single database instead of the entire Cloudsystem. See “Shutting Down Cloudscape or an Individual Database” on page2-22. You can reboot a database in the same Cloudscape session after shutdown.

cape Developer’s Guide

Page 35: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-9

here

eates y.

ns es . You h the

ally d by

,

e e

Defining the System Directory

You define the system directory when Cloudscape starts up by specifying a Java system property called cloudscape.system.home. If you do not specify the system directory when starting up Cloudscape, the current directory becomes the system directory. (For information on setting this and other properties, see Tuning Cloudscape.)

NOTE: Cloudscape recommends that you always explicitly specify the system directory when starting up Cloudscape.

Cloudscape uses the cloudscape.system.home property to determine which directory is its system directory—and thus what databases are in its system, wto create new databases, and what configuration parameters to use.

If you specify a system directory at startup that does not exist, Cloudscape crthis new directory—and thus a new system with no databases—automaticall

The Information (Error) Log

Once you create or connect to a database within a system, Cloudscape begioutputting information and error messages, if any. Typically, Cloudscape writthis information to a log called cloudscape.LOG in the system directory, althoughyou can also have Cloudscape send messages to a stream, using a propertycan also configure whether Cloudscape writes over or appends to the log witcloudscape.infolog.append property. (For information on setting this and other properties, see Tuning Cloudscape.)

cloudscape.properties

The text file cloudscape.properties contains the definition of properties, or configuration parameters valid for the entire system. This file is not automaticcreated; you should create it yourself. The file should be in the format createthe java.util.Properties.save method. A sample cloudscape.properties file is provided in /demo/programs/tours/scripts. For more information about propertiessee Tuning Cloudscape.

Double-Booting System Behavior

Cloudscape attempts to prevent two instances of Cloudscape from booting thsame database by using a file called db.lck inside the database directory (see “ThDatabase Directory” on page 2-12).

Cloudscape Version 3.0

Page 36: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-10

On some platforms, Cloudscape can successfully prevent a second instance of Cloudscape from booting the database, and thus prevents corruption. If this is the case, you will see an SQLException like the following:

ERROR XJ040: Failed to start database ’toursDB’, see the next

exception for details.

ERROR XSDB6: Another instance of Cloudscape may have already

booted the database C:\databases\toursDB.

The error is also written to the information log.

On other platforms, Cloudscape issues a warning message if an instance of Cloudscape attempts to boot a database that may already have a running instance of Cloudscape attached to it. However, it does not prevent the second instance from booting, and thus potentially corrupting, the database. (You can change this behavior with the property cloudscape.database.forceDatabaseLock.)

If a warning message has been issued, corruption may already have occurred.

NOTE: When you are using Cloudview, error messages appear in the console or operating system window from which Cloudview was started.

The warning message looks like this:

WARNING: Cloudscape (instance 80000000-00d2-3265-de92-

000a0a0a0200) is attempting to boot the database /export/home/

sky/wombat even though Cloudscape (instance 80000000-00d2-

3265-8abf-000a0a0a0200) may still be active. Only one instance

of Cloudscape

should boot a database at a time. Severe and non-recoverable

corruption can result and may have already occurred.

The warning is also written to the information log.

This warning is primarily a Technical Support aid to determine the cause of corruption. However, if you see this warning, your best choice is to close the connection and exit the JVM. This minimizes the risk of a corruption. Close all instances of Cloudscape, then restart one instance of Cloudscape and shut down the database properly so that the db.lck file can be removed. The warning message continues to appear until a proper shutdown of the Cloudscape system can delete the db.lck file.

When developing applications, you may want to configure Cloudscape to append to the log. Doing so will help you detect when you have inadvertently started more than one instance of Cloudscape in the same system. For example, when the cloudscape.infolog.append property is set to true for a system, booting two instances of Cloudscape in the same system produces the following in the log:

cape Developer’s Guide

Page 37: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-11

em-

of

-

d

e, hat

Thu Aug 06 09:42:51 PDT 1998:

Booting Cloudscape instance 80000000-00d2-1c87-7586-

000a0a0b1300 on database at directory

C:\tutorial_system\toursDB

------------------------------------------------------------

Thu Aug 06 09:42:59 PDT 1998:

Booting Cloudscape instance 80000000-00d2-1c87-9143-

000a0a0b1300 on database at directory

C:\tutorial_system\HelloWorldDB

NOTE: Cloudscape allows you to boot databases that are not in the system directory. While this may seem more convenient, it may cause more problems with double-booting.

Recommended Practice

When developing Cloudscape applications, create a single directory to hold your database or databases. Name this directory something like cloudscape_system or database_directory. Doing so will help you remember that:

• All databases exist within a system.

• System-wide properties affect the entire system, and persistent systwide properties live in the system directory.

• You can boot all the databases in the system, and the boot-up timesall databases affect the performance of the system.

• You can preboot databases only if they are within the system. (Databases do not necessarily have to live inside the system directory, but keeping your databases there is the recommended practice.)

• Once you connect to a database, it is part of the current system (anthus inherits all system-wide properties).

• Only one instance of Cloudscape can run in a system at a single timand only one instance of Cloudscape should boot a database at onetime (keeping databases in the system directory makes it less likely tyou would use more than one instance of Cloudscape).

• To back up a database or databases, back up the entire system.

• The error log lives inside the system directory.

Cloudscape Version 3.0

Page 38: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-12

ame

2-13:

as

r iety of to set d-

ou

A Cloudscape Database

A Cloudscape database contains dictionary objects such as tables, columns, indexes, and jar files. A Cloudscape database also stores its own configuration information.

• “The Database Directory” on page 2-12

• “Creating, Dropping, and Backing Up Databases” on page 2-13

• “Storage and Recovery” on page 2-14

• “Log on Separate Device” on page 2-15

• “Database Pages” on page 2-15

• “Version 3.0 Database Limitations” on page 2-15

The Database Directory

A Cloudscape database is stored in files that live in a directory of the same nas the database. Database directories typically live in system directories (see “Cloudscape System” on page 2-5).

A database directory contains the following, as shown in Figure 2-2 on page

• log directory

Contains files that make up the database log, used internally for datarecovery (not the same thing as the information log).

• seg0 directory

Contains one file for each user table, system table, and index (knownconglomerates), plus one file for internal tables.

• service.properties file

A text file with internal configuration information.

• tmp directory

(May or may not exist.) A temporary directory used by Cloudscape folarge sorts and deferred updates and deletes. Sorts are used by a varSQL-J statements. For databases on read-only media, you may needa property to change the location of this directory. See “Creating Clouscape Databases for Read-Only Use” on page 3-12.

• jar directory

(May or may not exist.) A directory in which jar files are stored when yuse database class loading.

cape Developer’s Guide

Page 39: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-13

) into in a

ies

to the

se d

on

then ystem

• cloudscape.db file

Provided for file finders.

Read-only database directories can be archived (and compressed, if desiredjar or zip files. For more information, see “Accessing a Read-Only Database Zip/Jar” on page 3-14.

Figure 2-2 Cloudscape database directories contain files and directorused by the software.

Creating, Dropping, and Backing Up Databases

You create new databases and access existing ones by specifying attributes Cloudscape database connection URL (see “Examples” on page 2-20).

There is no drop database command. To drop a database, delete the databadirectory with operating system commands. The database must not be bootewhen you remove a database. You can get a list of booted databases with getPropertyInfo (see “Offering Connection Choices to the User” on page 9-2).

To back up a database, you can use the online backup utility. For informationusing this utility, see the Cloudscape Server and Administration Guide.

NEW: The backup utility is new in Version 3.0.

A simpler way to back up a Cloudscape database is simply to use operating system tools to copy the database directory. Simply shut down Cloudscape, back up databases in the context of their system. That is, back up the entire sdirectory in order to back up:

• the database directory

• persistent system-wide configuration properties (cloudscape.properties)

SalesDB

service.properties

log

seg0

tmp

jar

cloudscape.DB

Cloudscape Version 3.0

Page 40: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-14

and

e

ay be e n

the

are . Thus

ual ning re

to be

You can use compression tools such as pkzip, which may be necessary to reduce database size for backup storage.

To back up a single database when there is more than one database in the system directory, create a new “system” folder. Copy the database folder and the cloudscape.properties files to the new folder. Then back up that folder.

Single Database Shutdown

An application can shut down a single database within a Cloudscape systemleave the rest of the system running. See “Shutting Down Cloudscape or an Individual Database” on page 2-22.

Storage and Recovery

A Cloudscape database provides persistent storage and recovery. Cloudscapensures that all committed transactions are durable, even if the system fails, through the use of a database log. Whereas inserts, updates, and deletions mcached before being written to disk, log entries tracking all those changes arnever cached but always written to disk. If the system fails unexpectedly, wheCloudscape next starts up it can use the log to perform recovery, recovering “lost” transactions from the log and rolling back uncommitted transactions. Recovery ensures that all committed transactions at the time the system failedapplied to the database, and all transactions that were active are rolled backthe databases are left in a consistent, valid state.

In normal operation, Cloudscape keeps the log small through periodic checkpoints. Checkpointing marks the portions of the log that are no longer useful, writes changed pages to disk, then truncates the log.

Cloudscape checkpoints the log as it fills. It also checkpoints the log when a shutdown command is issued; see “Shutting Down Cloudscape or an IndividDatabase” on page 2-22. Shutting down the JVM in which Cloudscape is runwithout issuing the proper shutdown command is equivalent to a system failufrom Cloudscape’s point of view.

Booting a database means that Cloudscape checks to see if recovery needsrun on a database. Recovery can be costly, so using the proper shutdown command improves connection or startup performance.

cape Developer’s Guide

Page 41: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-15

te not

ore de, rows use, an

that ages.

set in s

s

Log on Separate Device

NEW: Beginning with Version 3.0, you can put a database’s log on a separadevice when you create it. (This is useful for improving performance, for improved recovery.) For more information, see the Cloudscape Server and Administration Guide.

Database Pages

Cloudscape tables and indexes, known as conglomerates, consist of two or mpages. A page is a unit of storage whose size is configurable on a system-widatabase-wide, or conglomerate-specific basis. By default, a conglomerate gone page at a time until eight pages of user data (or nine pages of total disk which includes one page of internal information) have been allocated. (You cconfigure this behavior; see “cloudscape.storage.initialPages” on page 5-55 in Tuning Cloudscape.). After that, it grows eight pages at a time.

The size of a row or column is not limited by the page size. Rows or columnsare longer than the table’s page size are automatically wrapped to overflow p

Database-Wide Properties

You can set many Cloudscape properties as database-level properties. Whenthis way, they are stored in the database and “travel” with the database unlesoverridden by a system property. For more information, see “Database-WideProperties” on page 1-7 in Tuning Cloudscape.

NOTE: Cloudscape recommends that you work with database-level propertiewherever possible.

Version 3.0 Database Limitations

A Version 3.0 Cloudscape database has these limitations:

• Indexes are not supported for long rows.This means that if the length of the key columns in an index is larger than half the page size of the index, creating an index on those key columns for the table fails. For existing indexes, an insert of new rows for which the key columns are larger than half of the index page size causes the insert to fail.

NOTE: Indexing on long columns is a bad idea in any case. Create indexes on small columns that provide a quick look-up to larger, unwieldy data in the

Cloudscape Version 3.0

Page 42: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-16

the

tion

” on

ing ctory.

chive nvi-

for

row. Indexing on long columns does not provide the performance improvements that indexes usually provide. For information about indexes, see Tuning Cloudscape. However, it is possible to tune the page size of indexes to allow for larger rows, if you wish.

• The system shuts down if the database log cannot allocate more diskspace.There will be a “LogFull” error in cloudscape.LOG or some sort of IOEx-ception if it runs out of space in places other than the log, or nothing if system has no more disk space to append to cloudscape.LOG.

Connecting to Databases

You connect to a database using a form of the Cloudscape database connecURL as an argument to the DriverManager.getConnection call (see “Cloudscape JDBC Database Connection URL” on page 2-4). You specify a path to the database within this database connection URL.

• “Standard Connections—Connecting to Databases in the File Systempage 2-17

The standard way to access databases is in the file system by specifythe path to the database, either absolute or relative to the system direIn a client/server environment, this path is always the server’s path.

• “Special Database Access” on page 2-18

It is also possible to connect to databases in the class path or in an arfile (and even to an archive file in the class path). (In a client/server eronment, this refers to the server’s class path). Connections of this kind are always read-only.

• “Examples” on page 2-20

The examples in this section use the syntax of the database connection URLuse in an embedded environment. This information also applies to the client database connection URL in a client/server environment. For reference information about client database connection URLs, see “java.sql.Connection” on page 6-11 in the Cloudscape Reference Manual.

cape Developer’s Guide

Page 43: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-17

the URL.

ies of y the ting

lly

pe it

ings. stem

s

Standard Connections—Connecting to Databases in the File System

Within the System

By default, you can connect to databases within the current system directory (see “Defining the System Directory” on page 2-9). To connect to databases withincurrent system, just specify the database name on the database connection For example, if your system directory contains a database called myDB, you can connect to that database with the following database connection URL:

jdbc:cloudscape:myDB

The full call within a Java program would be:

Connection conn = DriverManager.getConnection("jdbc:cloudscape:myDB");

Outside the System Directory

You can also connect to databases in other directories (including subdirectorthe system directory) by specifying a relative or absolute path name to identifdatabase. The way you specify an absolute path is defined by the host operasystem (see java.io.File.isAbsolute). You must specify a path for a database in adirectory other than the system directory even if you have defined the cloudscape.service property to have Cloudscape boot the database automatica(see “cloudscape.service” on page 5-53 in Tuning Cloudscape).

Using the database connection URL as described here, you can connect to databases in more than one directory at a time.

Two examples:

jdbc:cloudscape:../otherDirectory/myDB

jdbc:cloudscape:c:/otherDirectory/myDB

NOTE: Once connected to, such a database becomes a part of the Cloudscasystem, even though it is not in the system directory. This means thattakes on the system-wide properties of the system and that no other instance of Cloudscape should access that database, among other thCloudscape recommends that you connect to databases only in the sydirectory. See “Recommended Practice” on page 2-11 for suggestionabout working with a Cloudscape system.

Cloudscape Version 3.0

Page 44: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-18

the

M is

ctual

same onical

ready tory,

a on .

lass

e. he

Conventions for Specifying the Database Path

When accessing databases from the file system (instead of from class path or a jar file), any path that is not absolute is interpreted as relative to the system directory.

The path must do one of the following:

• refer to a previously created Cloudscape database

• specify the create=true attribute

The path separator in the database connection URL is / (forward slash), as instandard file:// URL protocol.

You can specify only databases that are local to the machine on which the JVrunning. NFS file systems on UNIX and remote shared files on Windows (//machine/directory) are not guaranteed to work.

If two different database name values, relative or absolute, refer to the same adirectory, they are considered equivalent. This means that connections to a database through its absolute path and its relative path are connections to thedatabase. Within Cloudscape, the name of the database is defined by the canpath of its directory from java.io.File.getCanonicalPath.

Cloudscape automatically creates any intermediate directory that does not alexist when creating a new database. If it cannot create the intermediate directhe database creation fails.

If the path to the database is ambiguous, i.e., potentially the same as that to database that is available on the class path (see “Special Database Access” page 2-18), use the directory: subsubprotocol to specify the one in the file systemFor example:

jdbc:cloudscape:directory:myDB

Special Database Access

You can also access databases from the class path or from a jar file (in the cpath or not) as read-only databases.

From the Class Path

In most cases, you access databases from the file system as described abovHowever, it is also possible to access databases from the user’s class path. Tdatabases can be archived into a jar or zip file or left as is.

NOTE: All such databases are treated as read-only databases.

cape Developer’s Guide

Page 45: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-19

uous

not

can

jar

ee

To access an unarchived database from the class path, specify the name of the database relative to the directory in the class path. (Even a database directly under such a directory would require a forward slash, to show that it is relative to that directory.) You can use the class path subprotocol (see “Standard Cloudscape JDBC Database Connection URL” on page 2-26) if such a database is ambigwith one in the directory system.

For example, for a database called toursDB in C:\cloudscape\demo\databases, you could put the C:\cloudscape\demo\databases directory in the user’s class pathand access toursDB like this:

jdbc:cloudscape:/toursDB

The forward slash is required before toursDB to indicate that it is relative to C:\cloudscape\demo\databases directory.

If only C:\cloudscape were in the class path, you could access toursDB (read-only) like this:

jdbc:cloudscape:/demo/databases/toursDB

From a Jar or Zip File

It is possible to access databases from a jar file. The jar file can be, but doeshave to be, on the user’s class path.

NOTE: All such databases are read-only.

For example, suppose you have archived the database jarDB1 into a file called jar1.jar. This archive is in the class path before you start up Cloudscape. Youaccess jarDB1 like this:

Connect ’jdbc:cloudscape:/jarDB1’;

To access a database in a jar file that is not on the user’s class path, use thesubprotocol.

For example, suppose you have archived the database jarDB2 into a file called jar2.jar. This archive is not in the class path. You can access jarDB2 by specifying the path to the jar file along with the jar subsubprotocol, like this:

jdbc:cloudscape:jar:(c:/cloudscape/lib/jar2.jar)jarDB2

For complete instructions and examples of accessing databases in jar files, s“Accessing a Read-Only Database in a Zip/Jar” on page 3-14.

Cloudscape Version 3.0

Page 46: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-20

Examples

Here are more example database connection URLs:

• jdbc:cloudscape:db1Open a connection to the database db1. db1 is a directory located in the system directory.

• jdbc:cloudscape:london/salesOpen a connection to the database london/sales. london is a subdirectory of the system directory, and sales is a subdirectory of the directory lon-don.

• jdbc:cloudscape:/reference/phrases/frenchOpen a connection to the database /reference/phrases/french.

On a UNIX system, this would be the path of the directory. On a Windows system, the path would be C:\reference\phrases\french if the current drive were C. If a jar file storing databases were in the user’s class path, thiscould also be a path within the jar file.

• jdbc:cloudscape:a:/demo/toursDBOpen a connection to the database stored in the directory \demo\toursDB on drive A (usually the floppy drive) on a Windows system.

• jdbc:cloudscape:c:/databases/salesdbjdbc:cloudscape:salesdbThese two database connection URLs connect to the same database, salesdb, on a Windows platform if the system directory of the Cloudscape system is C:\databases.

• jdbc:cloudscape:support/bugsdb;create=trueCreate the database support/bugsdb in the system directory, automatically creating the intermediate directory support if it does not exist.

• jdbc:cloudscape:toursDB;shutdown=trueShut down the toursDB database.

• jdbc:cloudscape:/myDBAccess myDB (which is directly in a directory in the class path) as a read-only database.

• jdbc:cloudscape:classpath:/myDBAccess myDB (which is directly in a directory in the class path) as a read-only database. The reason for using the subsubprotocol is that it may hap-pen to have the same path as a database in the directory structure.

• jdbc:cloudscape:jar:(C:/dbs.jar)products/boiledfoodAccess the read-only database boiledfood in the products directory from the jar file C:/dbs.jar.

cape Developer’s Guide

Page 47: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-21

se in alues

abase

in the

• jdbc:cloudscape:directory:myDBAccess myDB, which is in the system directory. The reason for using the directory: subsubprotocol is that it may happen to have the same path as a database in the class path.

Working with the Database Connection URL Attributes

You specify pairs of attributes and values on the Cloudscape database connection URL (see “Cloudscape JDBC Database Connection URL” on page 2-4). The examples in this section use the syntax of the database connection URL for uan embedded environment. You can also specify these same attributes and von the client database connection URL if you are using Cloudscape as a datserver. For more information, see the Cloudscape Server and Administration Guide.

You can also set these attributes by passing a Properties object along with a database connection URL to DriverManager.getConnection when obtaining a connection; see “Specifying Attributes in a Properties Object” on page 2-25.

For detailed information about the database connection URL syntax and attributes, see “Cloudscape Database Connection URL Syntax” on page 6-5 Cloudscape Reference Manual.

You can specify the following attributes:

• shutdown=true

See “Shutting Down Cloudscape or an Individual Database” on page 2-22.

• create=true

See “Creating and Accessing a Database” on page 2-23.

• autocommit=false

See “Turning Off Auto-Commit” on page 2-24.

• current=true

See “Getting a Nested Connection” on page 2-24.

• databaseName=nameofDatabase

See “Accessing an Existing Database” on page 2-23.

• user=userName

See “Providing a User Name and Password” on page 2-24.

Cloudscape Version 3.0

Page 48: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-22

by t ecify

• password=userPassword

See “Providing a User Name and Password” on page 2-24.

• dataEncryption=true

See “Encrypting a Database When You Create It” on page 2-24.

• bootPassword=key

See “Booting an Encrypted Database” on page 2-25.

• (no attributes)See “Accessing an Existing Database” on page 2-23.

• upgrade=true

See “Upgrading a Database” on page 2-25.

• logDevice=logDirectoryPath

See the Cloudscape Server and Administration Guide.

• synchronization attributes

See the Cloudscape Synchronization Guide.

Shutting Down Cloudscape or an Individual Database

Applications in an embedded environment shut down the Cloudscape systemspecifying the shutdown=true attribute in the database connection URL. To shudown the system, you do not specify a database name, and you must not spany other attribute.

jdbc:cloudscape:;shutdown=true

A successful shutdown always results in an SQLException to indicate that Cloudscape has shut down and that there is no other exception.

NOTE: Cloudconnector is shut down with a utility. See the Cloudscape Server and Administration Guide.

You can also shut down an individual database if you specify the databaseName. You can shut down the database of the current connection if you specify the current=true attribute instead of a database name (within an SQL-J statement).

// shutting down a database from your application

DriverManager.getConnection(

’jdbc:cloudscape:toursDB;shutdown=true’);

-- shutting down the current database using SQL

CALL (CLASS java.sql.DriverManager).getConnection(

’jdbc:cloudscape:;current=true;shutdown=true’)

cape Developer’s Guide

Page 49: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-23

NOTE: Any request to the DriverManager with a shutdown=true attribute raises an exception, so expect this behavior when shutting down.

Creating and Accessing a Database

You create a standard (non-synchronization) database by supplying a new database name with the database connection URL and specifying create=true. Cloudscape creates a new database inside a new subdirectory in the system directory with the same name as the new database. If you specify a partial path, it is relative to the system directory. You can also specify an absolute path.

jdbc:cloudscape:databaseName;create=true

For more details about create=true, see “create=true” on page 7-4 in the Cloudscape Reference Manual.

For more information on creating synchronization databases, see the Cloudscape Synchronization Guide.

Accessing an Existing Database

You access an existing database by specifying it in the Cloudscape databaseconnection URL in one of the following:

• the subprotocol to jdbc:cloudscape:

• the databaseName attribute

The database must exist (see also “Standard Connections—Connecting to Databases in the File System” on page 2-17).

As the Subprotocol

jdbc:cloudscape:databaseName

Using the databaseName Attribute

jdbc:cloudscape:;databaseName=databaseName

You can use autocommit=false with this attribute. For more details, see “(no attributes)” on page 7-14 and “databaseName=nameofDatabase” on page 7-6 in the Cloudscape Reference Manual.

You can access read-only databases in jar or zip files by specifying jar as thesubsubprotocol, like this:

Cloudscape Version 3.0

Page 50: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-24

use ents.

t for

e and see

an this,

jdbc:cloudscape:jar:(pathToArchive)databasePathWithinArchive

Or, if the jar or zip file has been included in the class path, like this:

jdbc:cloudscape:/databasePathWithinArchive

Turning Off Auto-Commit

You can turn off auto-commit with autocommit=false. For information about auto-commit, see “Using Auto-Commit” on page 6-4.

jdbc:cloudscape:databaseName;autocommit=false

Getting a Nested Connection

When you are executing a method within SQL-J, that method may need to rethe current connection to the database in order to execute more SQL-J statemSuch a connection is called a nested connection. One way for a method to get a nested connection is to issue a connection request with current=true as an attribute to the database connection URL.

jdbc:cloudscape:;current=true

If you combine this attribute with any other attributes, they are ignored (excepshutdown). For more details, see “current=true” on page 7-5 in the Cloudscape Reference Manual.

Providing a User Name and Password

When user authentication is enabled, an application must provide a user nampassword. One way to do this is to use database connection URL attributes (“user=userName” on page 7-13 and “password=userPassword” on page 7-9).

jdbc:cloudscape:toursDB;user=jill;password=toFetchAPail

For more information, see “Working with User Authentication” on page 8-5.

Encrypting a Database When You Create It

If your environment is configured properly, you can created your database asencrypted database (one in which the database is encrypted on disk). To do you use the dataEncryption=true attribute to turn on encryption and the bootPassword=key attribute to specify a key for the encryption. For more

cape Developer’s Guide

Page 51: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Basics 2-25

For on

f no

ecify nt

for

information about data encryption, see “Encrypting Databases on Disk” on page8-27.

jdbc:cloudscape:encryptedDB;create=true;bootPassword=cloudscape

Booting an Encrypted Database

You must specify the encryption key with the bootPassword=key attribute for an encrypted database when you boot it (which is the first time you connect to itwithin a JVM session or after shutting it down within the same JVM session).more information about data encryption, see “Encrypting Databases on Disk”page 8-27.

jdbc:cloudscape:encryptedDB;bootPassword=clo760uds2caPe

Upgrading a Database

To upgrade a database, use the upgrade=true attribute the first time you connect toit. See “Upgrades” on page 1-5 for more information. The attribute is ignored iupgrade is needed.

Specifying Attributes in a Properties Object

Instead of specifying attributes on the database connection URL, you can spattributes as properties in a Properties object that you pass as a second argumeto the DriverManager.getConnection method. For example, to set the autocommit attribute to false, you could set the autocommit property to false instead, as in thefollowing example:

Class.forName("COM.cloudscape.core.JDBCDriver").newInstance();

Properties p = new Properties();

p.put("autocommit", "false");

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:mynewDB", p);

NOTE: This method works only for database connection URL attributes, not Cloudscape properties.

Cloudscape Version 3.0

Page 52: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-26

26

age

dded

ape is

e

Cloudscape Embedded BasicsThis section explains how to use and configure Cloudscape in an embedded environment. Included in the installation is a sample application program, /demo/programs/simple, which illustrates how to run Cloudscape embedded in the calling program.

It includes the following topics:

• “Embedded Cloudscape JDBC Driver” on page 2-26

• “Standard Cloudscape JDBC Database Connection URL” on page 2-

• “Starting Cloudscape as an Embedded Database” on page 2-28

• “Working with Database Threads in an Embedded Environment” on p2-29

Embedded Cloudscape JDBC Driver

The Cloudscape driver class name for the embedded environment is COM.cloudscape.core.JDBCDriver. In a Java application, you typically load thedriver with the static Class.forName method or with the jdbc.drivers system property. For more information, see “Starting Cloudscape as an Embedded Database” on page 2-28.

For detailed information about loading the Cloudscape JDBC driver, see “ java.sql.Driver” on page 6-3 in the Cloudscape Reference Manual.

Standard Cloudscape JDBC Database Connection URL

This section discusses the database connection URL for working in an embeenvironment. In addition, in a client/server environment, the JDBC server framework essentially “translates” a client database connection URL into thisstandard (embedded) database connection URL. For example, when Cloudscrunning in the Cloudconnector environment, a client application might use thfollowing database connection URL:

jdbc:cloudscape:weblogic://godfrey:7001/toursDB;create=true

Cloudconnector passes the following standard database connection URL to Cloudscape:

jdbc:cloudscape:toursDB;create=true

cape Developer’s Guide

Page 53: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Embedded Basics 2-27

” to

jar

ame:

a Zip/

. For

t

For that reason, this section provides useful information for all environments.

The standard Cloudscape JDBC database connection URL (which you can use for tasks besides connecting to a database) is

jdbc:cloudscape:[subsubprotocol:][databaseName]

[;attribute=value]*

In JDBC lingo, cloudscape is the subprotocol for connecting to a Cloudscape database. The subprotocol is always cloudscape and does not vary.

Subsubprotocol, which is not typically specified, determines how Cloudscape looks for a database: in a directory, in a class path, or in a jar file. It is used only in rare instances, usually for read-only databases. Subsubprotocol is one of the following:

- directoryThe default. Specify this explicitly only to distinguish a database that may be ambiguous with one on the class path.

- classpathDatabases are treated as read-only databases, and all databaseNames must begin with at least a slash, because you specify them “relativethe class path directory. See “From the Class Path” on page 2-18.

- jarDatabases are treated as read-only databases. databaseNames may require a leading slash, because you specify them “relative” to the file. See “From a Jar or Zip File” on page 2-19.

jar requires an additional element immediately before the database n

(pathToArchive)

pathToArchive is the path to the jar or zip file that holds the database.

For examples of using this syntax, see “Accessing a Read-Only Database in Jar” on page 3-14.

You typically pass the database connection URL as an argument to the JDBCDriverManager.getConnection method call. For example:

DriverManager.getConnection(

"jdbc:cloudscape:toursDB;autocommit=false");

You can specify attributes and attribute values to a database connection URLmore information about what you can specify with the Cloudscape database connection URL, see “Examples” on page 2-20. For detailed reference abou

Cloudscape Version 3.0

Page 54: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-28

RL,

ent

you

e

to any ith the

page

attributes and values, see “Cloudscape Database Connection URL Syntax” on page 6-5 in the Cloudscape Reference Manual.

For information about the client/server version of the database connection Usee the Cloudscape Server and Administration Guide.

Starting Cloudscape as an Embedded Database

To start Cloudscape, you start the Cloudscape JDBC driver. Starting the Cloudscape driver starts up the complete Cloudscape system within the currJVM.

For example, when using the JBDC driver manager directly within Java code,typically start a JDBC driver in one of two ways:

• Specify the jdbc.drivers system property, which allows users to customizthe JDBC drivers used by their applications. For example:

java -Djdbc.drivers=COM.cloudscape.core.JDBCDriver

applicationClass

• Load the class directly from Java code using the static method Class.for-Name. For example:

Class.forName("COM.cloudscape.core.JDBCDriver").newInstance();

For more details, see “java.sql.Driver” on page 6-3 in the Cloudscape Reference Manual.

Once the Cloudscape JDBC driver class has been loaded, you can connect Cloudscape database by passing the embedded database connection URL wappropriate attributes to the DriverManager.getConnection method (see “Accessing an Existing Database” on page 2-23).

For example:

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:toursDB;autocommit=false");

For more information about connecting to a database, see “Connections” on 6-2.

cape Developer’s Guide

Page 55: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape Embedded Basics 2-29

tion

e

Working with Database Threads in an Embedded Environment

Do not use sleep and interrupt calls to notify threads that are accessing a database, because Cloudscape will catch the interrupt call and close the connection to the database. Use wait and notify calls instead.

This won’t happen in a client/server environment, but if you want your applicato work in either environment it is good practice to follow this rule.

There are special considerations when working with more than one databasethread in an application. See “Working with Multiple Connections to a Single Database” on page 6-27 and “Working with Multiple Threads Sharing a SinglConnection” on page 6-30.

Cloudscape Version 3.0

Page 56: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

JDBC Applications and the Cloudscape Technology

Clouds

2-30

cape Developer’s Guide

Page 57: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

erver.

3 Deploying Cloudscape Applications

Typically, once you have developed a Cloudscape application and database, you package up the application, the Cloudscape libraries, and the database in some means for distribution to your users. This process is called deployment.

This chapter discusses issues for deploying Cloudscape applications and databases.

• “Deployment Issues” on page 3-1

• “Creating Cloudscape Databases for Read-Only Use” on page 3-12

• “Loading Classes from a Database” on page 3-17

Deployment IssuesThis section discusses deployment options and details.

• “Deployment Options” on page 3-1

• “Choosing a Deployment Option” on page 3-5

• “Deploying Java Classes for Use as Java Data Types” on page 3-6

• “Deployment Cheat Sheets” on page 3-8

Deployment Options

Cloudscape has two basic deployment environments: embedded and client/s

3-1

Page 58: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-2

Embedded Deployment Application Overview

In an embedded environment, Cloudscape runs in the same JVM as the application. Depending on the Cloudscape deployment license that you purchase, the application can be a single-user application or a multi-user application server. In the latter case, Cloudscape runs embedded in the user-provided server framework, and any client applications use user-provided connectivity or allow the application server to handle all database interaction.

Figure 3-1 Cloudscape embedded in a single-user Java application

Figure 3-2 Cloudscape embedded in a multi-user Java application server

When a Cloudscape database is embedded in a Java application, the database is dedicated to that single application. If you deploy more than one copy of the

Application

Java Virtual Machine

JDBC API

Cloudscape Database

Cloudscape

User-providedconnectivity

Application

JDBC API

Cloudscape

Cloudscape Database

cape Developer’s Guide

Page 59: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deployment Issues 3-3

s its

hrough pe

the

ns

lows

application, each application has its own copy of the database and Cloudscape software. A server framework can work in multi-threaded, multi-connection mode and can even connect to more than one database at a time, just like single-user applications. However, only server framework at a time can operate against Cloudscape.

Figure 3-1 and Figure 3-2 look different, but from the point of view of the Cloudscape application (the one accessing Cloudscape), they are the same: the Cloudscape software is “embedded” in the application, and the application haown copy of the database.

The Cloudscape application accesses an embedded Cloudscape database tthe JDBC API. To connect, an application makes a call to the local CloudscaJDBC driver. Accessing the JDBC driver automatically starts the embedded Cloudscape software. The calling application is responsible for shutting downembedded Cloudscape database software.

Client/Server Deployment Application Overview

Cloudconnector is a JDBC and HTTP server framework. Cloudscape itself ruembedded in the continually running framework, Cloudconnector. Client applications connect to Cloudconnector over the network. Cloudconnector alCloudscape to act as a database server that provides data to multiple client applications.

Cloudscape Version 3.0

Page 60: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-4

Figure 3-3 Remote client applications connecting to Cloudscape running as a database server. Cloudconnector supports both HTTP and direct JDBC access.

Multiple client applications access Cloudconnector over the network. Cloudconnector returns data to multiple client applications.

Only Cloudconnector drivers are embedded in the deployed application, not Cloudscape.

Using Cloudconnector, multiple applications can access the same database concurrently. Only one Cloudconnector can access a particular Cloudscape database.

RmiJdbc is a customized version of freeware software that provides JDBC connectivity in a way similar to that described for Cloudconnector. It does not provide HTTP services or SSL.

Synchronization Application Overview

Distributed Cloudscape synchronization systems consist of one or more central source databases and multiple target databases (which can be multiple-user application servers or single-user applications).

Cloudscape Database

Java Virtual Machine

Java Virtual Machine

Cloudconnector

Application

Cloudscape

Application

JDBCAPI

Java Virtual Machine

CloudconnectorDriver

HTTP access

cape Developer’s Guide

Page 61: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deployment Issues 3-5

es,

Target databases act just like Cloudscape databases in the embedded mode. That is, they start up the embedded Cloudscape when running, access or insert and change data when needed, then shut down Cloudscape when the application shuts down. The only addition is that occasionally the databases themselves connect via HTTP to the source database for synchronization purposes.

Source databases can, but do not necessarily, run in the Cloudconnector framework. Running them in Cloudconnector makes it easier to have a continuously running source.

When the source databases run in the Cloudconnector framework, additional client/server-style applications can connect to Cloudconnector.

Figure 3-4 A Cloudscape synchronization system. The source database typically runs in a server framework such as Cloudconnector.

Choosing a Deployment Option

• If you want to deploy single-user applications with embedded databasbut you don’t want users to worry about network connections or any

source database

Application

target database

Application

target database

Application

target databaseCloudscape

HTTP

Cloudscape

Cloudscape Cloudscape

HTTP

HTTP

Application

JDBCAPI

CloudconnectorDriver

Cloudconnector

Cloudscape Version 3.0

Page 62: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-6

r or

s,

e r via

des

ct.

hin

les

those led

used

administrative overhead, choose the embedded database deployment option.

• If you want to provide all data services to remote clients and build youown framework, choose the embedded database deployment option fyour multi-user application server.

• If you need to share data between occasionally connected applicationchoose the synchronization deployment scenario.

• If you want more than one application to be able to connect to the samdatabase at the same time in a traditional client/server environment oservlets, choose the database server deployment option.

The deployment option you choose affects the connection and threading moavailable to your application. See “Deployment Options and Threading and Connection Modes” on page 6-28.

NOTE: You must purchase the appropriate deployment license for your produ

Deploying Java Classes for Use as Java Data Types

Cloudscape’s Java extensions allow you to use your application’s classes witCloudscape.

When used by the application, these classes constitute application-side logic. Application-side logic is application code executed by the application. Exampare:

• presentation logic such as GUI code

• JDBC calls to Cloudscape

When these same classes are used by Cloudscape, they constitute database-side logic and are called user-defined Java data types. Database-side logic is application code executed within the Cloudscape system in the context of anSQL-J statement or expression. Examples are:

• the class definition for stored objects

• database-side methods executed within SQL-J statements, including that make JDBC calls back to Cloudscape and synchronization-enabmethods known as work units

To summarize, Java data types are user-defined classes from your applicationby Cloudscape.

cape Developer’s Guide

Page 63: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deployment Issues 3-7

e the .

e

he sses lifies

ored

.

m the and

Java data types must be available to the JVM in which Cloudscape is running. This means that you must deploy those classes used by Cloudscape (and add them to class path) so that the Cloudscape software can use them.

Java Data Type Deployment, Embedded Environment

In the most basic scenario—an embedded environment—you do not have todeploy your classes separately. Since Cloudscape and your application sharsame JVM, they both access needed classes from the same user class path

Figure 3-5 In an embedded environment, both your application and Cloudscape run in the same JVM and load classes from thsame source.

In an embedded environment, it is also possible to store application logic in tdatabase. In this situation, both the application and Cloudscape can load clafrom the database, or Cloudscape only. Storing classes thus potentially simpsetting the class path for the user.

Synchronization users can upgrade application logic remotely by including stclasses in a publication.

For more information, see “Loading Classes from a Database” on page 3-17

Java Data Type Deployment, Client/Server Environment

In a client/server environment, you must deploy those classes needed by Cloudscape on the server. Cloudscape cannot access the classes directly frosame class path as the application, because it is running in a different JVM (

Application

Embedded System

Cloudscape

As soon as classes are needed byapplication OR Cloudscape, the JVMloads them from the class path.

Classes

Application and Cloudscape share the same JVM.Since application and Cloudscape use the same classes,they can pass objects back and forth.

Application-side logic is executed by application.Database-side logic is executed by Cloudscape.

Cloudscape Version 3.0

Page 64: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-8

lso rom a

ion ase.)

ct.

y

oad-

heir 3-9)

most likely on a different machine). Usually, it is easiest to deploy your entire application on the server, but not necessary. You only have to deploy those classes that are used within the context of SQL-J statements—Java data types. It is apossible to store Java data types within a database. (See “Loading Classes fDatabase” on page 3-17.) This can simplify administration.

Figure 3-6 In a client/server environment, both Cloudscape and the remote applications must have their own copies of applicatclasses. (Cloudscape can also load classes from the datab

Deployment Cheat Sheets

NOTE: You must purchase the appropriate deployment license for your produ

Deploying Cloudscape in an Embedded Environment

You can “embed” Cloudscape in any Java application (single- or multi-user) bdeploying the following package:

• the Cloudscape library (cloudscape.jar)

• the application’s libraries

You have the option of storing these libraries in the database. (See “Ling Classes from a Database” on page 3-17.)

• the database or databases used by the application, in the context of tsystem directory (see “Embedded Systems and Properties” on page

Server

JDBCServer

Application

JDBCNetwork

Driver

CloudscapeRemote Client

Client/server system

The JVM loads classesfrom the class path.

Classes

The JVM loads classesfrom the class path.

Classes

Application and Cloudscaperun in different JVMs.

Application-side logic is executed byremote client application.

Database-side logic isexecuted by Cloudscape.

Objects areserializedand sent orretrieved viaJDBC.

cape Developer’s Guide

Page 65: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deployment Issues 3-9

se-e and sier

ent. y the e lly ys-

-11.

ed for

Figure 3-7 Deploying an application, embedded Cloudscape software, and the database. Storing the application in the database and setting properties as database-wide properties simplify deployment.

Embedded Systems and Properties

• Are any system-wide properties being set that could be set as databawide properties? Database-wide properties are stored in the databasare simpler for deployment. System-wide parameters are probably eafor development.

• Are any properties being set in the cloudscape.properties file? Database-wide properties are stored in the database and are simpler for deploymSome properties can only be set on a system-wide bases. If so, deploentire system directory along with the properties file. Deploy only thosdatabases that you wish to include. Setting properties programmaticamay simplify this step—you won’t have to worry about deploying the stem directory/properties file.

Before deploying your application, read “Recommended Practice” on page 2

NOTE: Extra steps are required for deploying an application and an embedddatabase on read-only media. See “Creating Cloudscape Databases Read-Only Use” on page 3-12.

YourApplication.jar

YourDB

cloudscape.properties

cloudscape.jar

YourSystemDirectory

YourDB

cloudscape.jar

YourSystemDirectory

applicationand propertiesstored indatabase

Cloudscape Version 3.0

Page 66: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-10

tor

Deploying Client/Server Applications

On the server, you deploy:

• the Cloudscape jar file (cloudscape.jar)

• additional server framework classes

• Java data types

• the database

On the client, you deploy:

• the Cloudscape client jar file (client.jar)

• additional server framework client classes

• the application’s libraries

Figure 3-8 Deploying a client/server system when using Cloudconnec

For more information about client/server systems, see the Cloudscape Server and Administration Guide.

Deploying Cloudsync Systems

On the server, you deploy:

• The Cloudsync jar file (cloudsync.jar)

• additional server framework classes, if desired

• Java data types

• the source database

ServerRemote Client

YourJavaDataTypes

YourDB

cloudscape.properties

cloudscape.jar

YourSystemDirectory

YourApplication.jar

client.jar

Cloudconnector classesCloudconnector classes

cape Developer’s Guide

Page 67: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deployment Issues 3-11

oad-

Figure 3-9 Deploying a source database when using Cloudconnector

On the occasionally connected targets, you deploy:

• the Cloudsync jar file (cloudsync.jar)

• the application’s libraries

You have the option of storing these libraries in the database. (See “Ling Classes from a Database” on page 3-17.)

• a target database

Figure 3-10 Deploying an application, embedded Cloudscape target software, and a target database.

For more information about synchronization, see the Cloudscape Synchronization Guide.

ServerRemote Client

YourJavaDataTypes

YourDB

cloudscape.properties

cloudsync.jar

YourSystemDirectory

YourApplication.jar

client.jar

Cloudconnector classesCloudconnector classes

YourApplication.jar

YourDB

cloudscape.properties

cloudsync.jar

YourSystemDirectory

YourDB

cloudsync.jar

YourSystemDirectory

applicationand propertiesstored indatabase

Cloudscape Version 3.0

Page 68: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-12

-12

ge

-17

they

on

cape ape

nd dia.

Creating Cloudscape Databases for Read-Only UseYou can create Cloudscape databases for use on read-only media such as CD-ROMs. Cloudscape databases in zip or jar files are also read-only databases. Typically, read-only databases are deployed with an application in an embedded environment.

• “Creating and Preparing the Database for Read-Only Use” on page 3

• “Deploying the Database on the Read-Only Media” on page 3-13

• “Transferring Read-Only Databases to Archive (Jar or Zip) Files” on pa3-13

• “Accessing a Read-Only Database in a Zip/Jar” on page 3-14

• “Accessing Databases-in-a-Jar in the Class Path” on page 3-15

• “Read-Only Databases and Upgrading” on page 3-16

• “Databases on Read-Only Media and DatabaseMetaData” on page 3

Creating and Preparing the Database for Read-Only Use

To create databases for use on read-only media:

1 Create and populate the database on read-write media.

2 If the database contains stored prepared statements, make sure that are all valid and will not need recompilation.

You can recompile invalid statements with the following statement:

ALTER STATEMENT RECOMPILE INVALID

3 Commit all transactions and shut down Cloudscape in the prescribedmanner (see “Shutting Down Cloudscape or an Individual Database” page 2-22).

If you do not shut down Cloudscape in the prescribed manner, Cloudswill need to perform recovery the next time the system boots. Cloudsccannot perform recovery on read-only media.

4 Delete the tmp directory if one was created within your database direc-tory. If you include this directory, Cloudscape will attempt to delete it awill return errors when attempting to boot a database on read-only me

cape Developer’s Guide

Page 69: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Creating Cloudscape Databases for Read-Only Use 3-13

9.

an

. For 3-9.

ces-

eate

zip file read-in a er of

5 For the read-only database, set the property cloudscape.storage.tempDi-rectory to a writable location. Cloudscape needs to write to temporary files for large sorts required by such SQL-J statements as ORDER BY, UNION, DISTINCT, GROUP BY, and AGGREGATE. For more informa-tion about this property, see “cloudscape.storage.tempDirectory” on page5-66 in the Tuning Cloudscape. For example:

cloudscape.storage.tempDirectory=c:/temp/mytemp

Be sure to set this property such that it is deployed with the database. For more information, see “Embedded Systems and Properties” on page 3-

6 Configure the database to send error messages to a writable file or tooutput stream. For information, see the cloudscape.stream.xxx properties in Tuning Cloudscape.

cloudscape.stream.error.file=c:/temp/mylog.LOG

Be sure to set this property such that it is deployed with the databasemore information, see “Embedded Systems and Properties” on page

Deploying the Database on the Read-Only Media

1 Move the database directory to the read-only media, including the nesary subdirectory directories (log and seg0) and the file service.properties.

2 Use the database as usual, with the following exception:

You will not be able to insert or update any data in the database or cror drop dictionary objects.

Transferring Read-Only Databases to Archive (Jar or Zip) Files

Once a database has been created in Cloudscape, it can be stored in a jar orand continue to be accessed by Cloudscape in read-only mode. This allows aonly database to be distributed as a single file instead of as multiple files withdirectory and to be compressed. In fact, a jar or zip file can contain any numbCloudscape databases and can also contain other information not related to Cloudscape, such as application data or code.

You cannot store the cloudscape.properties file in a jar or zip file.

To create a jar or zip file containing one or more Cloudscape databases:

Cloudscape Version 3.0

Page 70: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-14

e

base

soft’s te

puts -

inal the

ases m-ding

ship di-

e.

1 Follow the instructions for creating a database for use on read-only media. See “Creating and Preparing the Database for Read-Only Use” on pag3-12.

2 From the directory that contains the database folder, archive the datadirectory and its contents. For example, for the database sales that lives in the system directory C:\london, issue the command from london. Do not issue the command from inside the database directory itself.

For example, archive the database folder and its contents using JavaJAR program from the JDK. You can use any zip or jar tool to generathe archive.

This command archives the database directory sales and its contents into acompressed jar file called dbs.jar.

cd C:\london

jar cMf C:\dbs.jar sales

You can add multiple databases with jar. For example, this command the sales databases and the boiledfood database (in the subdirectory products) into the archive.

cd C:\london

jar cMf C:\dbs.jar sales products\boiledfood

The relative paths of the database in the jar need not match their origrelative paths. You can do this by allowing your archive tool to changepath, or by moving the original databases before archiving them.

The archive can be compressed or uncompressed, or individual databcan be uncompressed or compressed if your archive tool allows it. Copressed databases take up a smaller amount of space on disk, depenon the data loaded, but are slower to access.

Once the database is archived into the jar or zip file, it has no relationto the original database. The original database can continue to be mofied if desired.

Accessing a Read-Only Database in a Zip/Jar

To access a database in a zip/jar, you specify jar in the subsubprotocol:

jdbc:cloudscape:jar:(pathToArchive)databasePathWithinArchive

The pathToArchive is the absolute path to the archive file. The databasePathWithinArchive is the relative path to the database within the archivFor example:

cape Developer’s Guide

Page 71: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Creating Cloudscape Databases for Read-Only Use 3-15

r or

-

g

jdbc:cloudscape:jar:(C:/dbs.jar)products/boiledfood

jdbc:cloudscape:jar:(C:/dbs.jar)sales

If you have trouble finding a database within an archive, check the contents of the archive using your archive tool. The databasePathWithinArchive must match the one in the archive. You may find that the path in the archive has a leading slash, and thus the URL would be:

jdbc:cloudscape:jar:(C:/dbs.jar)/products/boiledfood

Databases in a jar or zip file are always opened read-only and there is currently no support to allow updates of any type.

Databases in a jar or zip file are not booted automatically when Cloudscape is started, unless they are explicitly listed as cloudscape.service properties.

Accessing Databases-in-a-Jar in the Class Path

Once an archive containing one or more Cloudscape databases has been created it can be placed in the class path. This allows access to a database from within an application without the application’s knowing the path of the archive. When jazip files are part of the class path, you do not have to specify the jar subsubprotocol to connect to them.

To access a database in a zip or jar file in the class path:

1 Set the class path to include the jar or zip file before starting up Cloudscape:

CLASSPATH="C:\dbs.jar;%CLASSPATH%"

2 Connect to a database within the jar or zip file with one of the followindatabase connection URLs:

jdbc:cloudscape:/databasePathWithinArchive

(standard syntax)

jdbc:cloudscape:classpath:/databasePathWithinArchive

(syntax with subsubprotocol)

For example:

jdbc:cloudscape:/products/boiledfood

jdbc:cloudscape:classpath:/products/boiledfood

Cloudscape Version 3.0

Page 72: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-16

ch as ed

ith

When Path Is Ambiguous with Databases in File System

Use the basic database connection URL syntax only if the database path specified does not also point to a Cloudscape database in the file system. If this is the case, the connection attempt may fail or connect to the wrong database. Use the form of the syntax with the subsubprotocol to distinguish between the databases.

For example:

jdbc:cloudscape:classpath:/products/boiledfood

When Path Is Ambiguous Because of Databases in Class Path

To connect to a database in the file system when the database connection URL that you would use would be ambiguous with a database in the class path, use the following form of the database connection URL:

jdbc:cloudscape:directory:databasePathInFileSystem

For example,

jdbc:cloudscape:directory:/products/boiledfood

Apart from the database connection URL, databases in archives in the class path behave just like databases in archives accessed through the file system. However, databases in archives are read-only.

Read-Only Databases and Upgrading

Upgrading requires that databases be on read-write media. Both major and minor revisions of Cloudscape—such as those between version 2 and 3 and thosebetween 1 and 2—involve upgrading databases. Maintenance revisions—suthose between 1.5.1 and 1.5.2—also involve an upgrade step: Stored preparstatements are recompiled.

To upgrade, transfer the database to read-write media, connect with the newversion of Cloudscape, then retransfer to read-only media.

NOTE: To avoid upgrade problems, distribute the version of the Cloudscape software appropriate for the database on the read-only media along wthe application and the database.

cape Developer’s Guide

Page 73: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Loading Classes from a Database 3-17

e,

n the om the is

on

ase

ar

Databases on Read-Only Media and DatabaseMetaData

Databases on read-only media return true for DatabaseMetaData.isReadOnly.

Loading Classes from a DatabaseYou can store application logic in a database and then load classes from the database. Application logic, which can be used by both Cloudscape (for database-side methods and stored objects) and your application, includes Java class files and other resources. Storing application code simplifies application deployment, since it reduces the potential for problems with a user’s class path.

In an embedded environment, when application logic is stored in the databasboth the user application and Cloudscape can access classes loaded by the Cloudscape class loader from stored jar files.

NOTE: You can publish stored classes in a synchronized system. For more information about publishing stored classes, see the Cloudscape Synchronization Guide.

Class Loading Overview

You store application classes and resources by storing one or more jar files idatabase. Then your application can access classes loaded by Cloudscape frjar file and does not need to be coded in a particular way. The only differencethe way in which you invoke the application. Here are the basic steps:

1 “Create Jar Files for Your Application” on page 3-18

2 “Choose Between Database-Level and System-Level Class Loading”page 3-18

3 “Add the Jar File or Files to the Database” on page 3-19

4 “Enable Database Class Loading with a Property” on page 3-20

5 “Force Cloudscape Class Loading for the Application” on page 3-21

6 “Code Your Applications the Way You Normally Would” on page 3-25

NOTE: If you are interested in making changes to jar files stored in the databor changing the database jar “class path” of your application without having to re-boot, read “Dynamic Changes to Jar Files or Database JClass Path” on page 3-26.

Cloudscape Version 3.0

Page 74: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-18

ta-

from

y you

our a

y

r

Create Jar Files for Your Application

Include any Java classes in a jar file intended for Cloudscape class loading except:

• the standard Java packages (java.*, javax.*)

Cloudscape does not prevent you from storing such a jar file in the dabase, but these classes are never loaded from the jar file.

• those supplied with your Java environment (for example, sun.*)

A running Cloudscape system can load classes from any number of jar files any number of schemas and databases.

Create jar files intended for Cloudscape database class loading the same wacreate a jar file for inclusion in a user’s class path. For example:

jar cf tours.jar JBMSTours\*.class

Various IDEs have tools to generate a list of contents for a jar file based on yapplication. If your application requires classes from other jar files, you have choice:

• Extract the required third-party classes from its jar file and include onlthose in your jar file.Best if you need only a small subset of the classes in the third-party jar file.

• Store the third-party jar file in the database.Best if you need most or all of the classes in the third-party jar file, since your application and third-party logic can be upgraded separately.

• Deploy the third-party jar file in the user’s class path.Best if the classes are often already installed on a user’s machine (foexample, Objectspace’s JGL classes).

Include the class files and resources needed for your application.

Choose Between Database-Level and System-Level Class Loading

• Database-level class loadingYou can store jar files in a single database and make those jar files avail-able to that database only. This is the recommended practice, as it allows publication of jar files in synchronized systems and makes it possible to make changes to jar files or to change the database jar “class path” dynamically (without having to reboot).

cape Developer’s Guide

Page 75: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Loading Classes from a Database 3-19

e

ase,

al ntire

d

the f it is as

• System-level class loadingYou can also store jar files in any database or databases in the system and make those jar files available to all databases in the system. This usage is not possible when user authentication is turned on, because the system does not provide a user name and password when loading the class from the database where the jar file is stored.

Note that it is possible to have system class loading in general but data-base class loading in a particular database.

With system-level class loading, if you make changes to jar files or change the database jar “class path”, you will have to reboot to see theffects of those changes.

Add the Jar File or Files to the Database

Use the COM.cloudscape.tools.dbclasses utility (aliased as dbclasses) to add, update, and remove jar files in a database. When you add a jar file to a databyou give it a Cloudscape jar name, which is an SQL92Identifier.

See the Cloudscape Tools and Utilities Guide for reference information about theutility.

NOTE: Once a jar file has been stored, you cannot modify any of the individuclasses or resources within the jar file. Instead, you must replace the ejar file.

NOTE: Adding, removing, or replacing a jar file invalidates all stored preparestatements in the database.

You can use the utility on the command line or within an SQL-J statement. Oncommand line, you delimit the Cloudscape jar name with the schema name inot the default (APP). Within an SQL-J statement, you supply the schema namea parameter to the method separately.

Examples

See the Cloudscape Tools and Utilities Guide for reference information about theutility and complete syntax.

Cloudscape Version 3.0

Page 76: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-20

Adding Jar Files

-- SQL-J statement

CALL dbclasses.addJar(

’APP’, ’ToursLogic’, ’tours.jar’)

-- SQL-J statement

-- using a quoted identifier for the Cloudscape jar name

CALL dbclasses.addJar(

’APP’, ’"ToursLogic!"’, ’tours.jar’)

-- from the command line

java COM.cloudscape.tools.dbclasses add jdbc:cloudscape:toursDB

APP.ToursLogic tours.jar

-- SQL-J statement

-- using a quoted identifier for the Cloudscape jar name

-- on the command line you need to escape double quotes

java COM.cloudscape.tools.dbclasses add jdbc:cloudscape:toursDB

APP.\"ToursLogic!\" tours.jar

Removing Jar Files

-- SQL-J statement

CALL dbclasses.removeJar(

’APP’, ’ToursLogic’)

-- from the command line

java COM.cloudscape.tools.dbclasses remove

jdbc:cloudscape:toursDB APP.ToursLogic

Replacing Jar Files

-- SQL-J statement

CALL dbclasses.replaceJar(

’APP’, ’ToursLogic’, ’c:\myjarfiles\newtours.jar’)

-- from the command line

java COM.cloudscape.tools.dbclasses replace

jdbc:cloudscape:toursDB APP.ToursLogic

c:\myjarfiles\newtours.jar

Enable Database Class Loading with a Property

Once you have added one or more jar files to a database, you must set the database jar “class path” by including the jar file or files in the

cape Developer’s Guide

Page 77: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Loading Classes from a Database 3-21

er’s

ith the

n s loader

cloudscape.database.classpath property to enable Cloudscape to load classes from the jar files. This property, which behaves like a class path, specifies the jar files to be searched for classes and resources and the order in which they are searched. If Cloudscape does not find a needed class stored in the database, it can retrieve the class from the user’s class path. (Cloudscape first looks in the usclass path before looking in the database.)

Separate jar files with a colon (:).

• Database-level class loadingUse two-part names for the jar files (schema name and jar name). Set the property as a database-level property for the database. The first time you set the property, you must reboot to load the classes.

Example:

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.classpath’,

’APP.ToursLogic:APP.ACCOUNTINGLOGIC’)

• System-level class loadingUse three-part names for the jar files (database name, schema name, and jar name). Set the property as a system property.

Example: One jar file is in the photodb database with the Cloudscape name photo, the other in the general database with the Cloudscape name jgl.

cloudscape.database.classpath=photodb.APP.photo:general.APP.jgl

See “cloudscape.database.classpath” on page 5-17 in Tuning Cloudscape for more information about the property.

NOTE: Cloudscape’s class loader looks first in the user’s class path for any needed classes, and then in the database. To ensure class loading wdatabase class loader, remove classes from the class path.

Force Cloudscape Class Loading for the Application

Typically, in an embedded environment, you want both Cloudscape and the application to use classes loaded by the same class loader. However, you cachoose to have only Cloudscape use classes loaded by the Cloudscape clasloader, and have your application use those classes loaded by the JVM class from the class path.

Cloudscape Version 3.0

Page 78: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-22

only, de

ica-

ame

ke ee

t s.

he n, the

To choose this option, you must understand the implications of using different class loaders for each. Remember Figure 3-5 on page 3-7? It showed how both Cloudscape and the application use the same classes (those loaded by the JVM from the class path). Because they use the same classes, they can pass entire objects back and forth. When they use different class loaders, they use different classes, and therefore cannot pass entire objects back and forth.

Class Loading: Database-Side Only vs. Database- and Application-Side

You can do one of the following things:

• enable Cloudscape class loading for database-side execution of codeusing standard JVM class loading for application-side execution of cofrom the user’s class path

This situation prevents the application and Cloudscape from passing entire objects back and forth; see “Class Path Class Loading for Appltion-Side Logic Execution” on page 3-22.

In some stages of development, you may want this option.

NOTE: You can choose this option in a client/server scenario; however, the slimitations apply as in an embedded environment (described above).

• enable Cloudscape class loading for database-side execution of codeand for application-side execution of code

This situation avoids any version mismatch, but requires that you invoyour application in a special way to force Cloudscape class loading (s“Force Cloudscape Class Loading for the Application” on page 3-21).

NOTE: You cannot choose this option in a client/server scenario.

Enabling Cloudscape Class Loading for Database-Side Logic Execution

Enabling Cloudscape loading for execution of database-side logic means thaCloudscape uses classes loaded by Cloudscape retrieved from stored jar file

You automatically enable class loading for database-side logic execution by setting the cloudscape.database.classpath property (see “Enable Database ClassLoading with a Property” on page 3-20).

Class Path Class Loading for Application-Side Logic Execution

Cloudscape does not automatically load classes from the database for use by tapplication. When Cloudscape does not load classes for use by the applicatio

cape Developer’s Guide

Page 79: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Loading Classes from a Database 3-23

not

y class,

e-

not does

jects

-

but the

client application uses classes loaded by the JVM from the user’s class path,those loaded by the Cloudscape class loader. This leads to potential ClassCastExceptions. If two different class loaders (in this case, the one used bCloudscape and the one used by the class path class loader) load the same the JVM does not recognize them as the same class and will throw a ClassCastException if the application and Cloudscape attempt to pass entire objects back and forth.

Figure 3-11 Application-side logic loaded from the class path, databasside logic loaded from the database. If the application retrieves objects from Cloudscape or stores objects in thedatabase, a ClassCastException results.

Allowing two different class loaders is acceptable when the application does retrieve entire objects from, or store entire objects in, the database. That is, itnot use the setObject and getObject methods of JDBC to send or retrieve user-defined Java data types from the database. The application can work with obin a Cloudscape database only as follows:

• It does not retrieve entire objects using getObject, but only executes meth-ods that returned standard data types.

• it does not use setObject to store objects but instead uses the NEW constructor within a SQL-J statement to store objects. (It can use getObject and setObject to store and retrieve standard java.* objects.)

The following is an excerpt from an application that will generate a ClassCastException if embedded Cloudscape uses Cloudscape class loading the application uses class path class loading, even if the copy of the class in class path is identical to the one stored in the database:

ResultSet rs = s.executeQuery(

Application

The application and Cloudscape use different classes;they cannot share entire objects.

Cloudscape

The JVM loads classes from the class path whenthe application needs them.

Classes

Classes are loaded fromthe database for Cloudscape.

Cloudscape Version 3.0

Page 80: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-24

"SELECT City FROM Cities WHERE city_id = 1");

while (rs.next()) {

mycity = (JBMSTours.City) rs.getObject(1);

}

In a client/server environment, no error is generated if both the application and Cloudscape are using the same versions of the classes, because the object is serialized and re-created at the client with the application class.

Cloudscape Class Loading for Client-Side Logic Execution

In situations in which class path loading for client-side logic execution is not appropriate, enable Cloudscape class loading for the client application. Doing so ensures that all classes are loaded by the same class loader.

Figure 3-12 Both the application and Cloudscape loading classes from the database

Cloudscape provides an application bootstrap program that forces Cloudscape class loading for application-side logic. The program is called COM.cloudscape.util.DBClassLoad.

Typically, you would invoke your class like this:

java COM.cloudscape.util.DBClassLoad databaseConnectionURL

yourclassname classarguments

databaseConnectionURL refers to the database in which the classes are stored.

In cases when user authentication is turned on and you are using database-level class loading, you will probably not want to put the user name and password on

Application

When database class loading is enabled forCloudscape, Cloudscape loads classes from the database. These classes are then available for use bythe application, too. The application and Cloudscapecan share entire objects.

Cloudscape

Use the bootstrap method ofbooting the application to ensurethat the application uses databaseclass loading, too.

Classes are loaded from database

cape Developer’s Guide

Page 81: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Loading Classes from a Database 3-25

pass-

L. L, ation

ould:

he

re or

cape ven

the command line in the database connection URL. In that case, you can invoke the class like this:

• Create a “wrapper” class. Don’t store this one in the database.

• In that wrapper class, ask the user to input his or her user name and word.

• At this point, you have two choices. Do one of the following:

- Attach the user name and password to the database connection URCreate a String array (args) that contains the database connection URthe class name, and any arguments to your class. Invoke the appliclike this:

COM.cloudscape.util.DBClassLoad.main(args);

- Get a connection to the database first (theConnection), passing in the user name and password. Create a String array (args) for any arguments to your class, then invoke the application like this:

COM.cloudscape.util.DBClassLoad.invokeMain(theConnection,

"yourclassname", args);

For more information, see the javadoc for COM.cloudscape.util.DBClassLoad.

Code Your Applications the Way You Normally Would

In your applications, you cause classes to be loaded the way you normally w

• indirectly referencing them in the code

• directly using java.lang.Class.forName

In your applications, you load resources the way you normally would, using tstandard java.lang.Class.getResourceAsStream, a mechanism that allows an application to access resources defined in the class path without knowing whehow they are stored.

You do not need to make any changes to the way code interacts with Cloudsand its JDBC driver. An application can safely attempt to boot Cloudscape, ethough it is already running, without any errors. Applications connect to Cloudscape in the usual manner.

NOTE: The method getResource is not supported.

Cloudscape Version 3.0

Page 82: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Deploying Cloudscape Applications

Clouds

3-26

s

, not

.

nged.

ss

Dynamic Changes to Jar Files or Database Jar Class Path

In some situations, you can see changes to a class dynamically. That is, when you add or replace a jar file within an SQL-J statement or change the database jar “class path” (the cloudscape.database.classpath property), Cloudscape is able to load the new classes right away without your having to reboot.

Requirements

Certain conditions must be met for this to be true:

• You are using database-level class loading for jar files (see “Choose Between Database-Level and System-Level Class Loading” on page 3-18).

• You originally configured database-level class loading for the databasecorrectly. Turning on the database-level class loading property requiresetting the cloudscape.database.classpath property with valid two-part names, then rebooting.

• If changes to the cloudscape.database.classpath property are needed to reflect new jar files, you change the property to a valid value.

• You add or replace the appropriate jar files within an SQL-J statementon the command line.

If these requirements are not met, you will have to reboot to see the changes

Notes

When you are changing the cloudscape.database.classpath property, all classes loaded from database jar files are reloaded, even for a jar file that hasn’t cha

Remember that the user’s class path is searched first.

Any existing prepared statements will use the previously loaded classes unlethey require class loading, in which case they will fail with a ClassNotFound error.

Cached objects do not match objects created with newly loaded classes. Forexample, an in-memory Customer object will not match a new Customer object if the Customer class has been reloaded, and it will raise a ClassCastException. The issues are the same as those discussed in “Class Path Class Loading for Application-Side Logic Execution” on page 3-22.

cape Developer’s Guide

Page 83: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

nd

and

-17

on

e can his

4 Using Cloudscape’s Java Extensions

You can use Cloudscape as a purely SQL-92 RDBMS. This chapter introduces you to the way to use the Java extensions in Cloudscape’s SQL-J language aJDBC.

This chapter will make the most sense to you if you already know some SQLJava (including JDBC). It includes the following sections:

• “Java and SQL-J Integration” on page 4-1

• “Referring to Classes Within SQL-J” on page 4-2

• “Storing Java Objects in Cloudscape Tables” on page 4-3

• “Retrieving and Updating Objects” on page 4-5

• “Invoking Methods and Accessing Fields” on page 4-8

• “Other Java-Smart Syntax in SQL-J” on page 4-14

• “Invoking Database-Side JDBC Methods” on page 4-13

• “Using Methods to Emulate SQL-92 Functions” on page 4-15

• “SQL-J and Java Type Correspondence” on page 4-15

• “Using the Cloudscape Types to Query the System Tables” on page 4

• “Getting External Data: Using the Cloudscape Virtual Table Interface” page 4-19

Java and SQL-J IntegrationSQL-J gives you the ability to work with Java classes and objects. Cloudscapaccess all Java classes that are available to the JVM in which it is running. T

4-1

Page 84: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-2

orms on

use use ing

oes

s for ing

nd in va or

of lling

do

di-e:

tic

means that you can execute Java methods within Cloudscape (see “Invoking Methods and Accessing Fields” on page 4-8). You can also store serialized fof objects in the database (see “Storing Java Objects in Cloudscape Tables” page 4-3).

Java extensions to the syntax are integrated with the SQL. You don’t have tostandard SQL syntax in one place, then switch into another environment andJava. Instead, the boundaries between them are relaxed. Consider the followsimple SQL-J statement:

SELECT country.toUpperCase()

FROM Countries

In this example, country is a standard SQL-92 VARCHAR column, but toUpperCase is a method that belongs to the java.lang.String class. Cloudscape lets you execute Java methods on SQL data types. The rest of this section ginto more detail on the Java part of SQL-J. For complete details of the SQL-Jlanguage, see the Cloudscape Reference Manual.

NOTE: To use user-defined data types, known as Java data types, the classethose types must be available to the JVM in which Cloudscape is runn(installed and in the class path or stored in a jar file in the database athe database class path). See “Deploying Java Classes for Use as JaData Types” on page 3-6. The classes for basic JDK data types and fCloudscape-supplied data types are always available.

Referring to Classes Within SQL-JThe SQL-J language allows you to refer to Java classes as well as instancesthose classes. For example, you may need to refer to the class itself when castatic methods, defining a column data type, or instantiating a class. You canthis in one of two ways:

• You refer to the Java class with its full package and class name (in adtion, sometimes you must also use the CLASS keyword). For exampl

VALUES NEW java.lang.String(’hello, world!’)

You must use the CLASS keyword when casting and when calling stamethods, as in the following example:

CAST

(? AS CLASS JBMSTours.serializabletypes.Tour)

cape Developer’s Guide

Page 85: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Storing Java Objects in Cloudscape Tables 4-3

to the

he

face. To ust

e 5-8.

tor-

dat-

(see

ate-

or ber,

• You create a class alias for the Java class name, and then refer only alias (you will not ever need to use the CLASS keyword).

Cloudscape provides built-in class aliases for Cloudscape classes.

For example:

CREATE CLASS ALIAS String FOR java.lang.String

VALUES NEW String(’hello, world!’)

NEW: The ability to create a class alias is new in Version 3.0. For more information, see “CREATE CLASS ALIAS statement” on page 1-39 in tCloudscape Reference Manual.

Storing Java Objects in Cloudscape TablesCloudscape allows you to define a column as a serialization of a class or interSerialization is a Java mechanism for reading and writing objects to a stream.store serialized instances of a class or interface in the database, the class mmeet the requirements for serialization. For information about creating serializable Java data types, see “Programming Serializable Classes” on pag

Once a column is defined to hold serialized instances of a class (or serializedinstances of a subclass or class that implements the interface), you can:

• store instances in that column with SQL-J INSERT statements (see “Sing Objects in the Column” on page 4-4)

• retrieve the objects with SELECT statements (see “Retrieving and Uping Objects” on page 4-5)

• update or delete stored objects with UPDATE or DELETE statements “Retrieving and Updating Objects” on page 4-5)

• execute methods and access fields of stored objects with SELECT stments (see “Invoking Methods and Accessing Fields” on page 4-8)

Defining a Column to Store a Java Data Type

When defining any column in a table, you assign it a name and a data type. Fexample, to define a column in which you want to store a city’s integer id numyou need to give it a name and an SQL data type:

city_id INT

Cloudscape Version 3.0

Page 86: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-4

ass or d to at

mic n

s, you

For Java data types, you must use the keyword SERIALIZE along with the class or interface name (or class alias) to specify the serialized Java class as the data type:

columnName SERIALIZE( { JavaClassName | ClassAlias })

The Java class must meet the requirements for serialization (see “Requirements for Serialization” on page 5-9).

For example, to store the Java class JBMSTours.serializabletypes.City (aliased as City) in a table along with its SQL-92 INT id, you would define the table as follows:

CREATE TABLE Cities (city_id INT,

city SERIALIZE(City))

Storing Objects in the Column

Once the table is defined, you can store any object that is an instance of a cla sub-class of the class named in the column definition. If the column is defineserialize an interface, you can store an object that is an instance of a class thimplements the interface.

From a Java application, you typically insert a row of object values using dynaparameters and then pass in the in-memory objects. For example, to insert ainstance of the Java class City assigned to the variable name theCity in your application, use JDBC methods as shown in the following example:

insert = conn.prepareStatement(

"INSERT INTO Cities (city_id, City) VALUES(?, ?)");

insert.setInt (1, 1);

insert.setObject (2, theCity);

insert.executeUpdate();

Cloudscape Database Design Considerations

Because you have the ability to store data as objects or as SQL-92 data typemust answer some basic design questions for a Cloudscape database:

• What data do you want to store as standard SQL data types?

• What data do you want to store as Java objects?

Here are a few guidelines:

cape Developer’s Guide

Page 87: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Retrieving and Updating Objects 4-5

ts.

. Stor-

ch as

sons tore

ces

egra-r-

e., d

tions

cape You and

• Store well-defined Java objects you are already working with as objec

• Store complex data as objects.

• If an object is not complex—i.e., if its only methods are simple set and get methods that access basic fields—store such data as SQL data typesing simple data as objects has some disadvantages:

- Even if only a single field is updated in an object, Cloudscape mustwrite out the entire object.

- You may lose some database consistency features of the DBMS suforeign keys.

Even if you decide to store an object as an object, for performance reayou might want to store some information separately in columns that sbuilt-in types so that you can index them.

Another design question to answer is:

• Is it better to store complex objects in the database or to store referento external files?

The advantages of storing the actual objects in the database are:

• You gain transactional control of your objects.

• You can use SQL-J to access the objects, which is a more natural inttion. If you store objects as external files, you must manage them youself.

• You can use a program in either the embedded or the server mode (i.you don’t have to worry about installing the external files in a deployeapplication).

In addition to these points, the standard relational database design consideraapply for designing a Cloudscape database.

Retrieving and Updating ObjectsSerialization has some implications for an object. Objects stored in a Cloudsdatabase do not reside in your application’s memory until you retrieve them. can alter objects stored in a database only by retrieving them, altering them, then storing the complete objects again. This section includes the following topics:

• “Retrieving Objects” on page 4-6

Cloudscape Version 3.0

Page 88: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-6

ct into elects on, g cute e.

s

n

• “Updating Objects” on page 4-6

Retrieving Objects

Once an object is stored in a Cloudscape database, you can retrieve the objea Java application using JDBC methods to execute an SQL-J statement that sthe object. When assigning the retrieved object to a variable in your applicatiyou must cast the result as an instance of the particular class you are workinwith. Once you retrieve the object into your Java application, you can then exeits methods directly in the application, or alter it and then update the databas

The following example shows how you would retrieve an instance of the clasJBMSTours.serializabletypes.City from a table called City, where the column City is defined to serialize the class JBMSTours.serializabletypes.City:

ResultSet rs = stmt.executeQuery("SELECT city " +

"FROM Cities " +

"WHERE city_id = 1");

rs.next();

//here is the cast

mycity = (City) rs.getObject(1);

//close the result set

rs.close();

//You can work with the object in your application

mycity.getName());

Updating Objects

The following example shows how you can modify a retrieved object and theupdate it in the database:

// retrieve the object into memory

ResultSet rs = stmt.executeQuery(

"SELECT city

FROM Cities

WHERE city_id = 1");

/* Expecting only one row*/

rs.next();

mycity = (City) rs.getObject(1);

//close the result set

cape Developer’s Guide

Page 89: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Orderable Java Data Types 4-7

r

mn

rs.close();

// modify the object in memory

mycity.setTemperatures(38, 52, 69, 56);

// update the database with the new object

PreparedStatement ptstmt2 = conn.executeUpdate(

"UPDATE Cities SET City = ? WHERE city_id = ?");

ptstmt2.setObject(1, mycity);

ptstmt2.setInt(2, 1);

ptstmt2.executeUpdate();

ptstmt2.close();

It is also possible to include methods in the class that alter the object and then return the object itself. With such methods, you can update the object with a single SQL-J statement. In the following example, the method setPhoneAndReturnObject returns the (altered) object itself:

-- Adult is a class alias for JBMSTours.serializabletypes.Adult

-- without a class alias you would have to use the CLASS

--keyword

UPDATE PEOPLE

SET person = CAST (person AS

Adult).setPassportNumberReturnSelf(’ABCD’)

WHERE person_id = 2

Orderable Java Data TypesCloudscape allows you to create special Java data types that allow for ordering capabilities usually only allowed on built-in data types. For example, if a Java data type is orderable, you can:

• use it in MAX/MIN aggregate operations

• use it to order results such as in a DISTINCT, GROUP BY, UNION, oORDER BY operation

• Use the comparisons <, >, <=, >=

• Create indexes or primary, foreign key, or unique constraints on a coluthat contains the type.

The JBMSTours application contains one orderable Java data type, JBMSTours.serializabletypes.City. Here are some examples of what you can dowith this special class:

Cloudscape Version 3.0

Page 90: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-8

have any

e

d

base. cuted se

-- use in primary key constraints

CREATE TABLE Cities (city SERIALIZE(City) PRIMARY KEY)

-- comparisons

SELECT city

FROM Cities

WHERE city < (SELECT city FROM cities WHERE city_id = 35)

-- ordering

SELECT city FROM Cities

ORDER BY city

-- MAX

SELECT MAX(city) FROM Cities

For information on how to create these classes, see “Programming Orderable Classes” on page 5-41.

Invoking Methods and Accessing FieldsIn other situations, you do not need to retrieve the object; you simply want to Cloudscape execute one of its methods or access one of its fields and returnrelevant results to the application. This section covers the following topics:

• “Executing Methods” on page 4-8

• “Refining Search Conditions” on page 4-9

• “Accessing Methods When Storing Subclasses” on page 4-9

• “Invoking Methods on Classes Not Serialized in the Database” on pag4-10

• “Class Method Invocation and Class Field Access (Static Methods anFields)” on page 4-12

Executing Methods

If an object’s field or method is public, you can access it in a Cloudscape dataIn the above example you retrieved an object into an application and then exethe methods getName and getCity on it. You could have Cloudscape execute thomethods and then retrieve the results instead of the whole object, as in the following example:

String cityname;

cape Developer’s Guide

Page 91: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Invoking Methods and Accessing Fields 4-9

:

you

, in that

t of a

to a s of

PreparedStatement ptstmt = conn.prepareStatement(

"SELECT city.getName() FROM Cities " +

"WHERE city_id = ?");

ptstmt.setInt(1, 1);

ResultSet rs = ptstmt.executeQuery();

rs.next()

cityname = rs.getString(1);

System.out.println("name of city is" + city);

rs.close();

You can also access a public field of an object stored in the database. You do not use a dot to separate the field name from the object, however. Instead, you use a two-character combination, “->”. For example, to access the public field name of all the City objects stored in the database, use the following SQL-J statement

SELECT city->name FROM Cities

Whether you retrieve the object or just invoke methods depends on whether want to manipulate the object further. If you want to manipulate the object, retrieve the object into your program.

When you are storing subclasses, or when the column serializes an interfaceSQL-J you can access only fields and methods that are available in the classthe column serializes unless you cast it to the subclass using CAST. See “Accessing Methods When Storing Subclasses” on page 4-9.

Refining Search Conditions

Having the DBMS execute a method or access a field is especially useful forrefining queries. The results of a method invocation or field access can be parquery’s WHERE clause, as in the following example:

SELECT city FROM cities WHERE city.isTropical()

AND city.getLanguage() = ’English’

Accessing Methods When Storing Subclasses

When you define a column to serialize a Java class, Cloudscape allows you store instances of both the class and any of its subclasses. When you definecolumn to serialize a Java interface, Cloudscape allows you to store instanceclasses that implement the interface and subclasses thereof.

Cloudscape Version 3.0

Page 92: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-10

Basic method invocation within an SQL-J statement allows you to access only the methods of the class or interface that the column is defined to serialize. However, using the CAST operator, you can access methods defined only in the subclass. When using the CAST operator in this way, use the INSTANCEOF operator to test for class membership.

For example, JBMSTours.serializabletypes.Child and JBMSTours.serializabletypes.Adult are both subclasses of JBMSTours.serializabletypes.Person. If a column person serializes JBMSTours.serializabletypes.Person, you are allowed to store instances of JBMSTours.serializabletypes.Child and JBMSTours.serializabletypes.Adult in that column. However, JBMSTours.serializabletypes.Child contains one method that JBMSTours.serializabletypes.Adult does not, called getParent. You must use the CAST operator to invoke that method within an SQL-J statement. In order to avoid runtime errors, test for membership in the JBMSTours.serializabletypes.Child class before execution:

SELECT CAST (person AS CLASS

JBMSTours.serializabletypes.Child).getParent()

FROM People

WHERE person INSTANCEOF JBMSTours.serializabletypes.Child

Another example: if a column serializes java.io.Serializable, you can store instances of any class that implements Serializable in the column. However, you will not be able to access very many methods unless you CAST the column into the class you are working with:

SELECT CAST (serializable_column

AS CLASS java.lang.Float).longValue()

FROM mytable

WHERE serializable_column INSTANCEOF java.lang.Float

Invoking Methods on Classes Not Serialized in the Database

You can invoke public methods and access public fields of any Java class visible to your JVM, provided it is visible to the JVM in which Cloudscape is running. An instance of the class does not have to be stored in the database.

NOTE: The classes must be available to the JVM in which Cloudscape is running (installed and in the class path or stored in a jar file in the database and in the database class path). See “Deploying Java Classes for Use as Java

cape Developer’s Guide

Page 93: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Invoking Methods and Accessing Fields 4-11

or

.

hich sions

,

Data Types” on page 3-6. The classes for basic JDK data types and fCloudscape-supplied data types are always available.

Creating an Instance of a Class on the Fly Using Built-in Types

You can construct expressions that are instances of Java types within SQL-J

One way to do this is by constructing instances of the built-in SQL-J types, wcorrespond to Java classes. Within an SQL-J statement, you can use expressuch as:

• 1+3 (evaluates to an SQL-J INT)

• hotel_id (name of integer column, evaluates to an SQL-J INT)

• ’Santiago’ (evaluates to an SQL-J CHAR)

Each built-in SQL-J type has a corresponding Java type. An SQL-J INT’s corresponding Java type is java.lang.Integer; an SQL-J CHAR’s corresponding Java type is java.lang.String. (For more information about type correspondencesee “SQL-J and Java Type Correspondence” on page 4-15.)

This means that the above expressions are all instances of their respective Java types. 1+3 is an instance of java.lang.Integer; the hotel_id stored in any particular row is an instance of java.lang.Integer; ‘Santiago’ is an instance of java.lang.String. In an SQL-J statement, therefore, you can invoke all methods associated with these objects by using the same syntax that you would in a Java application, which you saw above.

For example, you can construct the following valid SQL-J statements that invoke non-static methods:

VALUES((1+3).toString())

VALUES(’Santiago’.toUpperCase())

SELECT hotel_id.toString() FROM Hotels

You can also invoke static methods associated with an instance of a Java class. For example, you can invoke any static method of the java.lang.Integer class on the expression 1+3:

VALUES((1+3).toString(35))

Cloudscape Version 3.0

Page 94: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-12

e

mic red

e of he

Class Method Invocation and Class Field Access (Static Methods and Fields)

Cloudscape provides syntax for invoking static methods and static fields that belong to Java classes, not instances of a Java class (objects).

When a class does not have a class alias, this syntax uses the keyword CLASS. When the class has an alias, simply use the class alias.

VALUES (CLASS JBMSTours.serializabletypes.City).findCity(

getCurrentConnection(),

’Santiago’, ’Chile’)

-- City is a class alias for JBMSTours.serializabletypes.City

VALUES City.findCity(getCurrentConnection(),

’Santiago’, ’Chile’)

VALUES (CLASS java.lang.Integer)->MAX_VALUE

This syntax requires that the method return a value. If the method does not return a value, use a CALL command:

CALL HotelStay.archiveRecords(CURRENT_DATE)

For more information about the CALL command, see the Cloudscape Reference Manual.

Method Invocation and Dynamic Parameters

You may want to invoke a method with dynamic instead of literal parameters, setting the values of the parameters inside the application for multiple execution.

This brings up a few problems: Cloudscape must be able to determine the data type of the dynamic parameter when it compiles the statement. Cloudscape doesn’t have any problem doing this in a standard SQL statement such as thfollowing:

SELECT * FROM MyTable WHERE anIntegerColumn = ?

In the above situation, Cloudscape determines that the data type of the dynaparameter must be the same as that of the column to which it is being compa(an INTEGER).

However, since Java methods can be overloaded, the data type of a dynamicparameter is often ambiguous. In a Java program, the JVM uses the data typthe parameter to determine which signature to call. Cloudscape cannot use t

cape Developer’s Guide

Page 95: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Invoking Methods and Accessing Fields 4-13

can not the as

lasses ay be

led page

data type of a dynamic parameter to determine which signature to call, and so cannot use the signature of the method to determine the data type of the dynamic parameter!

In most cases, you will need to CAST the data type of the dynamic parameter when it is used as a parameter to a method call, like this:

CALL (CLASS java.lang.Integer).toString(CAST (? AS INT))

Even though there is only one signature for the method toString() in the class java.lang.Integer, you still need to cast the data type of the dynamic parameter, because it is a primitive.

In other cases, if the number of parameters makes the method signature unambiguous and none of the data types is a primitive, you do not need to CAST.

Invoking Database-Side JDBC Methods

RDBMS users who first use Cloudscape may wonder where the stored procedures are. This section explains why you will not miss them. It includes the following topics:

In an RDBMS, you can write stored procedures in a proprietary SQL-based programming language. Stored procedures allow you to execute a piece of procedural programming in the DBMS. They are called stored procedures because they are stored in the database.

Because Cloudscape extends SQL with Java, you do not need to write separate stored procedures. As shown in the earlier sections in this chapter, you can simply execute or invoke a Java class’s methods within the DBMS as simply as you invoke a class’s methods within a Java application. Instances of the class do need to be stored in the database for you to execute one of its methods, but class must be available to Cloudscape (see “Deploying Java Classes for UseJava Data Types” on page 3-6).

NOTE: Java classes can be stored in and loaded from the database. When care stored in and loaded from the database, database-side methods msaid to be “stored in the database.” Such methods are sometimes calJava stored procedures. See “Loading Classes from a Database” on 3-17.

Methods invoked within an application are called application-side methods. Methods invoked within Cloudscape are called database-side methods.

Cloudscape Version 3.0

Page 96: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-14

se pe thods. e are

ase-

F, is

ts

An application-side method can be exactly the same as a database-side method. The only difference is where you invoke them. You write the method only once. Where you invoke the method—within the application or within an SQL-J statement—determines whether it is an “application-side” or a “database-sidemethod.

Methods invoked within an application that interact with a Cloudscape databaare called application-side JDBC methods; methods invoked within Cloudscathat interact with a Cloudscape database are called database-side JDBC meMethods in this last category most closely resemble stored procedures; thesmethods you call from an SQL-J statement that execute SQL-J statements themselves. Here are two examples of database-side JDBC methods:

CALL HotelStay.makeHistoryDatabase()

VALUES City.findCity(getCurrentConnection(), 35)

For more details on database-side JDBC methods, see “Programming DatabSide JDBC Methods” on page 5-1.

Other Java-Smart Syntax in SQL-JSQL-J syntax includes other elements borrowed from Java syntax to facilitateworking with Java objects and classes. It includes the keyword INSTANCEOwhich allows you to test whether an object belongs to a particular class. Thisuseful if you are storing objects that are members of a subclass in a column associated with a superclass data type.

SQL-J also includes the NEW keyword, which allows you to construct new objecwithin an SQL-J statement:

VALUES NEW java.lang.String(’hello, world!’)

SELECT NEW JBMSTours.Hotel(

hotel_id, hotel_name, city_id, tour_level,

normal_rate, high_season_rate,

number_rooms_in_block,

high_season_begin, high_season_end)

FROM Hotels

The conditional expression (?:) provides simple if-then control:

cape Developer’s Guide

Page 97: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Methods to Emulate SQL-92 Functions 4-15

ar as

o a

0-2.

a e

the ues rt

SELECT city.getName() IS NULL ? ’no name’

: city.getName()

FROM Cities

For more information on these commands, see their manual pages in the Cloudscape Reference Manual.

Using Methods to Emulate SQL-92 FunctionsSQL-92 specifies several built-in functions that can be executed within a DBMS. Typical functions are mathematical and string functions. Instead of retrieving raw data from the DBMS and doing all computing in the application, functions allow you to do some computing in the DBMS. For example, the SQL-92 text functions, such as SUBSTRING and LENGTH, perform some operations on VARCHAR columns within the DBMS.

Cloudscape includes most but not all of the SQL-92 functions. However, because it is integrated with Java, its real power is that it lets you invoke Java methods. You don’t need SQL-92 functions; you have Java. If a built-in function duplicates aJava method, use whichever is more convenient.

In addition, you can define an alias for any static Java method, making it appea native built-in function. You use the CREATE METHOD ALIAS statement. Alias definitions are specific to a database; to use an alias when connected tdatabase, you must already have defined the alias within that database.

For more information, see “Using java.lang Methods as Functions” on page 1

SQL-J and Java Type CorrespondenceBuilt-in types have corresponding Java data types at compile time. This correspondence is pertinent at compile time, when Cloudscape validates dattypes for inserts, joins, unions, and any statement in which two values must bcompared somehow. A PreparedStatement is compiled when it is prepared; a Statement is compiled when it is executed. Values associated with a column ofbuilt-in type automatically map, when an SQL-J statement is compiled, to valof the corresponding Java data type during compilation. For example, an inse

Cloudscape Version 3.0

Page 98: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-16

into a column of type INTEGER expects a value of an INTEGER data type. Because the INTEGER data type has a compile-time corresponding Java data type of java.lang.Integer, Cloudscape also accepts a value of java.lang.Integer at compile time.

-- the compiler determines that the data type of the

-- value to be inserted into myIntColumn matches

-- the expected type

INSERT INTO myTable (myIntColumn)

VALUES (NEW java.lang.Integer(’2’))

Since built-in types do not correspond to Java primitives at compile time, you cannot construct a Java primitive with a simple literal within the context of an SQL-J statement. For example, the literal 1 is an INTEGER value (which corresponds to a java.lang.Integer).

Because of the compile-time correspondences, you can insert a value of a built-in type into a column of its corresponding Java class, and vice versa.

In addition, SQL-J expressions that become method receivers (an expression to which the method is applied) and SQL-J expressions that are used as parameter values in a method are also mapped to Java types. In the following example, the expression (1+3) is the method receiver and 35 is a parameter. Both expressions, initially SQL-J INT types, are converted to java.lang.Integer when Cloudscape executes the method.

VALUES((1+3).toString(35))

In SQL-J statements, Cloudscape converts the return values of invoked Java methods and accessed fields of Java objects or classes to SQL-J values, except when the value is used as a receiver or parameter to another method. In that case, the value remains a Java value.

Although built-in SQL-J types map to Java classes, not Java primitives, many Java methods use primitive types as parameters or return values. For that reason, if on the first attempt to resolve a method Cloudscape does not find a match for the method with what it thinks is the given signature, Cloudscape converts all SQL-J numeric types and BOOLEANs to their corresponding Java primitive types. (This conversion is all-or-nothing.) Consider the following example:

VALUES NEW java.lang.Integer(1)

On the first attempt, Cloudscape looks for a method with a java.lang.Integer parameter (because that is the type that corresponds to the SQL-J INT expression 1) and fails. On the second attempt, Cloudscape looks for a method with an int parameter and succeeds.

cape Developer’s Guide

Page 99: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using the Cloudscape Types to Query the System Tables 4-17

nder meter, e of the

a good

out pe

ided

For details about conversion of SQL-J types to Java types, see “SQL-J and Java Type Correspondence” on page 1-243 in the Cloudscape Reference Manual.

Because of the way Cloudscape maps SQL-J types to Java object types, Cloudscape may not be able to find a method with the appropriate signature ucertain circumstances. When you use a dynamic parameter as a method parafor example, you may have to use an explicit CAST when invoking such Javamethods within Cloudscape. For more information, see “SQL-J and Java TypCorrespondence” on page 1-243 and “Dynamic Parameters” on page 1-226 Cloudscape Reference Manual.

Using the Cloudscape Types to Query the System TablesThe preferred mechanism for getting metadata information about a ResultSet or about the database is to use the JDBC MetaData classes and methods. (For discussion of using JDBC’s MetaData classes and methods, see JDBC Database Access with Java.)

However, you can also query the system tables directly to get information abtables, columns, indexes, and other dictionary objects. Chapter 4, “CloudscaSystem Tables”, in the Cloudscape Reference Manual details the contents and layout of the system tables.

Querying the system tables successfully requires using the Cloudscape-provJava types stored in the system tables. These types, which are part of the COM.cloudscape.types package, are:

• TypeDescriptor (COM.cloudscape.types.TypeDescriptor)

serialized in SYS.SYSCOLUMNS.COLUMNDATATYPE

• IndexDescriptor (COM.cloudscape.types.IndexDescriptor)

serialized in SYS.SYSCONGLOMERATES.DESCRIPTOR

• DependableFinder (COM.cloudscape.types.DependableFinder)

serialized in SYS.SYSDEPENDS.DEPENDENTFINDER and SYSDE-PENDS.PROVIDERFINDER

• ReferencedColumnDescriptor (COM.cloudscape.types.ReferencedCol-umnsDescriptor)

serialized in SYS.SYSCHECKS.REFERENCEDCOLUMNS

Cloudscape Version 3.0

Page 100: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-18

ion, ype of

• AliasInfo (COM.cloudscape.types.AliasInfo) serialized in SYS.SYSALIASES.ALIASINFO

• ErrorInfo ((COM.cloudscape.types.ErrorInfo) serialized in SYS.SYSER-RORS.ERRORINFO

• ReferencedColumnsDescriptor ((COM.cloudscape.types.ReferencedColumnsDescriptor) serialized in SYS.SYSTRIGGERS.REFERENCEDCOLUMNS

For an instructive example, look at the information provided by the column COLUMNDATATYPE in SYS.SYSCOLUMNS. Whereas another DBMS might have separate columns to store information about a data type’s length, precisnullability, and the like, Cloudscape stores all of that information in the Java tTypeDescriptor. Use methods to find out specific information. The API for eachthese types is included in the javadoc directory:

Examining the API, you see that COM.cloudscape.types.TypeDescriptor includes the following methods:

• getMaximumWidth

• getPrecision

• getScale

• getStorageType

• getTypeName

• isNullable

• getSQLstring

So, for example, to find out which columns in the table called Hotels are nullable, you could use the following query:

SELECT Columnname FROM SYS.Systables AS T,

SYS.Syscolumns AS C

WHERE T.Tableid = C.Referenceid AND T.Tablename = ’HOTELS’

AND C.ColumnDataType.isNullable()

COM.cloudscape.types.DependableFinder is less intuitive. The description of SYSDEPENDS provides example queries to help you get started using this type (see Chapter 4, “Cloudscape System Tables”, in the Cloudscape Reference Manual).

cape Developer’s Guide

Page 101: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Getting External Data: Using the Cloudscape Virtual Table Interface 4-19

To

or or open sing

a ing e

ta in

news age

Getting External Data: Using the Cloudscape Virtual Table InterfaceCloudscape comes with a powerful interface to external data. Called the Virtual Table Interface, or VTI, it provides a way for you to access data from some external data source within an SQL-J statement as if it were a real table.

To access the data, you first must create a Java class that fulfills the VTI requirements (see “Requirements and Options for VTI Classes” on page 5-17). summarize, the class must implement the java.sql.ResultSet interface. The idea is that when you construct a new instance of your class, given some parameterparameters, the instance of the class accesses some kind of external data. Fexample, it could call a routine to access another vendor’s database, it couldsome Web pages, or it could open some kind of proprietary files. After accesthe data, it instantiates the data in such a way as to make it look like a ResultSet, and it provides the appropriate ResultSetMetaData that tells Cloudscape what thedata looks like.

Within the SQL-J language, you do not need to declare a VTI or create it as database object. Instead, you construct a VTI on the fly in a FROM clause usthe NEW keyword, providing any parameters, and providing a correlation namfor the virtual table.

For example, the class COM.cloudscape.tools.FileImport is a class provided by Cloudscape for an import/export utility that fulfills the VTI requirements. (Cloudscape has also provided a built-in class alias for this class). Within an SQL-J statement, you use the NEW keyword to create a virtual table from daa flat file (from which you can SELECT).

INSERT INTO emptyTable

SELECT a, b,c

FROM NEW FileImport(’c:/export/dump.txt’)

AS tableFromFile (a, b, c)

You can write your own classes to access any kind of external data, such as feeds, data from other database vendors, etc. See “Programming VTIs” on p5-16 for more information.

Cloudscape Version 3.0

Page 102: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape’s Java Extensions

Clouds

4-20

cape Developer’s Guide

Page 103: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

2

2

age

5 Special Cloudscape Programming

This chapter discusses special programming for Cloudscape features such as database-side JDBC methods, serializable classes, VTIs, and more.

• “Programming Database-Side JDBC Methods” on page 5-1

• “Programming Serializable Classes” on page 5-8

• “Programming VTIs” on page 5-16

• “Programming User-Defined Aggregates” on page 5-27

• “Programming Trigger Actions” on page 5-30

• “Programming Orderable Classes” on page 5-41

Programming Database-Side JDBC Methods

• “Overview” on page 5-2

• “Database-Side JDBC Methods and Nested Connections” on page 5-

• “Requirements for Database-Side JDBC Methods Using Nested Connections” on page 5-3

• “Database-Side JDBC Methods and Nested Connections” on page 5-

• “Database-Side JDBC Methods Using Non-Nested Connections” on p5-6

• “Database-Side JDBC Methods and SQLExceptions” on page 5-6

• “User-Defined SQLExceptions” on page 5-8

5-1

Page 104: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-2

e are hat s. e are

ore th, on

a,

e as the

ith

tion as re-

tion:

Overview

Methods invoked within an application are called application-side methods. Methods invoked within Cloudscape are called database-side methods.

An application-side method can be exactly the same as a database-side method. The only difference is where you invoke them. You write the method only once. Where you invoke the method—within the application or within an SQL-J statement—determines whether it is an “application-side” or a “database-side” method.

Methods invoked within an application that interact with a Cloudscape databascalled application-side JDBC methods; methods invoked within Cloudscape tinteract with a Cloudscape database are called database-side JDBC methodMethods in this last category most closely resemble stored procedures; thesmethods you call from an SQL-J statement that execute SQL-J statements themselves.

NOTE: For tips on how to make your database-side methods look and feel mlike “stored procedures,” if those are what you are used to working wisee “Getting Methods to Look and Work More Like Stored Procedures”page 10-3.

NEW: Version 3.0 allows you to create triggers. Because of the power of Javyour triggers can be turbo-triggers; a trigger can be a simple SQL-J statement or any Java method call. For more info, see “ProgrammingTrigger Actions” on page 5-30.

Database-Side JDBC Methods and Nested Connections

Most database-side JDBC methods need to share the same transaction spacstatements that called them for the following reasons:

• to avoid blocking and deadlocks

• to ensure that any updates done from within the method are atomic wthe outer transaction

In order to use the same transaction, the method must use the same connecthe parent SQL-J statement in which the method was executed. Connectionsused in this way are called nested connections.

Cloudscape provides three mechanisms for a method to get a nested connec

cape Developer’s Guide

Page 105: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Database-Side JDBC Methods 5-3

in

ion.

le:

in

• getting a Connection object as a parameter using the GETCURRENTCONNECTION method (when you invoke this methodthe application, you simply pass in the Connection)

(the preferred mechanism)

• using the current=true attribute form of the URL to re-use the current Connection

• using the database connection URL jdbc:default:connection to re-use the current Connection

GETCURRENTCONNECTION Built-In Method

Some methods take a connection parameter. In an application, pass in the application’s Connection object so that the method can use the current connectWithin an SQL-J statement, call the built-in method GETCURRENTCONNECTION, which supplies the Connection object of the outer statement to the method being invoked within the statement. An examp

SELECT city

FROM Cities WHERE

city.isTropical() AND

city.getDistanceFrom( GETCURRENTCONNECTION(), 35) < 3000

For more information, see “GETCURRENTCONNECTION()” on page 1-242 the Cloudscape Reference Manual.

current=true attribute

A special URL allows a Java method to get the Connection of the SQL-J statementthat called it. The method would get a Connection like this:

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:;current=true");

For more information, see “current=true” on page 7-5 of the Cloudscape Reference Manual.

Requirements for Database-Side JDBC Methods Using Nested Connections

In order to preserve transactional atomicity, database-side JDBC methods that use nested connections must follow the rules listed in this section.

Cloudscape Version 3.0

Page 106: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-4

ou urns on e

alled

ts.

when

all.

• Must not issue a commit or rollback.

Enforced by an exception.

• Must not issue a commit or rollback implicitly, which happens when yare in auto-commit mode. In the current release, Cloudscape silently toff auto-commit to execute these methods (see “Using Auto-Commit”page 6-4). Changing the transaction isolation also implicitly commits thtransaction.

• Must not change connection attributes such as auto-commit.

Enforced by an exception.

• Must not modify the data in a table used by the parent statement that cthe method, using INSERT, DELETE, or UPDATE. For example, if a SELECT statement using table T calls method changeTables, changeTables cannot modify data in table T.

Not explicitly prohibited, but do not do this!

• Must not drop a table used by the statement that called the method.

Not explicitly prohibited, but do not do this!

• Must not be in a class whose static initializer executes DDL statemen

Enforced by an exception.

Nested Connections and Work Units

In a Cloudscape synchronization system, you must use a nested connectioncalling a work unit. Cloudscape recommends that you use the GETCURRENTCONNECTION built-in method as a parameter to the method cSee the Cloudscape Synchronization Guide for more information.

Example Method

/*This example queries the City table and returns a City object.

This method is a static method in the City class.*/

public static City findCity(Connection conn,

String acity,

String acountry) throws SQLException {

City mycity;

mycity = new City();

PreparedStatement ptstmt = conn.prepareStatement(

"SELECT city FROM Cities " +

"WHERE city.getName() = ? AND city.getDisplayCountry() = ?");

cape Developer’s Guide

Page 107: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Database-Side JDBC Methods 5-5

ptstmt.setString(1, acity);

ptstmt.setString(2, acountry);

ResultSet rs = ptstmt.executeQuery();

while (rs.next())

{

mycity = (City) rs.getObject(1);

}

//close the result set

ptstmt.close();

return mycity;

/* Do not commit the transaction or close the connection*/

}

Invoking the Example Method

In an application, invoke the method like this:

City.findCity(Conn, "Santiago", "Chile");

In an SQL-J statement, invoke the method like this:

VALUES (CLASS

JBMSTours.serializabletypes.City).findCity(GETCURRENTCONNECTION

(),

’Santiago’, ’Chile’)

Or, if there is a class alias for JBMSTours.serializabletypes.City, like this:

VALUES City.findCity(GETCURRENTCONNECTION(),

’Santiago’, ’Chile’)

Or, since the method belongs to a class that has instances of it stored in the database (in column called City), you can invoke the method off one of those instances:

SELECT City.findCity(GETCURRENTCONNECTION(), ’Santiago’,

’Chile’)

FROM Cities

WHERE city_id = 1

You would not use the CALL method syntax for this method, because the method returns a value.

Cloudscape Version 3.0

Page 108: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-6

Database-Side JDBC Methods Using Non-Nested Connections

A database-side JDBC method can create a new connection instead of using a nested connection. Statements executed in the method will be part of a different transaction, and so can issue commits and rollbacks.

Such methods can connect to a database different from the one to which the parent SQL-J statement that called it is connected. The method does not use the same transaction or Connection. It establishes a new Connection and transaction.

NOTE: If database-side JDBC methods do not use nested connections, this means that they are operating outside of the normal DBMS transaction control, so it is not good practice to use them indiscriminately.

Example Method Using New (not Nested) Connection

For an example of a method that uses new rather than nested connections, see the methods archiveRecords and archiveRecordsVTI in the class JBMSTours.serializabletypes.HotelStay in the sample application.

Invoking the Example Method Using the CALL Command

If a method does not return a value, you can have Cloudscape execute the method using the SQL-J CALL command. You can invoke the method in an SQL-J statement such as the following:

CALL HotelStay.archiveRecords(DATE’1998-02-08’)

NOTE: You could not roll back this statement, because commits happen within the method itself. Methods that use nested connections, on the other hand, are not permitted to commit or roll back and can therefore be rolled back after the calling statement.

You can also use the CALL command to execute a method that does return a value, but you will not be able to access the value.

Database-Side JDBC Methods and SQLExceptions

It is possible to code database-side methods, like application-side methods, to catch SQLExceptions. SQLExceptions that are caught within a database-side method are hidden from the calling application code. When such SQLExceptions are of

cape Developer’s Guide

Page 109: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Database-Side JDBC Methods 5-7

s

a gin a ts that ne

ork ding bad

aking , but

d other it is

d s:

transaction severity (such as deadlocks), this “hiding” of the exception causeunexpected problems.

This is because errors of transaction severity roll back work already done by transaction (not just the piece executed by the called method) and silently benew transaction. When the method execution is complete, Cloudscape detecthe outer statement was invalidated by a deadlock and rolls back any work do in the new transaction as well. This is the expected behavior, because all the statements in between explicit commits should be treated atomically; the newtransaction implicitly begun by Cloudscape’s rollback was not intended by theapplication designer.

However, this is not the same behavior that would happen if the method wereinvoked in the application. In that situation, Cloudscape would roll back the wdone by the transaction and silently begin a new transaction. Work in the newtransaction would not be rolled back when the method returned. However, cothe application in that way means that the transaction did not end where youexpected it to and is probably a programming mistake, and is most certainly programming practice.

A method that catches a deadlock exception and then continues is probably ma mistake. Errors of transaction severity should be caught not by nested codeonly by the outermost application code. That is the only way to ensure that transactions begin and end where you expect them to.

Not all database vendors handle nested deadlocks the same way. For this anreasons, it is not possible to write portable SQL-invoking methods. However,possible to write SQL-invoking methods that behave identically regardless of whether you invoke them application- or database-side.

In order to ensure identical application- and database-side handling of nesteerrors, code try-catch blocks to check for the severity of exceptions as follow

try {

preparedStatement.execute();

} catch (SQLException se ) {

checkJBMSSeverity(se);

// if the SQLException is not of transaction severity,

// okay to catch exception and continue

String SQLState = se.getSQLState();

if ( SQLState.equals( "23500" ) )

{ correctDuplicateKey(); }

else if ( SQLState.equals( "22003" ) ) {

correctArithmeticOverflow(); }

Cloudscape Version 3.0

Page 110: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-8

n the ” on

else { throw se; }

}

where checkJBMSSeverity is a static method in the Cloudscape-provided class COM.cloudscape.database.JBMSException.

public static void checkJBMSSeverity( SQLException se )

throws SQLException

{

if (se.getErrorCode() > JBMSExceptionSeverity.STATEMENT_SEVERITY )

{ throw se; }

}

Of course, users also have the choice of not wrapping SQL statements in try-catch blocks within methods. In that case, SQLExceptions are caught higher up in their applications, which is the desired behavior.

User-Defined SQLExceptions

When the execution of a database-side method raises an error, Cloudscape wraps that exception in an SQLException with an SQLState of 38000. You can avoid having Cloudscape wrap the exception if:

• the exception is an SQLException

• the range of the SQLState is 38001–38999

(This conforms to the SQL99 and the SQLJ standards.)

The most compelling example of when it would make sense to do that is whemethod is called from a trigger. See “Example of User-Defined SQLExceptionpage 5-38.

NEW: The ability to create user-defined SQLExceptions is new in Version 3.0.

Programming Serializable ClassesCloudscape can store objects that are serializable. This section discusses how to create serializable classes.

For an overview of JavaSoft’s serialization mechanisms, see http://java.sun.com/products/jdk/1.1/docs/guide/serialization/index.html.

This section covers the following topics:

cape Developer’s Guide

Page 111: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Serializable Classes 5-9

ion r

that at ct is

he

ic

• “Requirements for Serialization” on page 5-9

• “Serializable vs. Externalizable” on page 5-9

• “Marking Fields as Transient” on page 5-10

• “Modifying Classes (Java Versioning)” on page 5-11

• “Serializable Objects and Input/Output Streams” on page 5-16

Requirements for Serialization

When you define a column to hold a Java object, you declare that the columnserializes a particular class or interface.

Requirements for classes:

• implement the java.io.Serializable or the java.io.Externalizable interface (classes that implement Externalizable must also have a public no-argument constructor)

• exist at the time the column is created and accessed

• be a public class

Requirement for interfaces:

• extend the java.io.Serializable interface

The java.io.Externalizable interface extends java.io.Serializable, and so classes that extend either interface are actually “serializable.” When this documentatrefers to serializable classes (with a lowercase s), those classes can extend eitheSerializable or Externalizable.

Serializable vs. Externalizable

The choice between implementing java.io.Serializable and java.io.Externalizable depends on whether you want ease of use or optimized storage. For classesimplement java.io.Serializable, you do not have to write any methods to ensure ththe object is stored properly. Java automatically implements the way the objewritten to the output stream (and thus to the Cloudscape database). Define tcolumn and you are finished.

The java.io.Externalizable interface requires more work to implement; if you choose to implement Externalizable, you stop getting the benefits of the automatimplementation. You must correctly implement the writeExternal and readExternal

Cloudscape Version 3.0

Page 112: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-10

.

.

.

eeded he you

methods so that all the fields of the class and its superclasses are stored. In addition, the class must have a no-argument constructor.

However, the java.io.Serializable implementation requires a certain amount of storage overhead. For classes that implement the java.io.Serializable interface, for each instance of the class, Java writes out:

• class and superclass metadata

The class name of the class and superclass (and its superclass, etc.)

• the serialVersionUID

See “Using the serialVersionUID to Indicate Serializable Compatibilityon page 5-12.

• field metadata and data

The name and type of each field in the class and superclass (and its superclass, etc.) as well as the values of the fields.

If you are storing thousands of records, that is a lot of overhead.

Classes that implement java.io.Externalizable require less overhead when storedFor each instance of the class, Java writes out:

• class metadata

The class name of the class only (not superclasses)

• the serialVersionUID

• data (whatever the writeExternal method stores)

Java does not write out any superclass metadata or any field metadata at all

Marking Fields as Transient

In addition, when using either java.io.Serializable or java.io.Externalizable, you can design your classes for more compact storage by storing only the fields nto reconstruct a class. If you are using java.io.Serializable, you can mark a field astransient to indicate that the field does not need to be stored with the rest of tobject. The field is automatically omitted from the output and input streams. If are using java.io.Externalizable, you must write the writeExternal and readExternal methods to omit the writing and reading of the appropriate field. However, it is useful documentation practice to mark the field as transient.

For an example of a transient field, see the JBMSTours.serializabletypes.HotelStay class in the sample database included in the installation.

NOTE: Static fields are not serialized.

cape Developer’s Guide

Page 113: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Serializable Classes 5-11

rent eneral

mple, n that scape, ss or

an then

Modifying Classes (Java Versioning)

Developers often modify classes after applications have been deployed. When they make minor changes, they want to be able to continue to use the stored instances of the earlier versions of the classes. The serialization mechanisms track all changes to classes and check the compatibility of classes with stored objects. You must explicitly indicate that the class is still compatible when you make any changes to it. Otherwise, the serialization mechanism assumes that the class change is incompatible.

Of course, when the changes you make are major, you may not want to mix instances of the new class with instances of the old class within the database. In this case, you mark the class as a new version from the serialization perspective. You will not be able to access instances of the earlier version of the class. This means that any SQL-J statement that selects the older instances will fail.

Cloudscape does not recognize the new class definition until you restart Cloudscape.

The rest of this section assumes that the changes you make are minor and that you want to keep the new class compatible (from the viewpoint of serialization) with the old class. When you want to change a class definition when a column serializes that type, you must follow Java’s rules for modifying the class to keep the diffeversions of the class compatible. These rules, which are discussed under the gtopic of “versioning,” are documented at http://www.javasoft.com/products/jdk/1.1/docs/guide/serialization/spec/version.doc.html.

Compatible and Incompatible Changes

Some changes to a class are considered compatible changes, which means that these changes do not affect the interoperability of the class versions. For exaadding a new method to a class is a compatible change. If you have a columstores objects of that class, and then you redefine the class and restart Cloudyou will not have any problems storing instances of the new version of the claretrieving instances of the old version of the class.

Some changes, however, are incompatible. Incompatible changes void the interoperability of class versions. For example, deleting a field from a class isincompatible change. Deleting a field from a class, restarting Cloudscape, andtrying to access instances of that class from the database raises a java.io.InvalidClassException. (Because the JDBC interface raises only SQLExceptions, you cannot “catch” this exception. The error is wrapped in an SQLException.) See the Java documentation at http://www.javasoft.com/products/

Cloudscape Version 3.0

Page 114: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-12

ion

ise,

jdk/1.1/docs/guide/serialization/spec/version.doc.html for a complete list of compatible and incompatible changes.

Using the serialVersionUID to Indicate Serializable Compatibility

When you alter a class definition by making a compatible change, you still must identify the class as being compatible with the original version of the class. Java implicitly identifies each unique class with what is called a serialVersionUID, an automatically generated ID, which is stored when objects are serialized. When you modify a class, you can explicitly include the original class’s automatically generated serialVersionUID in the altered class definition. You use Java’s serialver program to find out a serializable class’s serialVersionUID.

NOTE: The Java documents (http://www.javasoft.com/products/jdk/1.1/docs/guide/serialization/spec/class.doc.html) state that you can explicitly declare this serialVersionUID in the original class definition but that it is not required. Cloudscape recommends that you identify a class’s versin the original class definition.

You must use the words “static final long” when declaring the variable; otherwthe serialization mechanisms do not use the value.

Versioning Mini Tutorial

This section is an example of the way using serialVersionUID helps you keep classes compatible.

You define a very simple user class, called UserClass, which does not explicitly define the serialVersionUID.

import java.io.Serializable;

/**

* This is a sample user class for showing versioning problems.

*/

public class UserClass implements Serializable {

public int my_id;

public String name;

public UserClass () {

my_id = 1;

name = "SFO";

}

public int getId() {

cape Developer’s Guide

Page 115: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Serializable Classes 5-13

return my_id;

}

public String getName() {

return name;

}

}

You define a table that serializes the class and store some values in it:

CREATE TABLE myTable (the_id INTEGER, the_class

SERIALIZE(UserClass))

INSERT INTO myTable VALUES (1, new UserClass())

You then shut down Cloudscape and alter the class with a compatible change. However, you neglect to add the serialVersionUID.

import java.io.Serializable;

/**

* This is a sample user class for showing versioning problems.

*/

public class UserClass implements Serializable {

public int my_id;

public String name;

/*Here is the first change*/

public int second_id;

public UserClass () {

my_id = 1;

name = "SFO";

/*Here is the second change*/

second_id = 2;*/

}

}

public int getId() {

return my_id;

}

public String getName() {

return name;

}

/*Here is the third change*/

public String getAString () {

return getId() + " " + getName() + second_id;

}

Cloudscape Version 3.0

Page 116: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-14

lass

m.

terms the ant to hod One

e

}

When you restart Cloudscape, Cloudscape allows you to insert new rows into the table without complaint. However, when you try to retrieve rows from the table, you get a java.io.InvalidClassException (wrapped in an SQLException), even though the changes are compatible:

ERROR XJ001: Java exception: ’UserClass; Local class not

compatible: java.io.InvalidClassException’.

Java does not recognize the class as compatible because the automatically generated serialVersionUID in the new version does not match the automatically generated one in the first version.

However, the scenario would be different if you had added the serialVersionUID of the original class (which you can find out by running serialver -show from the command line).

static final long serialVersionUID = -1600135205756904045L;

In this scenario, you can access data from both versions of the class. You can even execute the new method on the objects that belong to the older version.

SELECT the_class.getAString() FROM mytable

The query returns “0” for rows that contain objects from the first version of the c(which did not contain this field).

However, you may still raise java.io.InvalidClassExceptions. Explicitly including the serialVersionUID in the original class definition helps you avoid that proble

Other Kinds of Versioning

Finally, you may want to implement your own “versioning” of a class for otherreasons. That is, you make a significant change but one that is compatible in of serialization to the class, but you still want to be able to store instances of new class alongside instances of the old class in the same table. You do not wlose your old data. However, the change is significant enough that some metinvocation or field access will give odd results if executed on the old members.way to handle this is to include an identifier such as currentClassId along with a getCurrentClassId method. The method allows you to specify versions when retrieving records from the database.

The following example shows a new class. The changes to this class from thprevious version (which is not shown) are:

• The currentClassVersion has been incremented.

cape Developer’s Guide

Page 117: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Serializable Classes 5-15

T

• The field third_id has been added.

import java.io.Serializable;

/**

* This is a sample user class showing how you might implement

class-specific, non-serializable versioning.

*/

public class UserClass implements Serializable {

public int my_id;

public String name;

public int second_id;

/* new field */

public int third_id;

static final long serialVersionUID = -1600135205756904045L;

public static int currentClassVersion;

public UserClass () {

my_id = 1;

name = "SFO";

second_id = 2;

third_id = 3;

/* this is a new version of the class. currentClassVersion is

set to 2. In the old version, it was 1).*/

currentClassVersion = 2;

}

public int getId() {

return my_id;

}

public String getName() {

return name;

}

public String toString () {

return getId() + " " + getName() + second_id;

}

public int getCurrentClassVersion() {

return currentClassVersion;

}

}

Using the currentClassVersion in the WHERE clause allows you to do a SELEClike the following without any problems:

Cloudscape Version 3.0

Page 118: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-16

akes

e

,” on

pes in erly

from s an in the ge

-- without the WHERE clause, you would get a

-- divide-by-zero error for those rows in which

-- instances of the original version of the class

-- were stored

SELECT the_class->second_id/the_class->third_id

WHERE the_class.getCurrentClassVersion() = 2

Serializable Objects and Input/Output Streams

The JDBC methods setBytes and setString are capable of sending unlimited amounts of data. Cloudscape supports the JDBC getXXXStream and setXXXStream methods (see “ java.sql.PreparedStatement” on page 6-15 and “java.sql.ResultSet” on page 6-20 in the Cloudscape Reference Manual) to pass large blobs of data insmaller chunks (streams). When the statement is executed, the JDBC driver mrepeated calls to this input stream, reading its contents and transmitting thoscontents as the actual parameter data.

Only the JDBC data types shown in Table 6-1, “Streamable JDBC Data Typespage 6-15 in the Cloudscape Reference Manual (and their corresponding SQL-J types) support streams. You cannot use streams to store user-defined data tycolumns of the user-defined data type. However, user-defined types that propimplement writeObject(java.io.ObjectOutputStream) and readObject(java.io.ObjectInputStream) can use ObjectInputStreams and can be stored in columns of the supported data types.

Programming VTIsCloudscape provides a construct for presenting external data—from a flat file, another vendor’s database, from a news feed—as a virtual table to an SQL-JSELECT statement. Access to external data presented in this way constituteexternal virtual table that can be used within the scope of an SQL-J statement same way as other virtual or derived tables (see “ExternalVirtualTable” on pa1-76 in the Cloudscape Reference Manual).

An external virtual table is created by an instance of any class that fulfills therequirements of Cloudscape’s virtual table interface (VTI).

This section discusses how to create classes of that type.

• “Requirements and Options for VTI Classes” on page 5-17

cape Developer’s Guide

Page 119: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming VTIs 5-17

0.

ass

izer sting

tting

ou on mpile

he

QL-J

• “Providing Costing Information” on page 5-22

• “Templates for Creating VTIs” on page 5-25

• “Built-In VTIs and Example VTIs” on page 5-26

Requirements and Options for VTI Classes

To qualify as a VTI class, Java class must fulfill the VTI requirements:

• It must implement the java.sql.ResultSet interface.

See “Implementing ResultSet” on page 5-17.

• It must provide a way for Cloudscape to get the ResultSetMetaData at compile time.

See “Providing the ResultSetMetaData at Compile Time” on page 5-2

• The parameters to the VTI must all follow certain rules, and your VTI clmust be able to handle default values for parameters.

See “Rules for Parameters” on page 5-21.

Optionally, the class can provide costing information to the Cloudscape optimor prevent Cloudscape from instantiating it more than once. See “Providing CoInformation” on page 5-22.

Implementing ResultSet

A VTI class implements java.sql.ResultSet. A ResultSet consists of rows and columns of data, the methods for stepping through them, and a method for gethe ResultSetMetaData (getMetaData()).

At compile time, Cloudscape needs only the metadata. Depending on how yprogram the class (see “Providing the ResultSetMetaData at Compile Time” page 5-20), Cloudscape may call only a static method or the constructor at cotime, so it is typically not necessary to do all the work required for a ResultSet (stepping through all the rows) in the constructor. That work can be done in tnext() method. (This may not be possible in some cases.)

ResultSet and ResultSetMetaData Methods Used by Cloudscape

Both the java.sql.ResultSet and java.sql.ResultSetMetaData interfaces have a lot of methods. Cloudscape calls only a small subset of these methods within an Sstatement that uses ExternalVirtualTable. The list of these methods, which are

Cloudscape Version 3.0

Page 120: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-18

d

sion.

methods from the 1.2 version of JDBC (not 2.0), follows. Cloudscape does not call any methods from the 2.0 version of JDBC.

NOTE: This list is subject to change.

• ResultSet

- next()

- close()

- wasNull() (if column is nullable)

- getXXX method calls (see “getXXX method calls” on page 5-18)

• ResultSetMetaData

- getColumnCount()

- isNullable(int column)

- getColumnDisplaySize(int column)(This method call is meaningful only for Types that can vary in size—Types.BIT, Types.NUMERIC, Types.DECIMAL, Types.CHAR, Types.VARCHAR, Types.LONGVARCHAR, Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY, and Types.OTHER.)

- getColumnName(int column)

- getPrecision(int column) (for NUMERIC or DECIMAL columns)

- getScale(int column)

- getColumnType(int column)

• getXXX method calls

The getXXX method called on a column returned by a VTI is determineby the JDBC type of the column. Table 5-1 shows which getXXX method is called for each type.

If the statement selects data from the ExternalVirtualTable to insert it into a table, Cloudscape does not need to call the appropriate getXXX method based on the type of the target table; Cloudscape handles the conver

In addition, there is nothing to prevent application code from using anentirely different getXXX call on the column when stepping through theResultSet returned by Cloudscape.

For example, a VTI could return a column of JDBC type BIGINT:

SELECT cn FROM

NEW ExternalQuery(

’jdbc:cloudscape:toursDB’,

cape Developer’s Guide

Page 121: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming VTIs 5-19

ot

’SELECT CONGLOMERATENUMBER FROM SYS.SYSCONGLOMERATES’) AS

EQ (cn)

When evaluating the following statement, Cloudscape calls the VTI’s getLong on the ResultSet returned by the VTI to create the ResultSet returned to the user when the query is executed.

SELECT cn

FROM NEW ExternalQuery(

’jdbc:cloudscape:toursDB’,

’SELECT CONGLOMERATENUMBER FROM SYS.SYSCONGLOMERATES’)

AS EQ (cn)

However, the user’s application could call a getInt on that column instead:

ResultSet rs = s.executeQuery(

"SELECT * FROM NEW ExternalQuery" +

"’jdbc:cloudscape:toursDB’, " +

"’SELECT CONGLOMERATENUMBER FROM SYS.SYSCONGLOMERATES’) " +

"AS EQ");

while (rs.next()) {

System.out.println(rs.getInt(1));

}

In this case, the getInt method is the one implemented by Cloudscape, nby your VTI class. Cloudscape only calls the getLong method on the VTI.

Table 5-1 getXXX Methods Called for JDBC Types

ExternalVirtualTable’s Column JDBC Data Type getXXX Methods Called

BIGINT getLong

BINARY getBytes

BIT getBoolean

CHAR getString

DATE getDate

DECIMAL getBigDecimal

DOUBLE getDouble

FLOAT getDouble

INTEGER getInt

LONGVARBINARY getBytes

LONGVARCHAR getString

NUMERIC getBigDecimal

OTHER getObject

REAL getFloat

Cloudscape Version 3.0

Page 122: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-20

rs in

ss. It rder

ters at

s r piler e

at

Providing the ResultSetMetaData at Compile Time

Cloudscape needs the ResultSetMetaData for the ResultSet returned by the VTI at compile time. By default, Cloudscape instantiates the class in order to call the non-static getResultSetMetaData method on the object. Instantiating the class may be expensive, so for simple VTI classes that can determine the shape of the ResultSetMetaData based on the parameters, you can provide a static version of the method which allows you to avoid instantiation at compile time. To do this you must:

• Provide the static method public static java.sql.ResultSetMetaData getResultSetMetaData(parameterList), for which the parameterList signature is the same as for the constructor for that object that appeathe SQL-J statement.

The ResultSetMetaData object returned by this method is used by Cloudscape in compiling the SQL-J statement that instantiates the clais up to the implementor to determine what work needs to be done in oto return the correct ResultSetMetaData. The contents of the ResultSetMetaData may need to be dynamic depending on the parameor, or maybe the ResultSetMetaData are always is the same, no matter whthe parameters.

One example of when this method is a good choice is when your clasalways returns a ResultSet of the same shape given the same parametesignature. In this case, it is a lot less expensive for the Cloudscape comto get the ResultSetMetaData using the static method than to instantiate thclass.

NOTE: If your VTI class provides costing information (see “Providing CostingInformation” on page 5-22), Cloudscape always instantiates the classcompile time to get that costing information, so the static getResultSetMetaData is ignored.

SMALLINT getShort

TIME getTime

TIMESTAMP getTimestamp

TINYINT getByte

VARBINARY getBytes

VARCHAR getString

Table 5-1 getXXX Methods Called for JDBC Types

ExternalVirtualTable’s Column JDBC Data Type getXXX Methods Called

cape Developer’s Guide

Page 123: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming VTIs 5-21

ile h

s, at g files, , you

e):

QL-J ple:

e, time.

NOTE: In a client/server environment, the constructor and static method are called from within Cloudscape, so the resources needed by these methods must be available to Cloudscape, not just the client application.

Compile Time vs. Execution Time

When Cloudscape needs to instantiate the VTI class at compile time to determine the shape of its ResultSet, such a class will be instantiated twice—once at comptime and once at runtime. You may want the VTI class to be able to distinguisbetween those two different situations. For example, for performance reasonruntime you may want the class to begin some external actions such as readinconnecting to a mainframe, and so on, when it is constructed. At compile timemay not want it to carry out those actions.

Here’s how the VTI class can determine the situation (compile time or runtim

1 Add an object parameter (such as a string) to the constructor.

2 When invoking it within SQL-J, pass in a valid parameter.

3 Inside the VTI class, check the value of the parameter. If the object parameter is null, it is compile time.

Rules for Parameters

Constant Parameters

The currently supported constant expressions for compilation time are:

• GETCURRENTCONNECTION()

• literals (for example, 1, 'asdf', 1.1, or DATE'1996-09-09')

• CAST of a constant expression (for example, CAST 1.1 AS REAL)

Non-Constant Parameters

SQL-J statements, as you know, often include non-literals. For example, an Sstatement may include dynamic parameters or column references. For exam

SELECT * FROM a, b

WHERE a.col1 = b.col1

AND a.col1 = ?

In this example, the ? is a dynamic parameter that the application fills in at runtimand a.col1 and b.col1 are column references that Cloudscape evaluates at run

Cloudscape Version 3.0

Page 124: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-22

n

ent

Your VTI class must be able to handle such non-literal expressions. For example:

-- column name is a parameter

SELECT COUNT(*) FROM NEW jarvti(jar) AS jars, myjars

WHERE myjars.jar = ?

SELECT name FROM NEW jarvti(?) AS jars

As discussed elsewhere, Cloudscape may need to instantiate the VTI class at compile time. What value does it pass for these parameters at compile time (before literal values are substituted for the non-literals)? That depends on the data type of the parameter. In the above examples, the data type of the parameter is a String, which is a Java object, so Cloudscape passes in null. You must program your VTI class to handle a null value for Object parameters.

For Java primitives, Cloudscape passes in arbitrary default values. The default values are shown in Table 5-2.

NOTE: You may want to read “Method Resolution and Type Correspondence” opage 1-246 for information on working with parameters that are Java primitives.

Providing Costing Information

If a VTI class implements COM.cloudscape.vti.VTICosting, Cloudscape’s optimizer can use the information it provides when optimizing an SQL-J statem

Table 5-2 Default Values for Parameter Data Types

Data Type Default Value

Object null

A VTI must be prepared to handle a null parameter for an Object in its constructor and in the optional getResultSetMetaData method, if implemented.

byte 0

short 0

int 0

long 0L

float 0.0

double 0.0

boolean false

char ’\u0000’

cape Developer’s Guide

Page 125: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming VTIs 5-23

ape

ion

nnot

ake a

that references it. This may be useful in determining join order if the SQL-J statement involves a join.

For example, if it is very expensive to iterate through the rows in a VTI, Cloudscape would probably not choose it as an outer table in a join. If on the contrary it is very cheap to iterate through the rows in the VTI, Cloudscape would definitely choose it as the inner table in a join if it has a choice.

By default, Cloudscape assumes that it is very expensive to instantiate a VTI and to iterate through its rows. If you know more about a VTI’s cost than Cloudscdoes, provide that information by implementing this interface.

NEW: The ability to have a VTI class return costing information is new in Vers3.0.

This interface also provides a way for you to tell Cloudscape that the class cabe instantiated more than once.

To implement the interface, you must provide three methods. (The methods tparameter of type COM.cloudscape.database.VTIEnvironment, which you can ignore for the current release.)

• public double getEstimatedRowCount(COM.cloudscape.database.VTIEnvironment)

The estimated number of rows returned by a particular instance of the VTI.

• public double getEstimatedCostPerInstantiation(COM.cloudscape.database.VTIEnvironment)

The estimated cost of instantiating the VTI and iterating through the rows of that instantiation. Usually the cost of iterating through the rows constitutes the greatest part of the cost. (For more information, see “Estimating the Cost” on page 5-24).

• public boolean supportsMultipleInstantiations(COM.cloudscape.database.VTIEnvironment)

Whether the VTI can be instantiated more than once during execution. (most VTIs do not have this limitation.) Some unusual VTIs may open read-once streams; those VTIs should be instantiated only once by Cloudscape. Otherwise, Cloudscape may instantiate the VTI more than once in evaluating the statement.

When this method returns false, if Cloudscape chooses the VTI instantiation as the inner table of a join, it must materialize the VTI instantiation into a temporary table.

NOTE: You may wish only to inform Cloudscape that the VTI class can be instantiated only once and have no need to provide costing information.

Cloudscape Version 3.0

Page 126: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-24

or

ords

it

lue of

Unfortunately, this interface is all or nothing; you have to implement the cost-related methods anyway. If so, simply have the cost-related methods return the pre-defined variables defaultEstimatedRowCount or the defaultEstimatedCost.

Estimating the Cost

To estimate a VTI’s “cost,” your best bet is to work with RunTimeStatistics. (Fmore information about RunTimeStatistics, see Tuning Cloudscape.) This is done most easily from Cloudview, which provides an interface for viewing RunTimeStatistics.

1 In the SQL window, check the Use Statistics box.

2 Run a query that does a table scan.

3 Look at the Statistics tab, and select that node that begins with the wTable Scan (this is the TableScanResultSet). Right-click and select Inspectto display the TableScanResultSet object.

4 Write down the following values for the TableScanResultSet, which are displayed in the left-hand window:

optimizer’s estimated cost

total time spent in the result set (inspectOverall time, which is displayed in milliseconds)

5 Calculate the value of an “optimizer unit” for your environment:

(optimizer’s estimated cost)/

(total time spent in the result set)

6 Run the query again twice, re-calculating the value of an optimizer unfor your environment each time.

7 Calculate the average of the three calculations and use this as the vaan optimizer unit. This value does not have to be precise. It is used toprovide a rough estimate only.

8 Run a query that instantiates and selects from your VTI class.

9 Look at the Statistics tab for the statement.

10 Select the node that begins VTI, and right-click to inspect the VTIResultSet.

cape Developer’s Guide

Page 127: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming VTIs 5-25

is

tion

s ant,

is to

s

ds but s

11 Look through the text and write down:

total time spent in the result set (inspectOverall time, which is displayed in milliseconds)

the number of rows seen

12 Then calculate:

(optimizer unit) * (total time spent in the result set) /

(number of rows)

This figure is the inexact “cost” per row for your VTI class. If your classable to determine or estimate the number of rows in a particular instantiation, it should be able to return an estimated cost per instantia(“cost” per row * number of rows).

13 Estimate whether your VTI has an additional significant cost per instantiation over and above cost per row. For example, your VTI clasmay have a cost even if it returns 0 or 1 rows. If such a cost is significadd this cost to (cost per row * number of rows) when returning an estimate of total cost. To determine whether such a cost is significant select from an instantiation of the VTI that returns 0 or 1 rows, then inspect the statistics. If the statistics show any time at all in the inspectOverall field, the cost is significant. In such a case, the VTI classhould use the following slightly different formula to estimate cost:

((optimizer unit) *

((total time spent in the result set) - (total time spent in

empty result set)) /

(number of rows)) +

(total time spent in empty result set)

For an example of a VTI that provides costing information, see VTI class JBMSTours.vti.jdbc1_2.jarvti provided in the sample application.

Templates for Creating VTIs

The main requirement for a VTI class is that it implement java.sql.ResultSet, which has quite a few methods. Often a class uses only three or four of those methoit must implement the methods for them to compile correctly. Cloudscape haprovided two template classes to make it easier to develop VTI classes:

• COM.cloudscape.vti.VTITemplate

This class implements most of the methods of ResultSet, each one throwing an SQLException with the name of the method being called. A class that

Cloudscape Version 3.0

Page 128: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-26

extends this template can simply implement the methods it needs that are not implemented in the template and override any methods it needs to implement for correct functionality. (Compiles in JDBC 1.2 only.)

• COM.cloudscape.vti20.VTITemplate

This class implements most of the methods of ResultSet, each one throwing an SQLException with the name of the method being called. A class that extends this template can simply implement the methods it needs that are not implemented in the template and override any methods it needs to implement for correct functionality. (Compiles in JDBC 2.0.)

• COM.cloudscape.vti.VTIMetaDataTemplate,

An abstract implementation of ResultSetMetaData (JDK1.1/JDBC 1.2). This class implements most of the methods of ResultSetMetaData, each one throwing an SQLException with the name of the method. A class that extends this template can simply implement the methods not implemented here and override any methods it needs to implement for correct functionality. (Compiles in JDBC 1.2 only.)

• COM.cloudscape.vti20.VTIMetaDataTemplate,

An abstract implementation of ResultSetMetaData (JDK1.1/JDBC 1.2). This class implements most of the methods of ResultSetMetaData, each one throwing an SQLException with the name of the method. A class that extends this template can simply implement the methods not implemented here and override any methods it needs to implement for correct functionality. (Compiles in JDBC 2.0.)

Cloudscape provides the source for these classes in demo/programs/tours/JBMSTours/vti/jdbc1_2; see VTITemplate.txt, VTIMetaDataTemplate.txt., VTITemplate.txt, and VTIMetaDataTemplate.txt

Built-In VTIs and Example VTIs

The Cloudscape engineers have found VTI classes an extremely useful way of presenting information. Whereas another DBMS may come with clunky system functions, Cloudscape comes with a number of built-in VTIs that provide internal system information to the end-user (you) in an elegant way. For example:

• COM.cloudscape.vti.LockTable

• COM.cloudscape.vti.TransactionTable

• COM.cloudscape.vti.TriggerOldTransitionRows

• COM.cloudscape.vti.TriggerNewTransitionRows

cape Developer’s Guide

Page 129: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming User-Defined Aggregates 5-27

egates X, do

in

n any

s that

• COM.cloudscape.synchronization.RowListVTI

• COM.cloudscape.synchronization.StatementListVTI

• COM.cloudscape.synchronization.TransactionListVTI

• COM.cloudscape.vti.ExternalQuery

This one isn’t for internal use; you are free to use it yourselves. It’s souseful that Cloudscape has provided the source for it in demo/programs/tours/JBMSTours/vti/jdbc1_2; see ExternalQuery.txt.

The JBMSTours sample application comes with a sample VTI class, JBMSTours.vti.jarvti, if you want to look at another example VTI class.

Programming User-Defined AggregatesCloudscape allows you to create user-defined aggregates. User-defined aggrallow you to gather more sophisticated information than is available from MAMIN, SUM, and the other built-in aggregates. If you can do it in Java, you canit in Cloudscape.

On the language side, you issue a CREATE AGGREGATE statement that is essence an alias for the Java class that provides the logic for performing theaggregate.

If you provide the correct implementation, a user-defined aggregate can returbuilt-in type or any user-defined Java data type.

This section discusses how to create classes that perform aggregation for Cloudscape use.

Developing the Java Classes that Perform the Aggregation

To support Cloudscape aggregation, you must provide a Java class or classeimplements two interfaces:

• COM.cloudscape.aggregates.AggregateDefinition

For each valid input type, specifies the return type of the aggregate and the name of the class that will perform the aggregation (which implements COM.cloudscape.aggregates.Aggregator). This information is needed at compile time.

The name of this class is typically the same as the name you give the SQL-J aggregate with the CREATE AGGREGATE statement. For example:

Cloudscape Version 3.0

Page 130: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-28

CREATE AGGREGATE MAXBUTONE FOR

JBMSTours.aggregates.MaxButOneDef

You specify the aggregator by filling in the StringBuffer passed in to the getAggregator method.

You specify the return type in the same method by returning an object of type COM.cloudscape.types.TypeDescriptor, which is a Cloudscape object for describing types. For aggregates that simply return the input type, return the TypeDescriptor that was passed in as a parameter.

To return a TypeDescriptor representing any other Java type, construct a TypeDescriptor like this:

COM.cloudscape.database.Factory.getTypeFactory().getTypeDescrip

tor(javaClassName)

For example, if the aggregate returned a vector, the getAggregator method would return:

COM.cloudscape.database.Factory.getTypeFactory().getTypeDescrip

tor("java.util.Vector")

To return a TypeDescriptor representing any other built-in type, construct a TypeDescriptor like this:

COM.cloudscape.database.Factory.getTypeFactory().getTypeDescrip

tor(JDBCType)

For example, if the aggregate returned an INTEGER the getAggregator method would return:

COM.cloudscape.database.Factory.getTypeFactory().getTypeDescrip

tor(java.sql.Types.INTEGER)

For Java type, do not use java.sql.Types.OTHER; instead, specify the class name as a string.

For more information about the COM.cloudscape.aggregates.AggregateDefinition interface, see the Javadoc.

• COM.cloudscape.aggregates.Aggregator

The class that implements this interface performs the aggregation. This class is used at execution time. It is instantiated at run time and is passed in each value that is to be aggregated. The class is responsible for calculating the aggregate based on the input (which it does with the

cape Developer’s Guide

Page 131: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming User-Defined Aggregates 5-29

ate t it

n

accumulate method). When Cloudscape has finished processing all rows, it calls the getResult method to retrieve the final result.

This interface requires five methods. The interesting ones are:

- accumulate(ResultSet). Iteratively accumulates the addend into the aggregator. For an aggregator called CountMe that returns a simple int count, this method would simply add one to the count each time it was called. (Cloudscape will call the method once for each input row).

- getResult(). Produces the result to be returned by the query. For an aggregator called CountMe that returns a simple int count, this method would return the accumulated count.

- merge(Aggregator). Merges one aggregator into another aggregator. For an aggregator called CountMe that returns a simple int count, this method would aggregate (in this case, add) the count of the passed-in aggregator with the count of this. (This method is called instead of the accumulate method when the aggregate is used in a GROUP BY.)

Vector aggregates, aggregates that are used in a GROUP BY statement, require sorting. Aggregators must be serializable in case the sort is too large to keep in memory.

For more information about this interface, see the Javadoc.

The sample application JBMSTours comes with a few examples of aggregate classes (in the /demo/programs/tours/JBMSTours/aggregates directory), which may help you get started programming your own aggregates:

• JBMSTours.aggregates.MaxButOneDef

Implements AggregateDefinition. A very simple example of an aggregate that returns the “second highest” value in a column (like MAX, only it returns the value just below MAX). This class specifies that the aggregaccepts only values of type INTEGER and DOUBLE PRECISION; thareturns the same type as the input type; and that for values of type INTEGER, the aggregator is JBMSTours.aggregates.MaxButOneIntegerAggregator, and for values of type DOUBLE PRECISION, the aggregator is JBMSTours.aggregates.MaxButOneDoubleAggregator.

This is the only class for which an aggregate database object has beecreated in toursDB (with the CREATE AGGREGATE statement).

• JBMSTours.aggregates.MaxButOneDoubleAggregator

Implements COM.cloudscape.aggregates.Aggregator. The aggregator for JBMSTours.aggregates.MaxButOneDef when the input type is DOUBLE PRECISION.

Cloudscape Version 3.0

Page 132: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-30

data

.

ine a n a

tion,

ion ger

ement

• JBMSTours.Aggregates.MaxButOneIntegerAggregator

Implements COM.cloudscape.aggregates.Aggregator. The aggregator for JBMSTours.aggregates.MaxButOneDef when the input type is INTEGER.

• JBMSTours.aggregates.MaxButOneJDK12

A JDK1.2-only class that is similar to JBMSTours.aggregates.MaxButOneDef, except that this class implements both AggregateDefinition and Aggregator. The JDK 1.2’s improvements to java.lang.Object make it much easier to compare values among the standard data types, so this class accepts input values of all the built-intypes. This class also implements Aggregator and so performs the aggregation itself as well as the aggregate definition.

• JBMSTours.aggregates.StandardDeviation

Implements both AggregateDefinition and Aggregator. Uses the VisualNumerics.math.Statistics package to implement a poor man’s standard deviation. Accepts only values of type DOUBLE PRECISION

NOTE: You can create an aggregate for this class if you have the VisualNumerics.math.Statistics package available from http://www.vni.com.

Programming Trigger ActionsCloudscape allows you to create triggers. When you create a trigger, you defan action or set of actions that are executed when a database event occurs ospecified table. A database event is a delete, insert, or update operation. For example, if you define a trigger for a delete on a particular table, the trigger acis executed whenever someone deletes a row or rows from the table.

The “CREATE TRIGGER statement” on page 1-51 in the Cloudscape Reference Manual goes into detail of the complete CREATE TRIGGER syntax. This sectprovides information on only one aspect of creating triggers, defining the trigaction itself, which is the very last part of the CREATE TRIGGER statement.

The statement can call complex Java methods. This section refers to the statand all work performed by methods it calls as the trigger actions.

• “Trigger Action Overview” on page 5-31

• “Performing Referential Actions” on page 5-31

• “Accessing Before and After Rows” on page 5-32

cape Developer’s Guide

Page 133: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Trigger Actions 5-31

thod

tain

or Table you n A. rows key

t this

• “Examples” on page 5-33

• “Triggers and Exceptions” on page 5-38

• “Transactionally Independent Trigger Actions” on page 5-40

• “Long-Running Trigger Actions” on page 5-41

Trigger Action Overview

A trigger action can be a simple SQL-J statement, or it can invoke a Java meto perform more complex actions. For example:

CREATE TRIGGER . . .

DELETE FROM HotelAvailability

WHERE hotel_id IN (SELECT hotel_id FROM OLD)

CREATE TRIGGER . . .

CALL (CLASS

JBMSTours.triggers.TriggerActions).deleteOrRedoHotelBooking(

getCurrentConnection(), CURRENT_JDATE())

A trigger action does have some limitations, though; for example, it cannot condynamic parameters or alter the table on which the trigger is defined. See “TriggerAction” on page 1-54 in the Cloudscape Reference Manual for details.

Performing Referential Actions

One of the most common uses of a trigger is to perform a referential action. Fexample, you may want to create a trigger that performs a cascading delete. IfA’s primary key columns are referenced by Table B’s foreign key columns, thenwould not be able to delete rows from Table A if any rows in Table B depend oWith a cascading delete, you could configure the system to delete the relatedin Table B that depend on Table A before completing the delete of the primaryrows in Table A.

Although cascading deletes are not built in to Cloudscape, you can implemenfunctionality yourself through triggers. Most of the examples in this section perform cascading deletes.

Cloudscape Version 3.0

Page 134: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-32

alues:

age

The

ger.

and

an

this

l the

Accessing Before and After Rows

Many trigger actions need to access the values of the rows being changed. Such trigger actions need to know one or both of the following:

• the “before” values of the rows being changed (their values before thedatabase event that caused the trigger to fire)

• the “after” values of the rows being changed (the values to which the database event is setting them)

Cloudscape provides a few different ways for a trigger action to access these v

• Transition variables and transition tables.

See “Referencing Old and New Values: The Referencing Clause” on p1-52 in the Cloudscape Reference Manual.

• Transition Rows VTIs.

Usable from both SQL and Java methods called by the trigger actions.VTI classes COM.cloudscape.triggers.TriggerOldTransitionRows and COM.cloudscape.triggers.TriggerNewTransitionRows return a before or after image of all the rows being changed by the currently executing trig

Cloudscape provides built-in aliases for these classes, TriggerOldTransitionRows and TriggerNewTransitionRows.

NOTE: For statement triggers, these VTIs correspond to the OLD and NEW transition tables. For row triggers, these VTIs contain only a single row correspond to the OLD and NEW transition variables.

• An instance of COM.cloudscape.database.TriggerExecutionContext.

Typically used by methods executed by the trigger action.You retrieveinstance of this class by calling the method COM.cloudscape.database.Factory.getTriggerExecutionContext() from within your trigger action. (Cloudscape provides a built-in alias for Factory.) (Also usable from SQL.)

This object provides varied information about the trigger, not just the before and after image of a row. For information, see the Javadoc forclass.

To see the before or after image of the particular row being altered, calgetOldRow() and getNewRow() or getOldRowSet() and getNewRowSet() methods. The xxxRow() methods return a single-row ResultSet in position (you do not have to call a next() on them).

cape Developer’s Guide

Page 135: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Trigger Actions 5-33

Examples

You will find source code for all Java methods referred to in the following examples in JBMSTours.triggers.TriggerActions.

The following three trigger actions, though coded differently, all accomplish the same thing; when rows are deleted from the Cities table, they delete related rows in the Hotels table. The first trigger uses the OLD transition variable, which is the easiest way for the trigger to find out which rows it needs to delete from the Hotels table. The second trigger shows how to accomplish the same thing with the TriggerExecutionContext; the third trigger shows how to accomplish the same thing with the TriggerOldTransitionRows. Normally, however, you would not need to use those constructs unless you were unable to use the transition tables or transition variables, which is the case from within a Java method. (Later examples in this section demonstrate that.)

-- before deleting a city, delete related hotels

-- row trigger using transition variable

CREATE TRIGGER DeleteRelatedHotels1

BEFORE DELETE

ON Cities

REFERENCING OLD ROW AS DeletedCities

FOR EACH ROW

DELETE FROM Hotels

WHERE city_id = DeletedCities.city_id

-- Demonstrates how to use the TriggerExecutionContext

-- (but it’s easier to use the transition table,

-- as in the previous example)

-- before deleting a city, delete related hotels

CREATE TRIGGER DeleteRelatedHotels2

BEFORE DELETE

ON Cities

FOR EACH ROW

DELETE FROM Hotels

WHERE city_id = Factory.getTriggerExecutionContext().

getOldRow().getString(’city_id’)

-- Demonstrates how to use the TriggerOldTransitionRows()

-- (but it’s easier to use the transition table,

-- as in the previous example)

-- statement trigger referring to the old rows VTI

-- before deleting a city, delete related hotels

CREATE TRIGGER DeleteRelatedHotels3

BEFORE DELETE

ON Cities

Cloudscape Version 3.0

Page 136: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-34

FOR EACH STATEMENT

DELETE FROM Hotels WHERE city_id IN

(SELECT city_id FROM NEW TriggerOldTransitionRows()

AS Old_Cities)

For more complex logic, you can call a Java method.

Here is an example of a trigger action that calls a Java method that accesses the TriggerExecutionContext.

CREATE TRIGGER DeleteRelatedHotels4

BEFORE DELETE

ON Cities

FOR EACH STATEMENT

CALL (CLASS

JBMSTours.triggers.TriggerActions).deleteRelatedHotels(

getCurrentConnection())

And the source code for the method:

/*

* Demonstrate using the TriggerExecutionContext to reference

* the old values for the row being changed.

*/

public static void deleteRelatedHotels(Connection conn)

throws Throwable

{

TriggerExecutionContext context =

Factory.getTriggerExecutionContext();

PreparedStatement ps = conn.prepareStatement(

"DELETE FROM hotels WHERE city_id = ?");

/*

** Here we iterate through all the rows that have

** been deleted.

** We obtain the deleted rows from the trigger

** execution context.

*/

ResultSet oldRows = context.getOldRowSet();

while (oldRows.next())

{

ps.setString(1, oldRows.getString("city_id"));

ps.executeUpdate();

}

oldRows.close();

cape Developer’s Guide

Page 137: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Trigger Actions 5-35

to the

ps.close();

}

Here’s another example of calling a Java method in a trigger. This one refers TriggerOldTransitionRows VTI from within an SQL-J statement.

CREATE TRIGGER DeleteRelatedHotels5

BEFORE DELETE

ON Cities

FOR EACH STATEMENT

CALL (CLASS

JBMSTours.triggers.TriggerActions).deleteRelatedHotels2(

getCurrentConnection());

/*

* Use the TriggerOldTransitionRows VTI to do a cascading delete

* in one fell swoop.<p>

*/

public static void deleteRelatedHotels2(Connection conn)

throws Throwable

{

PreparedStatement ps = conn.prepareStatement(

"DELETE FROM hotels WHERE city_id IN "+

"(SELECT city_id FROM NEW TriggerOldTransitionRows() " +

"AS OLDROWS)");

ps.executeUpdate();

ps.close();

}

This example calls a Java method that access the TriggerNewTransitionRowsVTI directly instead of from within an SQL-J statement.

CREATE TRIGGER ShowNewBookings

AFTER INSERT

ON HotelBookings

FOR EACH STATEMENT CALL (CLASS

JBMSTours.triggers.TriggerActions).showNewBookings(

getCurrentConnection())

And the source of the method being called:

/*

* Use the TriggerNewTransitionRowsVTI from within a method call,

* not directly in the trigger statement. Use it to

* do a system out of rows inserted into the HotelBookings table.

Cloudscape Version 3.0

Page 138: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-36

*/

public static void showNewBookings(Connection conn)

throws SQLException

{

Statement s = conn.createStatement();

Util.println("New hotel bookings:");

ResultSet rs = s.executeQuery(

"SELECT * FROM new TriggerNewTransitionRows() AS EQ");

while (rs.next()) {

Util.println(rs.getInt(1) + " " +

rs.getDate(3) + " " + rs.getDate(4));

}

rs.close();

s.close();

}

Here’s another example:

CREATE TRIGGER AuditCities

BEFORE DELETE

ON Cities

FOR EACH STATEMENT

CALL (CLASS JBMSTours.triggers.TriggerActions).auditCities(

getCurrentConnection(), CURRENT_USER)

And the source of the method being called:

/*

* Get a connection to the History database,

* which we are using as kind of an audit database,

* insert a row for each city that is deleted.

* Also, send email for each deleted city. <p>

*/

public static void auditCities(Connection conn1, String user)

throws Throwable

{

Connection conn2=null;

try

{

// the statement querying the special vti must

// be against the original connection

Statement s = conn1.createStatement();

ResultSet deletedRows = s.executeQuery(

cape Developer’s Guide

Page 139: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Trigger Actions 5-37

"SELECT city FROM NEW TriggerOldTransitionRows() " +

"AS oldCities");

// make a new connection to the History database

// for storing the audit information

conn2 =

DriverManager.getConnection("jdbc:cloudscape:History");

PreparedStatement ps = conn2.prepareStatement(

"INSERT INTO deletedCities VALUES (?, ?)");

ps.setString(1, user);

while (deletedRows.next())

{

City city = (City)deletedRows.getObject("CITY");

sendMsg("deleted city "+ city.getName());

ps.setObject(2, city);

ps.execute();

}

deletedRows.close();

ps.close();

s.close();

}

finally

{

if (conn2 != null)

conn2.close();

}

}

Another example:

CREATE TRIGGER hotelsAltered

AFTER UPDATE OF normal_rate, high_season_rate

ON Hotels

FOR EACH STATEMENT

CALL (CLASS

JBMSTours.triggers.TriggerActions).hotelChanged(

getCurrentConnection())

/*

* Demonstrate doing a join with a triggers transition tables,

* send mail based on result

*/

public static void hotelChanged(Connection conn) throws Throwable

Cloudscape Version 3.0

Page 140: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-38

own

{

Statement s = conn.createStatement();

ResultSet rs = s.executeQuery(

"SELECT NewHotels.hotel_name, OldHotels.normal_rate, " +

"OldHotels.high_season_rate, "+

"NewHotels.normal_rate, NewHotels.high_season_rate " +

"FROM NEW TriggerNewTransitionRows() AS NewHotels, " +

"NEW TriggerOldTransitionRows() AS OldHotels " +

"WHERE NewHotels.hotel_id = OldHotels.hotel_id");

while (rs.next()) {

sendMsg(rs.getString(1) + "’s rates have changed: from $" +

rs.getBigDecimal(2, 2) + " and $" +

rs.getBigDecimal(3, 2) +

" to $" + rs.getBigDecimal(4, 2) + " and $" +

rs.getBigDecimal(5,2));

}

s.close();

}

Triggers and Exceptions

• “Example of User-Defined SQLException” on page 5-38

• “Exceptions in Triggers Actions” on page 5-39

• “Aborting Statements and Transactions” on page 5-40

Example of User-Defined SQLException

As stated in “User-Defined SQLExceptions” on page 5-8, you can throw your SQLExceptions from any database-side method, including methods called by triggers, for methods that perform some kind of integrity checking. The SQLException should be in the range of 38001-38999.

For example:

CREATE TRIGGER alterCity

BEFORE UPDATE

ON Cities

FOR EACH ROW

CALL TriggerActions.cityChanged()

cape Developer’s Guide

Page 141: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Trigger Actions 5-39

/*

* Demonstrate referencing the TriggerExecutionContext to find out

* information other than before or after values. Also, throw

* a user-defined SQLException to indicate an integrity violation

*/

public static void cityChanged() throws Throwable

{

TriggerExecutionContext context =

Factory.getTriggerExecutionContext();

// don’t let anyone change the CITY_ID

if (context.wasColumnModified("CITY_ID"))

{

// this exception will cause the update statement

//to be rolled back

throw new SQLException(

"changes to CITY_ID are prohibited", "38001")

}

}

Exceptions in Triggers Actions

Exceptions raised by triggers have a statement severity; that is, they roll back the statement that caused the trigger to fire. For example: Suppose that you have defined a row trigger on an update statement that does some work within a Java method. Suppose that an update statement successfully updates 10 rows but an exception is raised when it updates the 11th row. The entire update statement and any work done by the trigger using the current connection are rolled back. However, any work done within that transaction prior to the update statement is not rolled back.

The same rules apply for nested triggers (triggers that are fired by other triggers). If a trigger action raises an exception (and it is not caught), the transaction on the current connection is rolled back to the point before the triggering event. For example, suppose Trigger A causes Trigger B to fire. If Trigger B throws an exception, the current connection is rolled back to the point before to the statement in Trigger A that caused Trigger B to fire. Trigger A is then free to catch the exception thrown by Trigger B and continue with its work. If Trigger A does not throw an exception, the statement that caused Trigger A as well as any work done in Trigger A continue until the transaction in the current connection is either committed or rolled back. However, if Trigger A does not catch the exception from Trigger B, it is as if Trigger A had thrown the exception. In that case, the statement

Cloudscape Version 3.0

Page 142: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-40

is at

d by tion ion,

ord ion

that caused Trigger A to fire is rolled back, along with any work done by both of the triggers.

Aborting Statements and Transactions

You may want a trigger action to be able to abort the triggering statement or even the entire transaction. Triggers that use the current connection are not permitted to commit or roll back the connection, so how do you do that? The answer is: have the trigger throw an exception, which is by default a statement-level exception (which rolls back the statement). The application-side code that contains the statement that caused the trigger to fire can then roll back the entire connection if desired. Programming triggers in this respect is no different from programming any database-side JDBC method.

For example, imagine a program that contains a statement that causes the trigger shown in the section “Example of User-Defined SQLException” on page 5-38. Thtrigger sometimes throws an Exception. Here is some sample application code thcontains a statement that may cause the trigger to fire:

conn.commit();

Statement s = conn.createStatement();

try {

s.executeUpdate(userStatementString);

}

catch (SQLException e) {

// the statement will automatically be aborted since an exception

// was thrown.

// Roll back the whole transaction if desired. For example:

// conn.rollback();

}

Transactionally Independent Trigger Actions

It is possible for a trigger action to use a different connection than the one usethe statement that caused it to fire. Any work performed in a different connecis potentially transactionally independent of work done in the original connectbecause you can commit or roll back work on the new connection before completing the execution of the trigger. Working with a separate connection/transaction is sometimes useful. For example, you may want to audit and recinformation about attempts to update a table. Working in a separate transact

cape Developer’s Guide

Page 143: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Orderable Classes 5-41

5-43

allows you to record the attempt to update the table even if the update statement itself is rolled back.

NOTE: Opening a new connection to the same database can cause locking conflicts.

In most cases, your triggers work in the same connection (and transaction) as the statement that caused them to fire.

Long-Running Trigger Actions

Triggers are executed synchronously; long-running trigger actions can adversely affect performance. If you need trigger actions to perform many tasks and are worried about performance, have the Java method called by the trigger start a new thread to do its work.

NOTE: A method can access the TriggerExecutionContext only while the trigger is active. Once the event that caused the trigger to fire completes, the TriggerExecutionContext is invalidated.

Programming Orderable ClassesCloudscape allows you to perform ordering, comparisons operations, and index creation on special Java data types called orderable Java data types. (For a complete list of their capabilities and SQL-J examples, see “Orderable Java Data Types” onpage 1-214 in the Cloudscape Reference Manual. For more SQL-J examples, see“Orderable Java Data Types” on page 4-7.)

This section discusses how details of creating orderable Java data types andprovides detailed implementation notes.

It also discusses requirements for Java data types that will use the = or <> comparison operators (not just orderable Java data types).

• “Requirements for Orderable Java Data Types” on page 5-42

• “Notes on compareTo Implementation” on page 5-42

• “Notes on Implementing the equals and hashCode Methods” on page

• “Comparison Operators and Objects of Different Types” on page 5-44

Cloudscape Version 3.0

Page 144: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-42

re:

(See

1.1

Requirements for Orderable Java Data Types

Cloudscape can put objects in the correct order if those objects provide a special method for that purpose, the compareTo method.

Therefore, to qualify as an orderable Java data type, a Java class must meet the following requirements:

• In a JDK 1.1 environment, it has a method with the this exact signatu

public int compareTo(Object o)

For the behavior of the compareTo method (see “Notes on compareTo Implementation” on page 5-42).

• In a JDK 1.2 environment, it implements the interface java.lang.Comparable or follows the rules for the JDK 1.1 environment.

• In either environment, it must override the hashCode() and equals(Object o) methods in java.lang.Object correctly, which is a requirements for all Java data types if the = and <> operators are going to work correctly “Notes on Implementing the equals and hashCode Methods” on page5-43).

NOTE: Given these rules, a Java data type should be orderable in both environments, thus allowing a database to move freely between a JDKand a JDK1.2 environment.

Notes on compareTo Implementation

The behavior of the compareTo method is defined by the JDK 1.2 interface java.lang.Comparable, which is copied here:

cape Developer’s Guide

Page 145: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Orderable Classes 5-43

ass

at

ject

ovided

• public int compareTo(Object o)Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)

The implementor must also ensure that the relation is transitive: (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.

Finally, the implementor must ensure that x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.

It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is “Note: this clhas a natural ordering that is inconsistent with equals.”

NOTE: On this last point, although the JDK rules only strongly recommend ththe ordering be consistent with equals, Cloudscape requires it.

Any ordering or index maintenance in Cloudscape depends on the correct implementation of the compareTo method. If a class’s compareTo method does not follow the implementation rules, the results of any query involving such an obare not defined. It is also expected that calling the compareTo method of an object does not change the state of the object or that of the passed in object.

NOTE: The compareTo method should not do anything bizarre such as make random comparisons, call database-side JDBC, or alter the object. compareTo and equals must work correctly with subclasses.

Notes on Implementing the equals and hashCode Methods

The operators = and <> are allowed even on non-orderable Java data types prthat they correctly implement the following methods:

• equals (Object o)

• hashCode()

(See “Java Data Types and Equality Operations” on page 1-213 in the Cloudscape Reference Manual.)

Cloudscape Version 3.0

Page 146: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-44

e the

ery

om

when er is

The behavior of the equals method is defined by the class java.lang.Object. The API documentation is copied here:

• public boolean equals(Object obj) Compares two Objects for equality.

The equals method implements an equivalence relation:

It is reflexive: for any reference value x, x.equals(x) should return true.

It is symmetric: for any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

It is transitive: for any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.

It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false.

For any reference value x, x.equals(null) should return false.

The behavior of the hashCode method is also defined by the API. Typically implementation of hashCode is related to implementation of equals.

If a Java data type is orderable, Cloudscape uses the type’s compareTo method (not the equals method) to implement the = and <> operators. Cloudscape may ushashCode method for DISTINCT operations.

Therefore, correct comparisons in Cloudscape depend on the correct implementation of the compareTo or equals methods. If a class’s compareTo or equals method does not follow the implementation rules the results of any quinvolving such an object are not defined.

NOTE: The equals method should not do anything bizarre such as make randcomparisons, call database-side JDBC, or alter the object. compareTo and equals must work correctly with subclasses.

Comparison Operators and Objects of Different Types

When comparisons between different data types are supported, what happenscomparisons between objects when one of the types is orderable and the othnot?

One of the Java Data Types is Orderable

Expressions using the comparison operators are converted to internal Java expressions as shown in the following tables.

cape Developer’s Guide

Page 147: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Programming Orderable Classes 5-45

If a is an orderable Java data type and b is an orderable or non-orderable Java data types:

If a is not an orderable Java data type, but b is:

Built-in data types are converted to their corresponding Java type before being used as parameters in the method calls shown in these tables.

Neither Java Data Type Is Orderable

(If neither Java Data Type is Orderable, only the = and <> operators are allowed.)

If a is a non-orderable Java data type, the internal method calls are:

If a is a built-in type but b is a Java data type:

SQL-J Expression Equivalent Java Expression

a < b a.compareTo(b) < 0

a <= b a.compareTo(b) <= 0

a > b a.compareTo(b) > 0

a >= b a.compareTo(b) >= 0

a = b a.compareTo(b) == 0

a <> b a.compareTo(b) != 0

SQL-J Expression Equivalent Java Expression

a < b b.compareTo(a) > 0

a <= b b.compareTo(a) >= 0

a > b b.compareTo(a) < 0

a >= b b.compareTo(a) <= 0

a = b b.compareTo(a) == 0

a <> b b.compareTo(a) != 0

SQL-J Expression Equivalent Java Expression

a = b a.equals(b)

a <> b ! a.equals(b)

SQL-J Expression Equivalent Java Expression

a = b b.equals(a)

a <> b ! b.equals(a)

Cloudscape Version 3.0

Page 148: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Special Cloudscape Programming

Clouds

5-46

To force use of the specific method comparison (equals or compareTo), use the desired method call explicitly. For example:

SELECT CITY FROM CITIES WHERE city.equals(?)

NOTE: The JBMSTours sample application type includes three orderable types. One is JBMSTours.serializabletypes.City. Look at this type if you want a concrete example.

cape Developer’s Guide

Page 149: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

27

A DBC

6 Controlling Cloudscape Application Behavior

This chapter looks at some advanced Cloudscape concepts:

• “The JDBC Connection and Transaction Model” on page 6-1

• “SQL-J and JDBC ResultSet/Cursor Mechanisms” on page 6-7

• “Locking, Concurrency, and Isolation” on page 6-13

• “Working with Multiple Connections to a Single Database” on page 6-

• “Working with Multiple Threads Sharing a Single Connection” on page6-30

• “Working with Cloudscape SQLExceptions in an Application” on page6-34

The JDBC Connection and Transaction ModelSession and transaction capabilities for SQL-J are handled through JDBC methods, not by SQL-J commands.

JDBC defines a system session and transaction model for database access.session is the duration of one connection to the database and is handled by a JConnection object. This section includes the following topics:

• “Connections” on page 6-2

• “Transactions” on page 6-3

6-1

Page 150: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-2

t’s ases

d to BC

Connections

A Connection object represents a connection with a database. Within the scope of one Connection, you access only a single Cloudscape database. (Database-side JDBC methods can allow you to access more than one database in some circumstances.) A single application, depending on your Cloudscape produclicense, may be allowed to have one or more Connections to Cloudscape, either toa single database or to many different databases, provided that all the databare within the same system (see “Cloudscape System” on page 2-5).

You get a Connection object to a database with the DriverManager.getConnection method. You use the database connection URL as an argument to the methospecify which database to connect to and other details (see “Cloudscape JDDatabase Connection URL” on page 2-4).

The following example shows an application establishing three separate connections to two different databases in the current system.

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:toursDB");

System.out.println("Connected to database toursDB");

conn.setAutoCommit(false);

Connection conn2 = DriverManager.getConnection(

"jdbc:cloudscape:newDB;create=true");

System.out.println("Created AND connected to newDB");

conn2.setAutoCommit(false);

Connection conn3 = DriverManager.getConnection(

"jdbc:cloudscape:newDB");

System.out.println("Got second connection to newDB");

conn3.setAutoCommit(false);

A Connection object has no association with any specific thread; during its lifetime, any number of threads may have access to it, as controlled by the application.

Statements

To execute SQL-J statements against a database, an application uses Statements (java.sql.Statement) and PreparedStatements (java.sql.PreparedStatement). Since PreparedStatement extends Statement, this section refers to both as Statements. Statements are obtained from and are tied to a particular Connection.

cape Developer’s Guide

Page 151: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

The JDBC Connection and Transaction Model 6-3

with

and

nit he

you

ResultSets and Cursors

Executing a Statement that returns values gives a ResultSet (java.sql.ResultSet), allowing the application to obtain the results of the statement. Only one ResultSet can be open for a particular Statement at any time, as per the JDBC specification.

Thus, executing a Statement automatically closes any open ResultSet generated by an earlier execution of that Statement.

For this reason, you must use a different Statement to update a cursor (a named ResultSet) from the one used to generate the cursor.

The names of open cursors must be unique within a Connection. For more information about how to use cursors and ResultSets, see “SQL-J and JDBC ResultSet/Cursor Mechanisms” on page 6-7.

Nested Connections

SQL-J statements can include method invocations. If these methods interactthe database, they must use a Connection. When these methods use the same Connection as the calling statement, the Connection is known as a nested connection. For example:

-- findCity must not issue a commit or rollback

VALUES findCity(getCurrentConnection(), 5)

Methods using nested connections cannot commit or roll back a transaction,thus Cloudscape silently turns off auto-commit during database-side methodexecution and turns it back on when the execution completes. (See “Nested Connections” on page 6-3.)

For more information, see “Invoking Database-Side JDBC Methods” on page4-13.

Transactions

A transaction is a set of one or more SQL statements that make up a logical uof work that you can either commit or roll back and that will be recovered in tevent of a system failure. All the statements in the transaction are atomic. A transaction is associated with a single Connection object (and database). A transaction cannot span Connections (or databases).

Cloudscape permits schema and data manipulation statements (DDL) to be intermixed within a single transaction. If you create a table in one transaction,

Cloudscape Version 3.0

Page 152: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-4

the

s all

d

lt, as ment -curs comes

; the

o

can also insert into it in that same transaction. A schema manipulation statement is not automatically committed when it is performed, but participates in the transaction within which it is issued. Because DDL requires exclusive locks on system tables, keep transactions that involve DDL short.

Transactions When Auto-Commit Is Disabled

When auto-commit is disabled (see “Using Auto-Commit” on page 6-4), you usea Connection object’s commit and rollback methods to commit or roll back a transaction. The commit method makes permanent the changes resulting fromtransaction and releases locks. The rollback method undoes all the changes resulting from the transaction and releases locks. A transaction encompassethe SQL-J statements executed against a single Connection object since the last commit or rollback.

You do not need to explicitly begin a transaction. You implicitly end one transaction and begin a new one after disabling auto-commit, changing the isolation level, or after calling commit or rollback.

Committing or rolling back a transaction closes all open ResultSet objects and currently executing Statements in that Connection. It also releases any database locks currently held by the Connection, whether or not these objects were createin different threads.

Using Auto-Commit

A new connection to a Cloudscape database is in auto-commit mode by defauspecified by the JDBC standard. Auto-commit mode means that when a stateis completed, the method commit is called on that statement automatically. Autocommit in effect makes every SQL-J statement a transaction. The commit ocwhen the statement completes or the next statement is executed, whichever first. In the case of a statement returning a ResultSet, the statement completes when the last row of the ResultSet has been retrieved or the ResultSet has been closed explicitly.

Some applications may prefer to work with Cloudscape in auto-commit modesome may prefer to work with auto-commit turned off. You should be aware ofimplications of using either model.

The most important reason for turning off auto-commit is that you may want tkeep multiple ResultSets open, which you cannot do easily if auto-commit is turned on. When you commit one Statement, it closes open ResultSets that belong to other Statements in the connection. Working in auto-commit mode may not

cape Developer’s Guide

Page 153: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

The JDBC Connection and Transaction Model 6-5

R-and

able

give you enough control over keeping multiple ResultSets open. For a detailed example, see “ResultSets and Auto-Commit” on page 6-11.

NOTE: This behavior is mandated by the JDBC standard.

There are other things to be aware of when using auto-commit. They are:

• CursorsAuto-commit automatically closes cursors if you do any in-place updates or deletes (that is, an update or delete statement with a “WHERE CURENT OF” clause). (For more information about cursors, see “SQL-J JDBC ResultSet/Cursor Mechanisms” on page 6-7.) This means you can-not work with updatable cursors in auto-commit mode.

• Database-side JDBC Methods (methods using nested connections)You cannot execute methods within SQL-J statements if those methods perform a commit or rollback on the current connection. Since in the auto-commit mode all SQL-J statements are implicitly committed, Cloud-scape silently turns off auto-commit during execution of database-side methods and turns it back on when the method completes.

Methods that use nested connections are not permitted to turn auto-com-mit on or off or to commit or roll back.

• Table-level locking and the SERIALIZABLE isolation levelWhen an application uses table-level locking and the SERIALIZABLE isolation level, all statements that access tables hold at least shared table locks. Shared locks prevent other transactions that update data from accessing the table. A transaction holds a lock on a table until the transac-tion commits. So even a SELECT statement holds a shared lock on a tuntil its connection commits and a new transaction begins.

Table 6-1 Summary of Application Behavior with Auto-Commit On or Off

TopicAuto-Commit On Auto-Commit Off

Transactions Each state-ment is a separate transaction.

Commit() or roll-back() begins a transaction.

Database-side JDBC methods (methods using nested connections)

Auto-com-mit is silently turned off.

Works (no explicit commits or roll-backs are allowed).

Cloudscape Version 3.0

Page 154: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-6

a ent

and ptions,

Turning Off Auto-Commit

You can disable auto-commit with a URL attribute (see “Turning Off Auto-Commit” on page 2-24) or with the Connection class’s setAutoCommit method.

-- using the URL attribute

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:toursDB;autocommit=false");

-- using the JDBC setAutoCommit method

conn.setAutoCommit(false);

Explicitly Closing Statements, ResultSets, and Connections

You should explicitly close Statements, ResultSets, and Connections when you no longer need them. Connections to Cloudscape are resources external to an application, and the garbage collector will not close them automatically.

For example, close a Statement object using its close method; close a Connection object using its close method.

Statement vs. Transaction Runtime Rollback

When an SQL-J statement generates an exception, this exception results in runtime rollback. A runtime rollback is a system-generated rollback of a statemor transaction by Cloudscape, as opposed to an explicit rollback call from your application.

Extremely severe exceptions, such as disk-full errors, shut down the system,the transaction is rolled back when the database is next booted. Severe exce

Updatable cursors Does not work.

Works.

Multiple connections accessing the same data

Works. Works. Lower concurrency when applications use SERIALIZABLE isolation mode and table-level locking.

Table 6-1 Summary of Application Behavior with Auto-Commit On or Off

TopicAuto-Commit On Auto-Commit Off

cape Developer’s Guide

Page 155: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J and JDBC ResultSet/Cursor Mechanisms 6-7

e

a t o ent

such as deadlock, cause transaction rollback; Cloudscape rolls back all changes since the beginning of the transaction and implicitly begins a new transaction. Less severe exceptions, such as syntax errors, result in statement rollback; Cloudscape rolls back only changes made by the statement that caused the error. The application developer can insert code to explicitly roll back the entire transaction if desired.

The severity level of an SQLException, which is documented in COM.cloudscape.types.JBMSExceptionSeverity, is provided by the getErrorCode call. See “Working with Cloudscape SQLExceptions in an Application” on pag6-34 for more information.

SQL-J and JDBC ResultSet/Cursor MechanismsA cursor provides you with the ability to step through and process the rows inResultSet one by one. A java.sql.ResultSet object constitutes a cursor. You do noneed to use a language construct, such as SQL-92’s DECLARE CURSOR, twork with cursors in a Java application. In Cloudscape, any SELECT statemgenerates a cursor.

• “Simple Non-Updatable ResultSets” on page 6-7

• “Updatable Cursors” on page 6-8

• “ResultSets and Auto-Commit” on page 6-11

• “Scrolling Insensitive ResultSets” on page 6-12

Simple Non-Updatable ResultSets

Here is an excerpt from a sample JDBC application that generates a ResultSet with a simple SELECT statement and then processes the rows.

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:toursDB");

Statement s = conn.createStatement();

//note that autocommit is on--it’s on by default in JDBC

ResultSet rs = s.executeQuery(

"SELECT group_id, fixed_rate, number_seats FROM FlightBookings");

/** a standard JDBC 1.2 ResultSet. It maintains a cursor that points

Cloudscape Version 3.0

Page 156: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-8

* to the current row of data. The cursor moves down one

* row each time the method next() is called.

* You can scroll one way only--forward--with the next()

* method.

* When auto-commit is on, after

* you reach the last row the statement is considered completed

* and the transaction is committed.

*/

/* here we are scrolling through the result set

with the next() method.*/

while (rs.next()) {

// processing the rows

int gid = rs.getInt("GROUP_ID");

BigDecimal cost = rs.getBigDecimal("FIXED_RATE");

int number_seats = rs.getInt("NUMBER_SEATS");

System.out.println(gid + "; per seat rate: " + cost +

"; total cost: " +

cost.multiply(new BigDecimal(

(double)number_seats)).setScale(2));

}

rs.close();

// we can’t use the commit statement when autocommit is on.

// once we’ve iterated through the last row, the statement

// commits automatically

//conn.commit();

s.close();

Updatable Cursors

Cursors are read-only by default. For a cursor to be updatable, you must specify SELECT . . . FOR UPDATE. Use FOR UPDATE only when you will be modifying rows to avoid excessive locking of tables.

• “Requirements for Updatable Cursors” on page 6-9

• “Naming or Accessing the Name of a Cursor” on page 6-9

• “Updatable Cursors and Cloudconnector” on page 6-9

• “Extended Updatable Cursor Example” on page 6-10

cape Developer’s Guide

Page 157: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J and JDBC ResultSet/Cursor Mechanisms 6-9

u

erate ame

rder

Requirements for Updatable Cursors

Only specific SELECT statements—simple accesses of a single table—allow yoto update or delete rows as you step through them.

For more information, see “SELECT statement” on page 1-106 and “FOR UPDATE clause” on page 1-78 of the Cloudscape Reference Manual.

Naming or Accessing the Name of a Cursor

There is no SQL-J language command to assign a name to a cursor. You can usethe JDBC setCursorName method to assign a name to a ResultSet that allows positioned updates and deletes. You assign a name to a ResultSet with the setCursorName method of the Statement interface. You assign the name to a cursor before executing the Statement that will generate it.

Statement s3 = conn.createStatement();

// name the statement so we can reference the result set

// it generates

s3.setCursorName("UPDATABLESTATEMENT");

// we will be able to use the following statement later to access

// the current row of the cursor

PreparedStatement ps2 = conn.prepareStatement(

"UPDATE FlightBookings SET number_seats = ? " +

"WHERE CURRENT OF UPDATABLESTATEMENT");

More typically, you do not assign a name to the cursor, but let the system genone for you automatically. You can determine the system-generated cursor nof a ResultSet generated by a SELECT statement using the ResultSet class’s getCursorName method.

PreparedStatement ps2 = conn.prepareStatement(

"UPDATE FlightBookings SET number_seats = ? WHERE CURRENT OF "+

otherResult.getCursorName());

Updatable Cursors and Cloudconnector

When using Cloudconnector, turn off the server’s prefetching and caching in oto work with updatable cursors. For more information, see the Cloudscape Server and Administration Guide.

Cloudscape Version 3.0

Page 158: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-10

Extended Updatable Cursor Example

String URL = "jdbc:cloudscape:toursDB";

// turn off pre-fetching and catching on the

// database Connection URL if connecting to Cloudconnector

if (CloudconnectorClient)

URL += "&weblogic.t3.cacheRows=0";

Connection conn = DriverManager.getConnection(

URL);

// autocommit must be turned off for updatable cursors

conn.setAutoCommit(false);

int anygroup = 2;

Statement s3 = conn.createStatement();

// name the statement so we can reference the result set

// it generates

s3.setCursorName("UPDATABLESTATEMENT");

//Updatable statements have some requirements

ResultSet Updatable = s3.executeQuery(

"SELECT group_id, fixed_rate, number_seats FROM FlightBookings "+

"FOR UPDATE of number_seats");

// we need a separate statement to do the update

PreparedStatement ps2 = conn.prepareStatement("UPDATE FlightBookings "+

"SET number_seats = ? WHERE CURRENT OF UPDATABLESTATEMENT");

while (Updatable.next()) {

int thegroup = Updatable.getInt("GROUP_ID");

int ns = Updatable.getInt("NUMBER_SEATS");

if (thegroup < anygroup) {

// if the current row meets our criteria,

// update the updatable column in the row

ps2.setInt(1, 5);

ps2.executeUpdate();

System.out.println("Updating number_seats in FlightBookings"

" table for group number " + thegroup);

}

}

Updatable.close();

s3.close();

ps2.close();

conn.commit();

cape Developer’s Guide

Page 159: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J and JDBC ResultSet/Cursor Mechanisms 6-11

ResultSets and Auto-Commit

This example demonstrates how auto-commit can affect the behavior of a ResultSet.

// for this example, autocommit must be turned off

// since we will be executing

// one statement while another one is still open

conn.setAutoCommit(false);

// we will use the following statement to perform an action

// while scrolling through a different result set

PreparedStatement ps = conn.prepareStatement(

"SELECT City.getName(), budget FROM groups, Cities "+

"WHERE groups.city_id = Cities.city_id " +

"AND group_id = ?");

Statement s2 = conn.createStatement();

int bookingcount = 0;

ResultSet outerRs;

ResultSet innerRs;

/**

* When auto-commit is on, after

* you reach the last row the statement is considered completed

* and the transaction is committed.

* If autocommit is on, executing some other statement within the

* current connection will automatically close

* this ResultSet/Cursor.

*/

outerRs = s2.executeQuery(

"SELECT group_id, fixed_rate, number_seats FROM FlightBookings");

while (outerRs.next()) {

bookingcount++;

BigDecimal threshold = new BigDecimal(950.00).setScale(2);

BigDecimal cost = outerRs.getBigDecimal("FIXED_RATE");

cost.setScale(2);

if (cost.compareTo(threshold) == 1) {

//for big spenders, print out some group information

// set the value of the parameter for the prepared statement

ps.setInt(1, outerRs.getInt("GROUP_ID"));

// get a new result set

innerRs = ps.executeQuery();

//should return a single row

Cloudscape Version 3.0

Page 160: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-12

innerRs.next();

System.out.println(innerRs.getString(1) + ", " +

innerRs.getBigDecimal("BUDGET").setScale(2));

//if autocommit were on, the outer result set would

//now be closed, and access the next row would throw

// an exception!

innerRs.close();

}

}

outerRs.close();

conn.commit();

s2.close();

ps.close();

Scrolling Insensitive ResultSets

JDBC 2.0 adds a new kind of ResultSet, one that allows you to scroll in either direction or to move the cursor to a particular row.

Cloudscape implements only scrolling insensitive ResultSets that are not updatable.

// autocommit doesn’t have to be off for this type of result set, but

// it’s a very good idea. If we accidentally scroll past the last row,

// the statement commits and the result set is closed.

//

conn.setAutoCommit(false);

Statement s4 = conn.createStatement(

ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

ResultSet scroller= s4.executeQuery(

"SELECT group_id, fixed_rate FROM FlightBookings " +

"ORDER BY fixed_rate DESC");

if (scroller.first())

System.out.println("The largest rate for a flight is " +

scroller.getBigDecimal("FIXED_RATE"));

else

System.out.println("There are no rows.");

scroller.beforeFirst();

scroller.afterLast();

scroller.absolute(3);

cape Developer’s Guide

Page 161: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Locking, Concurrency, and Isolation 6-13

’s you e

if (!scroller.isAfterLast()) {

System.out.println("The third highest rate for a flight is " +

scroller.getBigDecimal("FIXED_RATE") +

" held by by group number = " + scroller.getInt("GROUP_ID"));

}

if (scroller.isLast()) {

System.out.println("There are only three rows.");

}

if (scroller.last())

System.out.println("The smallest fixed_rate in the table is: " +

scroller.getBigDecimal("FIXED_RATE"));

scroller.close();

conn.commit();

s4.close();

conn.close();

System.out.println("Committed transaction and closed connection");

Locking, Concurrency, and IsolationThis section discusses topics pertinent to multi-user systems, in which concurrency is important. Cloudscape is configured by default to work well for multi-user systems. For single-user systems, you may want to tune your system so that it uses fewer resources; see “Lock Granularity” on page 6-17.

• “Isolation Levels and Concurrency” on page 6-13

• “Configuring Isolation Levels” on page 6-16

• “Lock Granularity” on page 6-17

• “Types and Scope of Locks in Cloudscape Systems” on page 6-18

• “Deadlocks” on page 6-22

Isolation Levels and Concurrency

Cloudscape provides two transaction isolation levels. Setting the transaction isolation level for a connection allows a user to specify how severely the usertransaction should be isolated from other transactions. For example, it allowsto specify whether transaction A is allowed to make changes to data that havbeen viewed by transaction B before transaction B has committed.

Cloudscape Version 3.0

Page 162: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-14

ich

A connection determines its own isolation level, so JDBC provides an application with a way to specify a level of transaction isolation. It specifies five levels of transaction isolation. The higher the transaction isolation, the more care is taken to avoid conflicts; avoiding conflicts sometimes means locking out transactions. Lower isolation levels thus allow greater concurrency.

Inserts, updates, and deletes always behave the same no matter what the isolation level is. Only the behavior of select statements varies.

JDBC defines the following isolation levels:

• TRANSACTION_READ_UNCOMMITTED (ANSI level 0)

Not supported in Cloudscape Version 3.0

• TRANSACTION_READ_COMMITTED (ANSI level 1)

• TRANSACTION_REPEATABLE_READ (ANSI level 2)

Not supported in Cloudscape Version 3.0

• TRANSACTION_SERIALIZABLE (ANSI level 3)

These levels allow you to avoid particular kinds of transaction anomalies, whare described in Table 6-2.

Table 6-2 Transaction Anomalies

Example

Dirty Reads

A dirty read happens when a transaction reads data that is being modified by another transaction that has not yet com-mitted.

Transaction A begins.

UPDATE Flights SET miles = 7 WHERE flight_id = ’AA1111’

Transaction B begins.

SELECT * FROM Flights

(Transaction B sees data updated by trans-action A. Those updates have not yet been committed.)

cape Developer’s Guide

Page 163: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Locking, Concurrency, and Isolation 6-15

er

s.

emas

The transaction isolation level is a way of specifying whether these transaction anomalies are allowed. The transaction isolation level thus affects the quantity of data locked by a particular transaction. In addition, a DBMS’s locking schemamay also affect whether these anomalies are allowed. A DBMS may lock eiththe entire table or only specific rows in order to prevent transaction anomalie

Table 6-3 shows which anomalies are possible under the various locking schand isolation levels.

Non-Repeatable Reads

Non-repeatable reads happen when a query returns data that would be different if the query were repeated within the same transaction. Non-repeatable reads can occur when other transactions are modifying data that a transaction is read-ing.

Transaction A begins.

SELECT * FROM Flights WHERE flight_id = ’AA1111’

Transaction B begins.

UPDATE Flights SET miles = 7 WHERE flight_id = ’AA1111’

(Transaction B updates rows viewed by transaction A before transaction A com-mits.)

If Transaction A issues the same SELECT statement, the results will be different.

Phantom Reads

Records that appear in or disappear from a set being read by another transaction. Phantom reads can occur when other transactions insert or delete rows that would satisfy the WHERE clause of another transaction’s statement.

Transaction A begins.

SELECT * FROM Flights WHERE flight_id BETWEEN ’AA1112’ AND ’AA1115’

Transaction B begins.

INSERT INTO Flights VALUES ’AA1114’

Transaction B inserts a row that would satisfy Transaction A’s query if it were issued again.

Table 6-3 When Transaction Anomalies Are Possible

Isolation Level Table-Level Locking Row-Level Locking

TRANSACTION_READ_UNCOMMITTED Dirty reads, non-repeatable reads, and phantom reads possible

Dirty reads, nonrepeatable reads, and phan-tom reads possi-ble

TRANSACTION_READ_COMMITTED Nonrepeatable reads and phan-tom reads possi-ble

Nonrepeatable reads and phan-tom reads possi-ble

Table 6-2 Transaction Anomalies

Example

Cloudscape Version 3.0

Page 164: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-16

ted”

ion

.

In Cloudscape Version 3.0, the following java.sql.Connection isolation levels are available:

• TRANSACTION_SERIALIZABLEWithin the Cloudscape system (not JDBC), called SERIALIZABLE

SERIALIZABLE means that Cloudscape treats the transactions as if they occurred serially (one after the other) instead of concurrently. Cloudscape issues locks to prevent all the transaction anomalies listed in Table 6-2 on page 6-14 from occurring. The type of lock it issues is sometimes called a range lock. (You will learn more about this in “range locks” on page 6-19.)

• TRANSACTION_READ_COMMITTEDWithin the Cloudscape system (not JDBC), called READ_COMMITTED or READ COMMITTED

READ_COMMITTED means that Cloudscape issues locks to prevent only dirty reads, not all the transaction anomalies listed in Table 6-2 on page 6-14.

READ_COMMITTED is the default isolation level for transactions.

Attempting to set isolation to another level results in a “Feature not implemen(SQLState XJZZZ) SQLException. Cloudscape will offer more isolation level options in future releases.

Configuring Isolation Levels

If a connection does not specify its isolation level, it inherits the default isolatlevel for the Cloudscape system, which you set with the cloudscape.language.defaultIsolationLevel property. The default value of that property is READ_COMMITTED. When set to READ_COMMITTED, the connection inherits the TRANSACTION_READ_COMMITTED isolation levelWhen set to SERIALIZABLE, the connection inherits the TRANSACTION_SERIALIZABLE isolation level.

TRANSACTION_REPEATABLE_READ Phantom reads not possible because entire table is locked

Phantom reads possible

TRANSACTION_SERIALIZABLE None None

Table 6-3 When Transaction Anomalies Are Possible

Isolation Level Table-Level Locking Row-Level Locking

cape Developer’s Guide

Page 165: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Locking, Concurrency, and Isolation 6-17

t

it

lti-read-

ay to

,

s”.

here after e, or -level ore

To override the inherited default, use the methods of java.sql.Connection.

In addition, a connection can change the isolation level of the transaction within an SQL-J statement. For more information, see “SET TRANSACTION ISOLATION LEVEL statement” on page 1-114 of the Cloudscape Reference Manual. The AT ISOLATION clause changes the isolation level for the currenstatement only. See “AT ISOLATION clause” on page 1-24 of the Cloudscape Reference Manual.

With the exception of using the AT ISOLATION clause, changing the isolationlevel commits the current transaction.

NOTE: For information about how to choose a particular isolation level, see Tuning Cloudscape.

Lock Granularity

Cloudscape can be configured for table-level locking. With table-level locking, when a transaction locks data in order to prevent any transaction anomalies,always locks the entire table, not just those rows being accessed.

By default, Cloudscape is configured for row-level locking. Row-level locking uses more memory but allows greater concurrency, which works better in muuser systems. Table-level locking works best with single-user applications or only applications.

You typically set lock granularity for the entire Cloudscape system, not for a particular application. However, at compilation time or runtime, Cloudscape mescalate the lock granularity for a particular transaction from row-level lockingtable-level locking for performance reasons. You have some control over thethreshold at which this occurs. For information on turning off row-level lockingsee “cloudscape.storage.rowLocking” on page 5-64 in Tuning Cloudscape. For more information about automatic lock escalation, see “About the Optimizer’sSelection of Lock Granularity” on page 4-21 and “Transaction-Based Lock Escalation” on page 4-28 in Tuning Cloudscape. For more information on tuning your Cloudscape system, see Chapter 3, “Tuning Databases and Application

You can override row-level locking for individual tables. Because row-level locking uses more resources, it is useful to be able to use table-level locking wpossible. For example, you may have a table that you know will be read-only you populate it, or one that will always be accessed by only one user at a timyou want to ensure that only one user accesses it at a time. You override rowlocking with the SET LOCKING clause when you create or alter a table. For m

Cloudscape Version 3.0

Page 166: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-18

n -

on e

e ed en

,

ot

sin-os-

1

information, see “CREATE TABLE statement” on page 1-48 in the Cloudscape Reference Manual.

NEW: Overriding row-level locking for specific tables is new in Version 3.0.

Types and Scope of Locks in Cloudscape Systems

Types of Locks

When a statement modifies data, its transaction holds an exclusive lock on data that prevents other transactions from accessing the data. This lock remains iplace until the transaction holding the lock issues a commit or rollback. Tablelevel locking lowers concurrency in a multi-user system.

When a statement reads data without making any modifications, its transactiobtains a shared lock on the data. Another transaction that tries to read the samdata is permitted to read, but a transaction that tries to update the data will bprevented from doing so until the shared lock is released. How long this sharlock is held depends on the isolation level of the transaction holding the lock.Transactions using the READ COMMITTED isolation level release the lock whthe transaction steps through to the next row. Transactions using the SERIALIZABLE isolation level hold the lock until the transaction is committedso even a SELECT can prevent updates if a commit is never issued.

Scope of Locks

The amount of data locked by a statement can vary.

• table locksA statement may lock the entire table.

Table-level locking systems always lock entire tables.

Row-level locking systems may lock entire tables if the statement’s WHERE clause can’t use an index. For example, UPDATES that cannuse an index lock the entire table.

Row-level locking systems may lock entire tables if a high number of gle-row locks would be less efficient than a single table-level lock. Choing table-level locking instead of row-level locking for performance reasons is called lock escalation. (For more information about this topic, see “About the Optimizer’s Selection of Lock Granularity” on page 4-2

cape Developer’s Guide

Page 167: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Locking, Concurrency, and Isolation 6-19

ow the

and “Transaction-Based Lock Escalation” on page 4-28 in Tuning Cloud-scape.)

• single-row locksA statement may lock only a single row at a time.

This section applies only to row-level locking systems.

For READ COMMITTED isolation, Cloudscape treats rows as cursors for SELECT statements. It locks rows only as the application steps through the rows in the result. The current row is locked. The row lock is released when the application goes to the next row. (For SERIALIZABLE isolation, however, Cloudscape locks the whole set before the application begins stepping through. See “range locks” on page 6-19.)

Cloudscape locks single rows for INSERT statements, holding each runtil the transaction is committed. (If there is an index associated withtable, the previous key is also locked.)

• range locksA statement may lock a range of rows (range lock).

This section applies only to row-level locking systems.

For either isolation level, Cloudscape locks all the rows in the result plus an entire range of rows for updates or deletes.

For the SERIALIZABLE isolation level, Cloudscape locks all the rows in the result plus an entire range of rows in the table for SELECTs to prevent nonrepeatable reads and phantoms.

For example, if a SELECT statement specifies rows in the HotelAvailabil-ity table where the booking_date is BETWEEN two dates, the system may lock more than just the actual rows it returns in the result. It also must lock the entire range of rows between those two dates to prevent another transaction from inserting, deleting, or updating a row within that range.

An index must be available for a range lock. If one is not available, Cloud-scape locks the entire table.

Cloudscape Version 3.0

Page 168: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-20

is

me

Notes on Locking

In addition to the locks already described, foreign key lookups require briefly held shared locks on the referenced table (row or table, depending on the configuration).

The table and examples in this section do not take performance-based lock escalation into account. Remember that the system may choose table-level locking for performance reasons.

Bulk Fetch and Row Locks

For SELECTs in a read committed environment, Cloudscape in theory locks a single row at a time—the row being looked at currently by the application. Thisn’t actually true when bulk fetch is turned on. Bulk fetch is a performance enhancement that means that Cloudscape fetches more than one row at a tifrom the underlying conglomerate (index or table). By default, Cloudscape fetches 16 rows at a time.

Table 6-4 Possible Types and Scopes of Locking

Transaction Isolation Level Table-Level Locking Row-Level Locking

Read Committed SELECT statements get a shared lock on the entire table. The locks are released when the user closes the ResultSet.

Other statements get exclu-sive locks on the entire table, which are released when the transaction com-mits.

SELECTs lock and release single rows as the user steps through the ResultSet.

UPDATEs and DELETEs get exclusive locks on a range of rows.

INSERT statements get exclusive locks on single rows (and sometimes on the preceding rows).

Serializable SELECT statements get a shared lock on the entire table.

Other statements get exclu-sive locks on the entire table, which are released when the transaction com-mits.

SELECT statements get shared locks on a range of rows.

UPDATE and DELETE statements get exclusive locks on a range of rows.

INSERT statements get exclusive locks on single rows (and sometimes on the preceding rows).

cape Developer’s Guide

Page 169: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Locking, Concurrency, and Isolation 6-21

When bulk fetch is used, Cloudscape actually locks a different row from the one being looked at.

Some applications may need to rely on the current row being locked because they may go on to update the row currently being looked at. The most sensible thing in such a situation is for an application to use an updatable cursor, since bulk fetch is automatically turned off in that situation. Otherwise, applications could do one of the following:

• turn off bulk fetch (see “bulkFetch” on page 6-3 in Tuning Cloudscape)

• use a serializable isolation level.

Locking Examples

• “Row-Level Locking, TRANSACTION_READ_COMMITTED” on page6-21

• “Row-Level Locking, TRANSACTION_SERIALIZABLE” on page 6-22

No examples are provided for table-level locking, because the entire table is always locked.

Row-Level Locking, TRANSACTION_READ_COMMITTED

-- Cloudscape locks and releases the rows as

-- the user steps through them

SELECT hotel_id, booking_date, rooms_taken

FROM HotelAvailability

-- (no index on miles)

-- Cloudscape locks and releases the rows as

-- the user steps through them

SELECT flight_id

FROM Flights

WHERE miles > 4000

-- Cloudscape locks but does not release the rows as

-- the user steps through them

SELECT hotel_id, booking_date, rooms_taken

FROM HotelAvailability FOR UPDATE

-- Cloudscape locks the entire range right away

-- and does not release them until the commit

UPDATE HotelAvailability

SET rooms_taken = 4

WHERE hotel_id = 16

AND booking_date BETWEEN ’1999-01-10’ AND ’1999-01-15’

Cloudscape Version 3.0

Page 170: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-22

-- Cloudscape locks the row being inserted until commit

-- it gets a very brief lock on the Hotels table

-- (a foreign key references Hotels)

INSERT INTO HotelAvailability

VALUES (201, ’1999-05-99’, 10)

-- Cloudscape locks the range of rows

-- until commit

DELETE FROM HotelAvailability

WHERE booking_date < CURRENT_DATE

Row-Level Locking, TRANSACTION_SERIALIZABLE

-- Cloudscape locks the entire range (most likely

-- the entire table)

SELECT hotel_id, booking_date, rooms_taken

FROM HotelAvailability

-- (no index on miles)

-- Cloudscape locks the entire table

SELECT flight_id

FROM Flights

WHERE miles > 4000

-- Cloudscape locks the entire range until commit

UPDATE HotelAvailability

SET rooms_taken = 4

WHERE hotel_id = 16

AND booking_date BETWEEN ’1999-01-10’ AND ’1999-01-15’

-- Cloudscape locks the row being inserted until commit

-- It gets a very brief lock on the Hotels table

-- (foreign key reference)

INSERT INTO HotelAvailability

VALUES (201, ’1999-05-99’, 10)

-- Cloudscape locks the range of rows being deleted

-- until commit

DELETE FROM HotelAvailability

WHERE booking_date < CURRENT_DATE

Deadlocks

In a database, a deadlock is a situation in which two or more transactions are waiting for one another to give up locks.

cape Developer’s Guide

Page 171: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Locking, Concurrency, and Isolation 6-23

25

gic;

For example, Transaction A may hold a lock on some rows in the Accounts table and needs to update some rows in the Orders table to finish. Transaction B holds locks on those very rows in the Orders table but needs to update the rows in the Accounts table held by Transaction A. Transaction A cannot complete its transaction because of the lock on Orders. Transaction B cannot complete its transaction because of the lock on Accounts. All activity comes to a halt and remains at a standstill forever unless the DBMS detects the deadlock and aborts one of the transactions.

Figure 6-1 A deadlock.

• “Avoiding Deadlocks” on page 6-23

• “Deadlock Detection” on page 6-24

• “Configuring Deadlock Detection and Lock Wait Timeouts” on page 6-

• “Debugging Deadlocks” on page 6-27

Avoiding Deadlocks

Using both row-level locking and the TRANSACTION_READ_COMMITTED isolation level makes it likely that you will avoid deadlocks (both settings are Cloudscape defaults). However, deadlocks are still possible. Cloudscape application developers can avoid deadlocks by using consistent application lofor example, transactions that access Accounts and Orders should always access the tables in the same order. That way, in the scenario described above, Transaction B simply waits for transaction A to release the lock on Orders before it begins. When transaction A releases the lock on Orders, Transaction B can proceed freely.

transaction A transaction B

Orders Accounts

A needs a lockon Accountsin order tofinish.

B needs a lockon Ordersin order tofinish.

Cloudscape Version 3.0

Page 172: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-24

k n is locks or ust

ption e the evel has

(an

k

ing

tion. aited

Another tool available to you is the LOCK TABLE statement. A transaction can attempt to lock a table in exclusive mode when it starts to prevent other transactions from getting shared locks on a table. For more information, see “LOCK TABLE statement” on page 1-91 in the Cloudscape Reference Manual.

Deadlock Detection

When a transaction waits more than a specific amount of time to obtain a loc(called the deadlock timeout), Cloudscape can detect whether the transactioinvolved in a deadlock. When Cloudscape analyzes such a situation for deadit tries to determine how many transactions are involved in the deadlock (twomore). Usually aborting one transaction breaks the deadlock. Cloudscape mpick one transaction as the victim and abort that transaction; it picks the transaction that holds the fewest number of locks as the victim, on the assumthat that transaction has performed the least amount of work. (This may not bcase, however; the transaction may have recently been escalated from row-llocking to table locking and thus hold a small number of locks even though itdone the most work.)

When Cloudscape aborts the victim transaction, it receives a deadlock error SQLException with an SQLState of 40001). The error message gives you the transaction IDs, the statements, and the status of locks involved in a deadlocsituation.

ERROR 40001: A lock could not be obtained due to a deadlock,

cycle of locks & waiters is:

Lock : TABLE, X, FLIGHTS, Tablelock

Victim XID : 1221, APP,

update flights set miles = miles + 1

Granted XID : 1222

Lock : TABLE, X, FLIGHTAVAILABILITY, Tablelock

Waiting XID : 1222, APP, update flightavailability set

economy_seats_taken = 1

0

Granted XID : 1221

For information on configuring when deadlock checking occurs, see “ConfigurDeadlock Detection and Lock Wait Timeouts” on page 6-25.

NEW: Beginning in Version 3.0, Cloudscape performs actual deadlock detecIn previous versions, Cloudscape detected only when a transaction wfor a lock for more than a specified amount of time. In such a situationCloudscape assumed that a deadlock had occurred. It aborted any transaction that waited longer than the deadlock timeout.

cape Developer’s Guide

Page 173: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Locking, Concurrency, and Isolation 6-25

s any

r for

NOTE: Deadlocks are detected only within a single database. Deadlocks across multiple databases are not detected. Non-database deadlocks caused by Java synchronization primitives are not detected by Cloudscape.

Lock Wait Timeouts

Even if a transaction is not involved in a deadlock, it may have to wait a considerable amount of time to obtain a lock because of a long-running transaction or transactions holding locks on the tables it needs. In such a situation, you may not want a transaction to wait indefinitely. Instead, you may want the waiting transaction to abort, or time out, after a reasonable amount of time, called a lock wait timeout. (For information about configuring the lock wait timeout, see “Configuring Deadlock Detection and Lock Wait Timeouts” on page 6-25.)

NEW: The ability to configure the lock wait timeout is new in Version 3.0.

Configuring Deadlock Detection and Lock Wait Timeouts

You configure the amount of time a transaction waits before Cloudscape doedeadlock checking with the cloudscape.locks.deadlockTimeout property. You configure the amount of time a transaction waits before timing out with the cloudscape.locks.waitTimeout property. When configuring your database or system, you should consider these properties together. For example, in ordeany deadlock checking to occur, the cloudscape.locks.deadlockTimeout property must be set to a value lower than the cloudscape.locks.waitTimeout property. If it is set to a value equal to or higher than the cloudscape.locks.waitTimeout, the transaction times out before Cloudscape does any deadlock checking.

By default, cloudscape.locks.waitTimeout is set to 180 seconds. -1 is the equivalent of no wait timeout. This means that transactions never time out, although Cloudscape may choose a transaction as a deadlock victim.

Figure 6-2, Figure 6-3, and Figure 6-4 show some example configurations.

Cloudscape Version 3.0

Page 174: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-26

Figure 6-2 One possible configuration: deadlock checking occurs when a transaction has waited 30 seconds; no lock wait timeouts occur.

Figure 6-3 Another typical configuration: deadlock checking occurs after a transaction has waited 60 seconds for a lock; after 90 seconds, the transaction times out and is rolled back.

seconds waiting to obtain a lock

deadlockTimeout=30Transactions arenever abortedunless they are selected as thevictim when deadlocksare checked.

I've waited30 seconds. Am I deadlocked?If not, keep waiting until Ican obtain locks (or forever).

locksWaitTimeout=-1(infinite)

seconds waiting to obtain a lock

locksWaitTimeout=90

deadlockTimeout=60

I've been waiting60 seconds.Am I deadlockedwith anybody?If not, keep waiting.

I've waited90 seconds. Abort me(I'll try again later).

cape Developer’s Guide

Page 175: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with Multiple Connections to a Single Database 6-27

e

Figure 6-4 A configuration in which no deadlock checking occurs: transactions time out after they have waited 50 seconds. No deadlock checking occurs.

Debugging Deadlocks

If deadlocks are happening frequently in your multi-user system with a particular application, you may need to do some debugging. Cloudscape provides a VTI class to help you in this situation. For information, see the Cloudscape Server and Administration Guide.

Working with Multiple Connections to a Single Database

• “Deployment Options and Threading and Connection Modes” on pag6-28

• “Multi-User Database Access” on page 6-29

• “Multiple Connections from a Single Application” on page 6-30

seconds waiting to obtain a lock

deadlockTimeout=60

No deadlock checkingoccurs; waitingtransactionsalways time out.

I've waited50 seconds. Abort me(I'll try again later).

locksWaitTimeout=50

Cloudscape Version 3.0

Page 176: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-28

loud-

.

Deployment Options and Threading and Connection Modes

A database can be available to multiple connections in the following situations:

• Multiple applications access a single database (possible only when Cscape is running inside a server framework).

• A single application has more than one Connection to the same database

The way you deploy Cloudscape affects the ways applications can use multi-threading and connections, as shown in Table 6-5.

Table 6-5 Threading and Connection Modes

Embedded Server

Multi-Threaded

From an application, using a single Connection to a Cloud-scape database and issuing requests against that connec-tion in multiple threads.

Supply a single Connection object to separate threads. Cloudscape ensures that only one operation is applied at a time for consistency.

Note that committing a trans-action commits all statements open against a single connec-tion. For more information, see “Transactions” on page 6-3.

Server frameworks such as Cloudcon-nector and RmiJdbc can automatically multi-thread opera-tions. Allowing Cloudconnector to multi-thread does not affect transaction control, which is handled by the source application.

Remote client appli-cations can multi-thread if desired.

cape Developer’s Guide

Page 177: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with Multiple Connections to a Single Database 6-29

Multi-User Database Access

Multi-user database access is possible if Cloudscape is running inside a server framework.

If more than one client application tries to modify the same data, the application that gets the table first gets the lock on the data (either specific rows or the entire table). The second application has to wait until the first application commits or rolls back the transaction in order to access the data. If two applications are only querying and not modifying data, they can both access the same data at the same time because they can each get a shared lock. For more information, see “Locking, Concurrency, and Isolation” on page 6-13.

Multi-Connection

From an application, using multiple connections to a Cloudscape database and issuing requests against those connections on multiple threads.

(You must have a multi-user license to have more than one connection to Cloudscape.)

Create individual connec-tions within a single applica-tion and use the appropriate connection for each JDBC request. The connections can all be to the same database, or can be to different databases in the same Cloudscape sys-tem.

Cloudconnector and RmiJdbc always manage multiple connections.

Remote client appli-cations can establish the multiple connec-tions desired.

Multi-User

Multiple applications access-ing the same Cloudscape database. Each user applica-tion has its own connection or connections to the database.

Not possible. Only one appli-cation can access a database at a time, and only one appli-cation can access a specific system at a time.

In the current release, Cloud-scape may not prevent multi-ple applications from concurrently accessing the same Cloudscape system, but do not allow this because such access can corrupt the databases involved.

Only one server should access a data-base at a time.

Multiple remote cli-ent applications can access the same server, and thus can access the same database at the same time through that server.

Table 6-5 Threading and Connection Modes (continued)

Embedded Server

Cloudscape Version 3.0

Page 178: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-30

do e

out

ads”

Multiple Connections from a Single Application

A single application can work with multiple Connections to the same database and assign them to different threads. The application programmer can avoid concurrency and deadlock problems in several ways:

• Use the READ_COMMITTED isolation level and turn on row-level lock-ing (the defaults).

• Beware of deadlocks caused by using more than one Connection in a sin-gle thread (the most obvious case). For example, if the thread tries toupdate the same table from two different Connections, a deadlock can occur.

• Assign Connections to threads that handle discrete tasks. For example,not have two threads update the Hotels table. Have one thread update thHotels table and a different one update the Groups table.

• If threads access the same tables, commit transactions often.

• Multi-threaded Java applications have the ability to self-deadlock witheven accessing a database, so beware of that too.

• Use nested connections to share the same lock space.

Working with Multiple Threads Sharing a Single ConnectionJDBC allows you to share a single Connection among multiple threads.

• “Pitfalls of Sharing a Connection Among Threads” on page 6-30

• “Reasons for Trying to Share a Connection or Statement Across Threon page 6-32

• “Threads Sharing a Statement: A Case Study” on page 6-33

Pitfalls of Sharing a Connection Among Threads

Here is a review of the potential pitfalls of sharing a single Connection among multiple threads:

cape Developer’s Guide

Page 179: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with Multiple Threads Sharing a Single Connection 6-31

ates.

her

avior

• Committing or rolling back a transaction closes all open ResultSet objects and currently executing Statements.

If one thread commits, it closes the Statements and ResultSets of all other threads using the same connection.

• Executing a Statement automatically closes any existing open ResultSet generated by an earlier execution of that Statement.

If threads share Statements, one thread could close another’s ResultSet.

In many cases, it is easier to assign each thread to a distinct Connection. If thread A does database work that is not transactionally related to thread B, assign them to different Connections. For example, if thread A is associated with a user input window that allows users to delete hotels and thread B is associated with a user window that allows users to view city information, assign those threads to different Connections. That way, when thread A commits, it does not affect any ResultSets or Statements of thread B.

Another strategy is to have one thread do queries and another thread do updQueries hold shared locks until the transaction commits in SERIALIZABLE isolation mode; use READ_COMMITTED instead.

Yet another strategy is to have only one thread do database access. Have otthreads get information from the database access thread.

However, in many cases, the programmer decides to have multiple threads accessing the database share a single Connection and transaction. Multiple threadsare permitted to share a Connection, Statement, or ResultSet. However, the application programmer must ensure that one thread does not affect the behof the others.

Cloudscape Version 3.0

Page 180: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-32

ws

ds to d

n

Reasons for Trying to Share a Connection or Statement Across Threads

Some programmers may share a Connection among multiple threads because they have experienced bad concurrency using separate transactions. Here are some tips for increasing concurrency:

• Use row-level locking.

• Use the READ_COMMITTED isolation level.

• Avoid queries that cannot use indexes; they require locking if all the roin the table (if only very briefly) and may block an update.

In addition, some programmers may share a statement among multiple threaavoid the overhead of each thread’s having its own. If you use stored preparestatements, threads can share the same statement from different connections using the stored prepared statement cache. For more information, see “Additional Benefits for Multiple Connections: The Stored Prepared Statement Cache” opage 3-15 in Tuning Cloudscape.

Recommended Practices

Here are some tips for avoiding unexpected behavior:

• Try not to share Statements (and their ResultSets) among threads.

• Each time a thread executes a Statement, it should process the results before relinquishing the Connection.

• Each time a thread accesses the Connection, it should consistently commit or not, depending on application protocol.

• Have one thread be the “managing” database Connection thread that should handle the higher-level tasks, such as establishing the Connec-tion, committing, rolling back, changing Connection properties such as auto-commit, closing the Connection, shutting down the database (in an embedded environment), and so on.

• Close ResultSets and Statements that are no longer needed in order to release resources.

cape Developer’s Guide

Page 181: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with Multiple Threads Sharing a Single Connection 6-33

Threads Sharing a Statement: A Case Study

This example shows what can happen if two threads try to share a single Statement.

PreparedStatement ps = conn.prepareStatement(

"UPDATE account SET balance = balance + ? WHERE id = ?");

/* now assume two threads T1,T2 are given this

java.sql.PreparedStatement object and that the following events

happen in the order shown (pseudojava code)*/

T1 - ps.setBigDecimal(1, 100.00);

T1 - ps.setLong(2, 1234);

T2 - ps.setBigDecimal(1, -500.00);

// *** At this point the prepared statement has the parameters

// -500.00 and 1234

// T1 thinks it is adding 100.00 to account 1234 but actually

// it is subtracting 500.00

T1 - ps.executeUpdate();

T2 - ps.setLong(2, 5678);

// T2 executes the correct update

T2 - ps.executeUpdate();

/* Also, the auto-commit mode of the connection may lead

to some strange behavior.*/

If it is absolutely necessary, the application can get around this problem with Java synchronization.

If the threads each obtain their own PreparedStatement (with identical text), their setXXX calls do not interfere with each other. Moreover, Cloudscape is able to share the same compiled query plan between the two statements; it needs to maintain only separate state information. However, there is the potential for confusion in regard to the timing of the commit, since a single commit commits all the statements in a transaction.

Cloudscape Version 3.0

Page 182: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-34

Working with Cloudscape SQLExceptions in an ApplicationJDBC generates exceptions of the type java.sql.SQLException. To see the exceptions generated by Cloudscape, retrieve and process the SQLExceptions in a catch block.

Information Provided in SQLExceptions

Cloudscape provides the message, SQLState values, and error codes. Use the getSQLState and getMessage methods to view the SQLState and error messages. Use getErrorCode to see the error code. The error code defines the severity of the error and is not unique to each exception. The severity levels are described in COM.cloudscape.types.JBMSExceptionSeverity.

In addition, a single error can generate more than one SQLException. Use a loop and the getNextException method to process all SQLExceptions in the chain. In many cases, the second exception in the chain is the pertinent one.

The following example is taken from the sample application:

catch (Throwable e) {

System.out.println("exception thrown:");

errorPrint(e);

}

static void errorPrint(Throwable e) {

if (e instanceof SQLException)

SQLExceptionPrint((SQLException)e);

else

System.out.println("A non-SQL error: " + e.toString());

}

static void SQLExceptionPrint(SQLException sqle) {

while (sqle != null) {

System.out.println("\n---SQLException Caught---\n");

System.out.println("SQLState: " + (sqle).getSQLState());

System.out.println("Severity: " + (sqle).getErrorCode());

System.out.println("Message: " + (sqle).getMessage());

sqle.printStackTrace();

sqle = sqle.getNextException();

}

cape Developer’s Guide

Page 183: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with Cloudscape SQLExceptions in an Application 6-35

he

}

See also Chapter 5, “Cloudscape Exception Messages and SQL States”, in tCloudscape Reference Manual.

Applications should also check for and process java.sql.SQLWarnings, which are processed in a similar way. Cloudscape issues an SQLWarning if the create=true attribute is specified and the database already exists.

Cloudscape Version 3.0

Page 184: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Controlling Cloudscape Application Behavior

Clouds

6-36

cape Developer’s Guide

Page 185: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

I

ent.

7 Using Cloudscape as a J2EE Resource Manager

J2EE, or the Java 2 Platform, Enterprise Edition, is a new standard for development of enterprise applications; one example is Enterprise Java Beans (EJBs) with distributed capabilities.

Cloudscape Version 3.0 is a J2EE-conformant component in a distributed J2EE system. As such, it is one part of a larger system that includes, among other things, a JNDI server, a connection pool module, a transaction manager, a resource manager, and user applications. (Cloudscape also supports the JTA API, which is not a current J2EE requirement, but this functionality provides another piece of the same system.) Within this system, Cloudscape can serve as the resource manager.

For more information on J2EE and how to work in this environment, see the J2EE specification available at java.sun.com/j2ee/docs.html.

NOTE: This chapter does not show you how to use Cloudscape as a Resource Manager. Instead, it provides details specific to Cloudscape that are not covered in the specification. This information is useful to programmers developing other modules in a distributed J2EE system, not to end-user application developers.

In order to qualify as a resource manager in a J2EE system, J2EE requires these basic areas of support. These three areas of support involve implementation of APIS and are described in Chapter 8, “J2EE Compliance: Java Transaction APand javax.sql Extensions” in the Cloudscape Reference Manual.

This chapter describes the Cloudscape classes that implement the APIs andprovides some implementation-specific details.

NOTE: All of the classes described in this chapter require a JDK 1.2 environm

7-1

Page 186: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape as a J2EE Resource Manager

Clouds

7-2

• “The Classes” on page 7-2

• “How to Use Them” on page 7-2

The ClassesSee the javadoc for each class for more information.

• COM.cloudscape.core.DataSourceFactory

A factory for Cloudscape data sources. System administrators use the static methods of this class to obtain DataSource objects.

• COM.cloudscape.core.AbstractDataSource

The basic DataSource that the other classes extend. It is referenceable by a JNDI server. Contains the methods for setting DataSource properties such as setCreateDatabase, setShutdownDatabase, and set RemoteDataSourceProtocol.

• COM.cloudscape.core.BasicDataSource

Extends AbstractDataSource. Implements javax.sql.DataSource inter-face, referenceable by a JNDI server. Typically this is the object that you work with as a DataSource.

• COM.cloudscape.core.LocalConnectionPoolDataSource

Extends AbstractDataSource and implements javax.sql.ConnectionPoolDataSource. A factory for PooledConnection objects. You can obtain a LocalConnectionPoolDataSource object via a DataSourceFactory.

• COM.cloudscape.core.XaDataSource

Extends AbstractDataSource. Cloudscape’s implementation of a javax.sql.XADataSource. A factory for XAConnection objects, obtainable via a DataSourceFactory.

How to Use Them• “Getting a DataSource” on page 7-3

• “Shutting Down or Creating a Database” on page 7-3

• “Remote DataSources” on page 7-5

cape Developer’s Guide

Page 187: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

How to Use Them 7-3

he

Getting a DataSource

Normally, you can simply work with the interfaces for javax.sql.DataSource, javax.sql.ConnectionPoolDataSource, and javax.sql.XADataSource, as shown in the following examples. However, you do need to use the Cloudscape class COM.cloudscape.core.DataSourceFactory.

import COM.cloudscape.core.DataSourceFactory;

javax.sql.ConnectionPoolDataSource cpdf =

DataSourceFactory.getConnectionPoolDataSource()

javax.sql.DataSource ds = DataSourceFactory.getDataSource();

javax.sql.XADataSource xads = DataSourceFactory.getXADataSource();

Cloudscape provides three methods for a DataSource that are not part of the standard API. These methods are in COM.cloudscape.core.AbstractDataSource. They are:

• setCreateDatabase(String databaseName)

Sets a property to create a database the next time the XADataSource.getXAConection() method is called. databaseName can be a simple name or an absolute path to the database and is equivalent to the databaseName in the Cloudscape database connection URL.

• setShutdownDatabase()

Sets a property to shut down a database. Shuts down the database the next time XADataSource.getXAConnection().getConnection() method is called.

• setRemoteDataSourceProtocol

See “Remote DataSources” on page 7-5.

Shutting Down or Creating a Database

If you need to shut down or create a database, it is easiest just to work with tCloudscape-specific implementations of interfaces, as shown in the followingexamples.

javax.sql.XADataSource xads = makeXADataSource(mydb, true);

// example of setting property directory using Cloudscape’s

// XaDataSource object

Cloudscape Version 3.0

Page 188: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape as a J2EE Resource Manager

Clouds

7-4

import COM.cloudscape.core.DataSourceFactory;

import COM.cloudscape.core.XaDataSource;

import javax.sql.XADataSource;

// dbname is the database name

// if create is true, create the database if not already created

XADataSource makeXADataSource (String dbname, boolean create)

throws Throwable

{

XaDataSource xads = DataSourceFactory.getXADataSource();

// use Cloudscape’s setDatabaseName call

xads.setDatabaseName(dbname);

if (create)

xads.setCreateDatabase("create");

return xads;

}

Or, you could use reflection:

import javax.sql.DataSource

import COM.cloudscape.core.DataSourceFactory

DataSource ds = makeCloudscapeSource(mydb);

// example of using reflection to set properties

// knowledge of COM.cloudcape.core.DataSourceFactory required

DataSource makeCloudscapeDataSource (String dbname) throws Throwable

{

Class[] parameter = new Class[1];

parameter[0] = dbname.getClass();

DataSource ds = DataSourceFactory.getDataSource();

Class c1 = ds.getClass();

Method setName = c1.getMethod("setDatabaseName", parameter);

Object[] arg = new Object[1];

arg[0] = dbname;

setName.invoke(ds, arg);

return ds;

}

cape Developer’s Guide

Page 189: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

How to Use Them 7-5

You could use similar code to shut down a database.

Setting the property does not create or shut down the database. The database is not actually created or shut down until the next connection request.

Remote DataSources

XaDataSources are local only; no remote support is provided. Remote support is provided for DataSources and LocalConnectionPoolDataSources through RmiJdbc.

To create remote RmiJdbc data sources, use the method setRemoteDataSourceProtocol on the data source before getting the connection. The string argument to the method must be either:

• “rmi”

• “rmi://hostname:portnumber/”

Cloudscape Version 3.0

Page 190: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Using Cloudscape as a J2EE Resource Manager

Clouds

7-6

cape Developer’s Guide

Page 191: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

f o

8 Cloudscape and Security

• “Security Overview” on page 8-1

• “Working with User Authentication” on page 8-5

• “Users and Authorization Identifiers” on page 8-21

• “User Authorization” on page 8-23

• “Encrypting Databases on Disk” on page 8-27

• “SSL” on page 8-30

• “Notes on the Cloudscape Security Features” on page 8-31

• “User Authentication and Authorization Examples” on page 8-32

Security Overview

Features

Cloudscape can be deployed in a number of diverse ways and in a number odifferent environments. The security needs of the Cloudscape system are alsdiverse. Cloudscape supplies or supports the following optional security mechanisms:

• User authenticationCloudscape verifies user names and passwords before permitting them access to the Cloudscape system. See “Working with User Authentica-tion” on page 8-5.

8-1

Page 192: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-2

• User authorizationA means of granting specific users permission to read a database or to write to a database. See “User Authorization” on page 8-23.

• Network encryption with Secure Socket Layer (SSL)A protocol designed to guarantee privacy and integrity of messages on the wire and supported by some application servers, including Cloudconnec-tor. See “SSL” on page 8-30.

• Disk encryptionA means of encrypting Cloudscape data stored on disk. See “Encrypting Databases on Disk” on page 8-27.

Figure 8-1 Some of the Cloudscape security mechanisms at work in aclient/server environment

Connectivityframework

Cloudscape

Client application

Network

LDAP Directory Service

User authentication

Permissions to read/write data

SSL

Data notencrypted (trustedenvironment)

cape Developer’s Guide

Page 193: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Security Overview 8-3

your

hich

and

oud-r

Figure 8-2 Another Cloudscape security mechanism, disk encryption, protects data when the recipient may not know how to protect data. It is useful for databases deployed in an embedded environment.

Configuring Security for Your Environment

In most cases, you enable Cloudscape’s security features through the use ofproperties. It is important to understand the best way of setting properties for environment.

• “Configuring Security in a Client/Server Environment” on page 8-3

• “Configuring Security in an Embedded Environment” on page 8-4

Configuring Security in a Client/Server Environment

This discussion assumes a system with multiple databases and some administrative resources. For systems that have a single database and for wthere are no administrative resources, follow the instructions in “Configuring Security in an Embedded Environment” on page 8-4.

1 Configure security features as system properties.

See “System-Wide Properties” on page 1-4 in Tuning Cloudscape.

Provide administrative-level protection for the cloudscape.properties file and Cloudscape databases. For example, you can protect these filesdirectories with operating system permissions and firewalls.

2 Turn on user authentication for your system.

All users must provide valid user IDs and passwords to access the Clscape system. See “Working with User Authentication” on page 8-5 fo

Disk encryption

CloudscapeApplication

Cloudscape Version 3.0

Page 194: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-4

s-

typi- o ul me

and

is

e

re er

data-ted.

information.

If you are using Cloudscape’s built-in users, configure users for the sytem in the cloudscape.properties file. Provide the protection for this file.

3 Configure user authorization for sensitive databases in your system.

Only designated users will be able to access sensitive databases. Youcally configure user authorization with database-level properties. See“User Authorization” on page 8-23 for information. It is also possible tconfigure user authorization with system-level properties. This is usefwhen you are developing systems or when all databases have the salevel of sensitivity.

Configuring Security in an Embedded Environment

In an embedded environment, typically there is only one database per systemthere are no administrative resources to protect databases.

1 Encrypt the database when you create it.

2 Configure all security features as database-level properties.

When you do this, these properties are stored in the database (whichencrypted). See “Database-Wide Properties” on page 1-7 in Tuning Cloudscape.

3 Turn on protection for database-level properties so that they cannot boverridden by system properties.

Do this by setting the cloudscape.database.propertiesOnly property to true.

4 To prevent unauthorized users from accessing databases once they abooted, turn on user authentication for the database and configure usauthorization for the database.

See “Working with User Authentication” on page 8-5 for information.

See “User Authorization” on page 8-23 for information.

5 If you are using Cloudscape’s built-in users, configure each user as abase-level property so that user names and passwords can be encryp

Configuring Security in a Synchronization System

For information, see Cloudscape Synchronization Guide.

cape Developer’s Guide

Page 195: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with User Authentication 8-5

that

reful .

d-

m -

- ata-

Working with User Authentication• “Overview” on page 8-5

• “Enabling User Authentication” on page 8-7

• “Defining Users” on page 8-8

• “Properties Summary” on page 8-19

• “Programming Applications for Cloudscape User Authentication” on page 8-19

Overview

Cloudscape provides support for user authentication. User authentication means that Cloudscape authenticates a user’s name and password before allowing user access to the system.

Caveat for Configuring Security

Cloudscape does not come with a built-in superuser. For that reason, be cawhen configuring Cloudscape for user authentication and user authorization

1 When first working with security, work with system-level properties only so that you can easily override them if you make a mistake.

2 Be sure to create at least one valid user, and grant that user full (reawrite) access. For example, you may always want to create a user called sa with the password cloudscape while you are developing.

3 Test the authentication system while it is still configured at the systelevel. Be absolutely certain that you have configured the system correctly before setting the properties as database-level properties.

4 Before disabling system-level properties (by setting cloudscape.data-base.propertiesOnly to true), test that at least one database-level readwrite user (such as sa) is valid. If you don’t have at least one valid userthat the system can authenticate, you won’t be able to access your dbase.

Cloudscape Version 3.0

Page 196: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-6

nt vice

rties.

xternal -3

The

t r at a

When user authentication is enabled (which it is not by default), the user requesting a connection must provide a valid name and password, which Cloudscape verifies against the repository of users defined for the system. Once Cloudscape authenticates the user, it grants the user access to the Cloudscape system but not necessarily access to the database made in the connection request. In the Cloudscape system, access to a database is determined by user authorization. For information, see “User Authorization” on page 8-23.

Cloudscape allows you to provide a repository of users in a number of differeways. For example, you can hook Cloudscape up to an external directory serelsewhere in your enterprise, create your own, use Cloudscape’s simple mechanism for creating a built-in repository of users.

You can define a repository of users for a particular database or for an entiresystem, depending on whether you use system-wide or database-wide propeSee “Configuring Security for Your Environment” on page 8-3 for more information.

When Cloudscape user authentication is enabled and Cloudscape uses an edirectory service, the architecture looks something like that shown in Figure 8on page 8-6.

Figure 8-3 Cloudscape user authentication using an external service. application can be a single-user application with an embedded Cloudscape engine or a multi-user application server.

Cloudscape always runs embedded in another Java application, whether thaapplication is a single-user application or a multiple-user application server oconnectivity framework. A database can be accessed by only one application

Applicationor applicationserver

Cloudscape

External directory service

Cloudscapeuserauthentication

cape Developer’s Guide

Page 197: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with User Authentication 8-7

lti-

operty

t e er ser

time, so it is possible to deploy a system in which the application in which Cloudscape is embedded, not Cloudscape, handles the user authentication by connecting to an external directory service. For example, Cloudconnector can provide user authentication. In that scenario, Cloudconnector would authenticate the user name and password before granting access to the system in question. It would then grant the user access to the Cloudscape system and would pass the user’s name to Cloudscape.

Figure 8-4 The application provides the user authentication using an external service. The application can be a single-user application with an embedded Cloudscape engine or a muuser application server.

Enabling User Authentication

To enable user authentication, set the cloudscape.connection.requireAuthentication property to true. Otherwise, Cloudscape does not require a user name and password. You can set this pras a system-wide property or as a database-wide property.

For a multi-user product, you would typically set it for the system in the cloudscape.properties file for your server, since it is in a trusted environment.

NOTE: If you start a Cloudscape system with user authentication enabled buwithout defining at least one user, you will not be able to shut down thsystem gracefully. When Cloudscape is running in a connectivity servand user authentication is turned on, stopping the server requires a u

Cloudscape

External directory service

Applicationuserauthentication

Applicationor applicationserver

Cloudscape Version 3.0

Page 198: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-8

ion

g that

for a m. ith

nd

name and password. You will need to alter shutdown scripts accordingly. See the Cloudscape Server and Administration Guide for information.

Defining Users

Cloudscape provides several ways to define the repository of users and passwords. To specify which of these services to use with your Cloudscape system, set the property cloudscape.authentication.provider to the appropriate value as discussed in the appropriate section listed below.

Setting the property as a system-wide property creates system-wide users. Setting the property as a database-wide property creates users for a single database only.

• “External Directory Service” on page 8-8

- “LDAP Directory Service” on page 8-9. This includes Windows NT domain user authentication through the Netscape NT SynchronizatService.

- “NIS Directory Service Plus (NIS+)” on page 8-12

• “User-Defined Class” on page 8-13

• “Built-in Cloudscape Users” on page 8-17

NOTE: Shutting down the Cloudscape system (for example, using the shutdown=true form of the database connection URL without specifyina particular database) when user authentication is turned on requiresyou define at least one user as a system-wide user.

External Directory Service

A directory service stores names and attributes of those names. A typical usedirectory service is to store user names and passwords for a computer systeCloudscape uses the Java naming and directory interface (JNDI) to interact wexternal directory services that can provide authentication of users’ names apasswords.

In Version 3.0, Cloudscape can use the following services:

• “LDAP Directory Service” on page 8-9

• “NIS Directory Service Plus (NIS+)” on page 8-12

• “User-Defined Class” on page 8-13

cape Developer’s Guide

Page 199: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with User Authentication 8-9

e

. It -

pe

LDAP Directory Service

You can allow Cloudscape to authenticate users against an existing LDAP directory service within your enterprise. LDAP (lightweight directory access protocol), an emerging Internet standard, provides an open directory access protocol running over TCP/IP. An LDAP directory service can quickly authenticate a user’s name and password.

To use an LDAP directory service, set cloudscape.authentication.provider to LDAP.

Examples of LDAP service providers are:

• Netscape Directory Server

Netscape Directory Server is an LDAP directory server. In addition, thNetscape Directory Synchronization Service synchronizes entries in aWindows NT directory with the entries in Netscape’s Directory Serverallows you to use the Windows NT directory as a repository for Cloudscape users.

• UMich slapd (freeware for the UNIX platform from the University of Michigan)

• AE SLAPD for Windows NT, from AEInc

Cloudscape 2.0 has been tested with Netscape Directory Server and NetscaDirectory Synchronization Service.

Libraries

To use an LDAP directory service with Cloudscape, you need the following libraries in your class path:

• jndi.jar

JNDI classes

• ldap.jar

LDAP provider from Sun

• providerutil.jar

JNDI classes for a provider

Cloudscape does not provide these libraries; they are available from JavaSoft on the JNDI page at http://java.sun.com:80/products/jndi/. Use the 1.1.x versions of these libraries, not the 1.2.x versions. You may need to do two separate downloads to obtain all the required libraries.

Cloudscape Version 3.0

Page 200: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-10

ser and

N

full

te a

Setting Up Cloudscape to Use Your LDAP Directory Service

When specifying LDAP as your authentication service, you must specify the location of the server and its port number.

• cloudscape.authentication.serverSet the property cloudscape.authentication.server to the location and port number of the LDAP server. For example:

cloudscape.authentication.server=godfrey:389

Guest Access to Search for DNs

In an LDAP system, users are hierarchically organized in the directory as a set of entries. An entry is a set of name-attribute pairs identified by a unique name, called a DN (distinguished name). An entry is unambiguously identified by a DN, which is the concatenation of selected attributes from each entry in the tree along a path leading from the root down to the named entry, ordered from right to left. For example, a DN for a user might look like this:

cn=mary,ou=People,o=cloudscape.com

uid=mary,ou=People,o=cloudscape.com

The allowable entries for the name are defined by the entry’s objectClass.

An LDAP client can bind to the directory (successfully log in) if it provides a uID and password. The user ID must be a DN, the fully qualified list of names attributes. This means that the user must provide a very long name.

Typically, the user knows only a simple user name (e.g., the first part of the Dabove, WilliamS). With Cloudscape, you do not need the full DN, because an LDAP client (Cloudscape) can go to the directory first as a guest or even an anonymous user, search for the full DN, then rebind to the directory using theDN (and thus authenticate the user).

Cloudscape typically initiates a search for a full DN before binding to the directory using the full DN for user authentication. Cloudscape does not initiasearch in the following cases:

• You have set cloudscape.authentication.ldap.searchFilter to cloud-scape.user.

• A user DN has been cached locally for the specific user with the cloud-scape.user.UserName property.

For more information, see cloudscape.authentication.ldap.searchFilter in Tuning Cloudscape.

cape Developer’s Guide

Page 201: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with User Authentication 8-11

listed

o

N,

Some systems permit anonymous searches; other require a user DN and password. You can specify a user’s DN and password for the search with the properties below. In addition, you can limit the scope of the search by specifying a filter (definition of the object class for the user) and a base (directory from which tbegin the search) with the properties listed below.

• cloudscape.authentication.ldap.searchAuthDN (optional)Specifies the DN with which to bind (authenticate) to the server when searching for user DNs. This parameter is optional if anonymous access is supported by your server. If specified, this value must be a DN recognized by the directory service, and it must also have the authority to search for the entries.

If not set, it defaults to an anonymous search using the root DN specified by the cloudscape.authentication.ldap.searchBase property. For example:

uid=guest,o=cloudscape.com

• cloudscape.authentication.ldap.searchAuthPW (optional)Specifies the password to use for the guest user configured above to bind to the directory service when looking up the DN. If not set, it defaults to an anonymous search using the root DN specified by the cloud-scape.authentication.ldap.searchBase property.

myPassword

• cloudscape.authentication.ldap.searchBase (optional)Specifies the root DN of the point in your hierarchy from which to begin a guest search for the user’s DN. For example:

ou=people,o=cloudscape.com

When using Netscape Directory Server, set this property to the root Dthe special entry to which access control does not apply (optional).

To narrow the search, you can specify a user’s objectClass.

• cloudscape.authentication.ldap.searchFilter (optional)Set cloudscape.authentication.ldap.searchFilter to a logical expression that specifies what constitutes a user for your LDAP directory service. The default value of this property is objectClass=inetOrgPerson. For example:

objectClass=person

Cloudscape Version 3.0

Page 202: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-12

cts.

earch

s

ies

Performance Issues

For performance reasons, the LDAP directory server should be in the same LAN as Cloudscape. Cloudscape does not cache the user’s credential informationlocally and thus must connect to the directory server every time a user conne

Connection requests that provide the full DN are faster than those that must sfor the full DN.

Windows NT Users

Netscape provides LDAP functionality for Windows NT systems with its Netscape Directory Synchronization service, which synchronizes the WindowNT users with the Netscape Directory Server. SSL is recommended in this configuration.

Restrictions

Cloudscape Version 3.0 does not support LDAP groups.

NIS Directory Service Plus (NIS+)

Network Information Services Plus (NIS+) is an enhanced version of the NISname service used on the Sun Solaris and SunOS operating systems. In thissystem, users are contained in the NIS+ table called passwd.org_dir and groups in the table called group.org_dir.

To use an NIS+ directory service, set cloudscape.authentication.provider to NIS+.

Libraries

To use NIS+ directory service with Cloudscape, you need the following librarin your class path:

• jndi.jar

JNDI classes

• nisplus.jar

NIS+ provider from Sun, Early Release II

• providerutil.jar

JNDI classes for a provider

Cloudscape does not provide these libraries; they are available from JavaSoft on the JNDI page at http://java.sun.com:80/products/jndi/. Use the 1.1.x versions of

cape Developer’s Guide

Page 203: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with User Authentication 8-13

these libraries, not the 1.2.x versions. You may need to do two separate downloads to obtain all the required libraries.

Configuring Cloudscape for NIS+ User Authentication

You must set the cloudscape.authentication.server property to

//nis.server.name/nis.domain

For example:

//flare/cloudscape.com

JNDI-Specific Properties for External Directory Services

Cloudscape allows you to set a few advanced JNDI properties, which you can set in any of the supported ways of setting Cloudscape properties. Typically you would set these at the same level (database or system) for which you configured the external authentication service.

The list of supported properties can be found in Appendix A: JNDI Context Environment in the Java Naming and Direction API at http://java.sun.com:80/products/jndi/docs.html. The external directory service must support the property.

Each JNDI provider has its set of properties that you can set within the Cloudscape system.

For example, you can set the property java.naming.security.authentication to allow user credentials to be encrypted on the network if the provider supports it. You can also specify that SSL be used with LDAP (LDAPS).

User-Defined Class

Set cloudscape.authentication.provider to the full name of a class that implements the public interface COM.cloudscape.authentication.Interface.AuthenticationScheme.

By writing your own class that fulfills some minimal requirements, you can hook Cloudscape up to an external authentication service other than LDAP or NIS+. To do so, specify an external authentication service by setting the property cloudscape.authentication.provider to a class name that you want Cloudscape to load at startup.

The class that provides the external authentication service must implement the public interface COM.cloudscape.authentication.Interface.AuthenticationScheme

Cloudscape Version 3.0

Page 204: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-14

and throw exceptions of the type COM.cloudscape.authentication.Interface.AuthenticationException where appropriate.

Using a user-defined class makes Cloudscape adaptable to various naming and directory services.

A very simple example of a class that implements the interface follows.

import COM.cloudscape.authentication.Interface.*;

import java.io.FileInputStream;

import java.util.Properties;

/**

* A simple example of a specialized Authentication scheme.

* The system property ’cloudscape.connection.requireAuthentication

* must be set

* to true and ’cloudscape.connection.specificAuthentication’ must

* contain the full class name of the overriden authentication

* scheme, i.e., the name of this class.

*

* @see COM.cloudscape.authentication.Interface.AuthenticationScheme

*/

public class MyAuthenticationSchemeImpl implements

AuthenticationScheme {

private static final String USERS_CONFIG_FILE = "myUsers.cfg";

private static Properties usersConfig;

// Constructor

// We get passed some Users properties if the

//authentication service could not set them as

//part of System properties.

//

public MyAuthenticationSchemeImpl() {

}

/* static block where we load the users definition from a

users configuration file.*/

static {

/* load users config file as java properties

File must be in the same directory where

Cloudscape gets started.

(otherwise full path must be specified) */

cape Developer’s Guide

Page 205: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with User Authentication 8-15

FileInputStream in = null;

usersConfig = new Properties();

try {

in = new FileInputStream(USERS_CONFIG_FILE);

usersConfig.load(in);

in.close();

} catch (java.io.IOException ie) {

// No Config file. Raise error message

System.err.println(

"WARNING: Error during Users Config file

retrieval");

System.err.println("Exception: " + ie);

}

}

/**

* Authenticate the passed-in user’s credentials.

* A more complex class could make calls

* to any external users directory.

* NOTE: AuthenticationException must be thrown upon failure.

*

* @param userName The user’s name

* @param userPassword The user’s password

* @param databaseName The database

* @param infoAdditional jdbc connection info.

* @exception AuthenticationException on failure

*/

public voidauthenticateUser(String userName,

String userPassword,

String databaseName,

Properties info

)

throws AuthenticationException

{

/* Specific Authentication scheme logic.

If user has been authenticated, then simply return.

If user name and/or password are invalid,

then raise the appropriate exception:

new AuthenticationException.loginFailed();

If the user is not a valid user of the database,

then raise:

Cloudscape Version 3.0

Page 206: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-16

new AuthenticationException.notAValidUserInDatabase

(userName, databaseName);

For other (exceptional) exception, raise:

new AuthenticationException.loginFailed(myExceptionMsg);

This example allows only users defined in the

users config properties object.

Check if the passed-in user has been defined for the system.

We expect to find and match the property corresponding to

the credentials passed in. */

if (userName == null)

// We don’t tolerate ’guest’ user for now.

throw AuthenticationException.loginFailed();

//

// Check if user exists in our users config (file)

// properties set.

// If we didn’t find the user in the users config set, then

// try to find if the user is defined as a System property.

//

String actualUserPassword;

actualUserPassword = usersConfig.getProperty(userName);

if (actualUserPassword == null)

actualUserPassword = System.getProperty(userName);

if (actualUserPassword == null)

// no such passed-in user found

// Raise expected exception

throw AuthenticationException.loginFailed();

// check if the password matches

if (!actualUserPassword.equals(userPassword))

// Raise expected exception

throw AuthenticationException.loginFailed();

// Now, let’s check if the user is a valid user of the database

if (databaseName != null)

{

/* if database users restriction lists present, then check

if there is one for this database and if so,

check if the user is a valid one of that database.

For this example, the only user we authorize in database

DarkSide is user ’DarthVader’. This is the only database

cape Developer’s Guide

Page 207: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with User Authentication 8-17

users restriction list we have for this example.

We authorize any valid (login) user to access the

OTHER databases in the system.

Note that database users ACLs could be set in the same

properties file or a separate one and implemented as you

wish. */

//

if (databaseName.equals("DarkSide")) {

// check if user is a valid one.

if (!userName.equals("DarthVader"))

// This user is not a valid one of the passed-in

// database name. We raise the appropriate

// exception expected by Cloudscape.

throw AuthenticationException.notAValidDatabaseUser(

userName,

databaseName);

}

}

// The user is a valid one in this database

return;

}

/**

* Returns authentication scheme name string.

* Typically a string that succinctly states and identifies

* the authentication scheme.

* @return authentication scheme name string.

**/

public String toString() {

return "my authentication scheme";

}

}

Built-in Cloudscape Users

Cloudscape provides a simple, built-in respository of user names and passwords.

Cloudscape Version 3.0

Page 208: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-18

ord

ble to

sword

To use the built-in repository, set cloudscape.authentication.provider to CLOUDSCAPE. Using built-in users is an alternative to using an external directory service such as LDAP.

cloudscape.authentication.provider=CLOUDSCAPE

You can create user names and passwords for Cloudscape users by specifying them with the cloudscape.user.UserName property.

NOTE: These user names are case-sensitive for user authorization. User names are SQL92Identifiers. Delimited identifiers are allowed:

cloudscape.user."FRed"=java

For more information on user names and SQL92Identifiers, see “Users and Authorization Identifiers” on page 8-21.

NOTE: For passwords, it is a good idea not to use words that would be easilyguessed, such as a login name or simple words or numbers. A passwshould be a mix of numbers and upper- and lowercase letters.

Database-Level Properties

When you create users with database-level properties, those users are availathe specified database only.

You set the property once for each user. To delete a user, set that user’s pasto null.

-- adding the user sa with password ‘cloud3x9’

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.user.sa’, ’cloud3x9’)

-- adding the user mary with password ‘little7xylamb’

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.user.mary’, ’little7xylamb’)

-- removing mary by setting password to null

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.user.mary’, null)

System-Level Properties

When you create users with system-level properties, those users are available to all databases in the system.

cape Developer’s Guide

Page 209: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Working with User Authentication 8-19

You set the value of this system-wide property once for each user, so you may set it several times. To delete a user, remove that user from the file.

You can define this property in the usual ways—typically in the cloudscape.properties file. For more information about setting properties, see Tuning Cloudscape.

Here is a sample excerpt from the cloudscape.properties file:

# Users definition

#

cloudscape.user.sa=cloud3x9

cloudscape.user.mary=little7xylamb

Properties Summary

Table 8-1 summarizes the various properties related to user authentication.

Programming Applications for Cloudscape User Authentication

• “Programming the Application to Provide the User and Password” onpage 8-20

Table 8-1 User Authentication Properties

Property Name Use

cloudscape.connection.requireAuthentication Turns on user authentication.

cloudscape.authentication.provider Specifies the kind of user authentica-tion to use.

cloudscape.authentication.server For LDAP and NIS+ user authentica-tion, specifies the location of the server.

cloudscape.authentication.ldap.searchAuthDN,cloudscape.authentication.ldap.searchAuthPW,cloudscape.authentication.ldap.searchFilter,and cloudscape.authentication.ldap.searchBase

Configures the way DN searches are performed.

cloudscape.user.UserName Creates a user name and password for Cloudscape’s built-in user repository.

java.naming.* JNDI properties

Cloudscape Version 3.0

Page 210: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-20

with

e or not

tem,

ot

• “Login Failure Exceptions” on page 8-20

• “Authorization Identifiers, User Authentication, and User Authorizationon page 8-21

Programming the Application to Provide the User and Password

In the DriverManager.getConnection call, an application can provide the user name and password:

• separately as arguments to the following signature of the method: getCon-nection(String url, String user, String password)

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:myDB", "mary", "little7xylamb");

• as attributes to the database connection URL

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:myDB;user=mary;password=little7xylamb");

• by setting the user and password properties in a Properties object asother database connection URL attributes

Properties p = new Properties();

p.put("user", "mary");

p.put("password", "little7xylamb");

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:myDB", p);

NOTE: The password is not encrypted.When you are using Cloudscape in thcontext of a server framework, the framework should be responsible fencrypting the password across the network. If your framework does encrypt the password, consider using SSL. Cloudconnector does notencrypt a password unless you use SSL.

For information about the treatment of user names within the Cloudscape syssee “Users and Authorization Identifiers” on page 8-21.

Login Failure Exceptions

If user authentication is turned on and a valid user name and password are nprovided, SQLException XJ006 is raised.

ERROR XJ006: Login failed: Invalid username/password.

cape Developer’s Guide

Page 211: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Users and Authorization Identifiers 8-21

e

is

d to

t or

ays

se-

g

s

Users and Authorization IdentifiersUser names within the Cloudscape system are known as authorization identifiers. The authorization identifier is a string that represents the name of the user, if one was provided in the connection request. For example, the built-in function CURRENT_USER returns the authorization identifier for the current user.

Once the authorization identifier is passed to the Cloudscape system, it becomes an SQL92Identifier. SQL92Identifiers—the kind of identifiers that represent database objects such as tables and columns—are case-insensitive (they arconverted to all caps) unless delimited with double quotes, are limited to 128characters, and have other limitations.

User names must be valid authorization identifiers even if user authenticationturned off, and even if all users are allowed access to all databases.

For more information about SQL92Identifiers, see “SQL92Identifier” on page 1-4 of the Cloudscape Reference Manual.

Authorization Identifiers, User Authentication, and User Authorization

When working with both user authentication and user authorization, you neeunderstand how user names are treated by each system. If an external authentication system is used, the conversion of the user’s name to an authorization identifier does not happen until after authentication has occurred bubefore user authorization (see “User Authorization” on page 8-23). Imagine, fexample, a user named Fred.

• Within the user authentication system, Fred is known as FRed. Your external user authorization service is case-sensitive, so Fred must alwtype his name that way.

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:myDB", "FRed", "flintstone");

• Within the Cloudscape user authorization system, Fred becomes a cainsensitive authorization identifier. Fred is known as FRED.

• When specifying which users are authorized to access the accountindatabase, you must list Fred’s authorization identifier, FRED (which you can type as FRED, FREd, or fred, since the system automatically convertit to all-uppercase).

cloudscape.fullAccessUsers=sa,FRED,mary

Cloudscape Version 3.0

Page 212: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-22

the

n

g

se- If ase, case-er

ames

Let’s take a second example, where Fred has a slightly different name withinuser authentication system.

• Within the user authentication system, Fred is known as Fred!. You must now put double quotes around the name, because it is not a valid SQL92Identifier. (Cloudscape knows to remove the double quotes whepassing the name to the external authentication system.)

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:myDB", "\"Fred!\"", "flintstone");

• Within the Cloudscape user authorization system, Fred becomes a case-sensitive authorization identifier. Fred is known as Fred!.

• When specifying which users are authorized to access the accountindatabase, you must list Fred’s authorization identifier, "Fred!" (which you must always delimit with double quotation marks).

cloudscape.fullAccessUsers=sa,"Fred!",manager

As shown in the first example, your external authentication system may be casensitive, whereas the authorization identifier within Cloudscape may not be.your authentication system allows two distinct users whose names differ by cdelimit all user names within the connection request to make all user names sensitive within the Cloudscape system. In addition, you must also delimit usnames that do not conform to SQL92Identifier rules with double quotes.

User Names and Schemas

User names can affect a user’s default schema. For information about user nand schemas, see “SET SCHEMA statement” on page 1-112 in the Cloudscape Reference Manual.

Exceptions

Specifying an invalid authorization identifier in a database user authorizationproperty raises an exception. Specifying an invalid authorization identifier in aconnection request raises an exception.

cape Developer’s Guide

Page 213: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

User Authorization 8-23

et alues

User AuthorizationCloudscape provides user authorization, which is a means of granting users permission to access a database (or system). Cloudscape allows you to distinguish between full (read-write) access and read-only access. (Cloudscape Version 3.0 does not support the SQL GRANT and REVOKE features, which allow you to set permissions to specific database objects or specific SQL actions.)

Setting User Authorization

Database or System Access

Typically, you configure user authorization for a particular database. However, Cloudscape also allows you to configure user authorization for the system, which is useful during development and for specifying a secure default access for all databases in the system.

To control access to a particular database, set database-level properties that specify which users have full (read-write) access to the database and which users have read-only access to the database. Users not specified by either property inherit the default access for the database (none, read-only, or full read-write access). When not explicitly set, the default access for a database is full (read-write) access.

Setting the Default Access Mode

To specify the default access mode for the database, use the cloudscape.database.defaultConnectionMode property. You can set the property to the following values:

• noAccess

• readOnlyAccess

• fullAccess (the default)

Cloudscape validates the authorization configuration properties when users sthem. It raises an exception if a user attempts to set the properties to invalid v(see “Exceptions” on page 8-25).

Cloudscape Version 3.0

Page 214: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-24

ions.

Setting the Access Mode for Particular Users

To specify which particular users have full (read-write) access to a database, use the cloudscape.database.fullAccessUsers property. For example:

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.fullAccessUsers’, ’sa,mary’)

To specify which particular users have read-only access to a database, use the cloudscape.database.readOnlyAccessUsers property. For example:

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.readOnlyAccessUsers’, ’guest,"Fred!"’)

For these properties, you specify users as a comma-separated list (no spaces between the comma and the next user).

For users not specified with either property the access is specified by the cloudscape.database.defaultConnectionMode property.

NOTE: It is possible to configure a database so that it cannot be changed (or even accessed) using the cloudscape.database.defaultConnectionMode property. If you set this property to noAccess or readOnlyAccess, be sure to allow at least one user full access.

NEW: With Version 3.0 Cloudscape provides a new utility to make it easier to create and maintain the lists of read-only and full-access users. This utility is COM.cloudscape.database.UserUtility (aliased as UserUtility). For example, instead of having to retype the full list of cloudscape.database.fullAccessUsers when you add a full access user, you can simply use UserUtility’s add method to add a user. For example:

CALL UserUtility.add(

’mary’, UserUtility->FULL_ACCESS_PERMISSION)

See the Javadoc for the utility or “Examples” on page 8-26 for more details.

Notes on User Authorization

All the authorization properties are set for a connection when it is created. Changing any of the authorization properties does not affect existing connectHowever, all future connections are affected by the change.

For more information about authorization identifiers, see “Users and Authorization Identifiers” on page 8-21.

cape Developer’s Guide

Page 215: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

User Authorization 8-25

Exceptions

If a user is not authorized to connect to the database specified in the connection request, SQLException 04501 is raised.

If a user with readOnlyAccess attempts to write to a database, SQLException 22502 is raised.

About Read-Only and Full Access

Table 8-2 shows which actions read-only and full-access users are permitted to perform on regular or source databases and on target databases (source and target databases are part of a synchronization system).

For more information about security in synchronization systems, see the Cloudscape Synchronization Guide.

Table 8-2 Permissions for Read-Only and Full-Access Users

Action

Read-OnlyUserson Non-Target Databases

Full-AccessUsers on Non-Target Databases

Read-OnlyUserson Targets

Full-AccessUserson Targets

Executing SELECT state-ments

X X X X

Reading database properties X X X X

Loading database classes from jar files

X X X X

Creating a copy file from a publication

X(only if a source)

Performing a refresh X X

Executing INSERT, UPDATE, or DELETE state-ments

X X

Executing DDL statements X

Adding or replacing jar files X

Setting database properties X X (new in Ver-sion 3.0)

Cloudscape Version 3.0

Page 216: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-26

ad-

Examples

This example shows the property settings to configure a database to support:

• full access for a single user named sa

• read-only access for anyone else who connects to the database

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.defaultConnectionMode’,

’readOnlyAccess’)

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.fullAccessUsers’, ’sa’)

This example shows the settings to configure a database to support:

• full access for a single user named "Fred!" (case-sensitive) with full (rewrite) access

• Read-only access for mary and guest

• No access for other users.

(The example demonstrates the use of delimited identifiers for user names.)

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.defaultConnectionMode’,

’noAccess’)

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.fullAccessUsers’, ’"Fred!"’)

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.readOnlyAccessUsers’, ’mary,guest’)

This example uses UserUtility to create and then modify lists of read-only and full-access users.

-- first, make the default access mode noAccess

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.defaultConnectionMode’,

’noAccess’)

-- then add users to the read-access user list

-- add bill

CALL UserUtility.add(

’bill’, UserUtility->READ_ACCESS_PERMISSION)

-- add jane

CALL UserUtility.add(

’jane’, UserUtility->READ_ACCESS_PERMISSION)

cape Developer’s Guide

Page 217: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Encrypting Databases on Disk 8-27

-- now add users to the full-access user list

-- add george

CALL UserUtility.add(

’george’, UserUtility->FULL_ACCESS_PERMISSION)

-- add felipe

CALL UserUtility.add(

’felipe’, UserUtility->FULL_ACCESS_PERMISSION)

-- now change jane’s permission to full-access

CALL UserUtility.set(

’jane’, UserUtility->FULL_ACCESS_PERMISSION)

-- check on felipe’s permissions:

VALUES UserUtility.getPermission(’felipe’)

-- take felipe out of all lists

CALL UserUtility.drop(’felipe’)

Encrypting Databases on Disk

Overview

Cloudscape provides a way for you to encrypt your data on disk.

Typically, database systems encrypt and decrypt data in transport over the network, using industry-standard systems such as SSL. This system works well for client/server databases; the server is assumed to be in a trusted, safe environment, managed by a system administrator. In addition, the recipient of the data is trusted and is assumed to be capable of protecting the database. The only risk comes when in transporting data over the wire, and data encryption happens during network transport only.

With Cloudscape, however, such a system may be insufficient because of the portability of Cloudscape databases, which are platform-independent files that are designed to be easily shared in a number of ways, including transport over the Internet. Recipients of the data may not know how to, or may not have the means to, properly protect the data.

This data encryption feature provides the ability to store user data in an encrypted form. The user who boots the database must provide a boot password.

Cloudscape Version 3.0

Page 218: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-28

.2 re,

ithout se.

ring e

te it.

you lpha-

ed,

ou the

Libraries and JVM

Cloudscape’s data encryption uses the 64-bit DES encryption engine in the 1version of the Java Cryptographic Extension (JCE). In order to use this featuyou must obtain the 1.2 version of the standard JCE package, which is freelydistributed to all U.S. residents (see http://java.sun.com/products/jce/index.html). With encryption, Cloudscape runs only in JDKs of version 1.2 or later.

NOTE: This library is available only to U.S. customers.

Any attempt to create or access an encrypted database without SunJCE or wJCE 1.2 raises an exception; you will not be able to create or boot the databa

NOTE: The JCE documentation installation documentation describes configu(registering) the JCE software. You do not need to do this; Cloudscapregisters JCE dynamically.

Working with Encryption

• “Encrypting Databases on Creation” on page 8-28

• “Booting an Encrypted Database” on page 8-29

• “Changing the Boot Password” on page 8-29

Encrypting Databases on Creation

Cloudscape allows you to configure a database for encryption when you crea

When you create a database, you can specify whether to encrypt the data. Ifspecify data encryption, you must also specify a boot password, which is an anumeric string used to generate the encryption key. It must be at least eight characters long. It is a good idea not to use words that would be easily guesssuch as a login name or simple words or numbers. A bootPassword, like any password, should be a mix of numbers and upper- and lowercase letters.

You turn on encryption and specify the corresponding boot password on the database connection URL for a database when you create it:

jdbc:cloudscape:wombat;create=true;dataEncryption=true;

bootPassword=clo760uds2caPe

NOTE: If you lose the bootPassword and the database is not currently booted, ywill not be able to connect to the database anymore. (If you do know

cape Developer’s Guide

Page 219: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Encrypting Databases on Disk 8-29

sword all

ut the

quire

icitly

own

to has

tely;

current bootPassword, you can change it. See “Changing the Boot Password” on page 8-29.)

Booting an Encrypted Database

Once you have created an encrypted database, you must supply the boot pasto reboot it. Encrypted databases cannot be booted automatically along with other system databases on system startup (see “cloudscape.system.bootAll” on page 5-72 of Tuning Cloudscape). Instead, you boot encrypted databases whenyou first connect to them.

For example, to access an encrypted database called wombat, created with the boot password cloudscape, you would use the following database connection URL:

jdbc:cloudscape:wombat;bootPassword=clo760uds2caPe

Once the database is booted, all connections can access the database withoboot password. Only a connection that boots the database requires the key.

For example, the following connections would boot the database and thus rethe boot password:

• the first connection to the database in the JVM session

• the first connection to the database after the database has been explshut down

• the first connection to the database after the system has been shut dand then rebooted

NOTE: The boot password is not meant to prevent unauthorized connectionsthe database once it has been booted. To protect a database once it been booted, turn on user authentication (see “Working with User Authentication” on page 8-5).

Changing the Boot Password

You can change the boot password for the current database.

call (CLASS COM.cloudscape.database.PropertyInfo).setDatabaseProperty(’bootPasword’, ’oldbpw , newbpw’);

where oldbpw is the current boot password and newbpw is the new boot password.Secret keys must be at least eight characters long. This call commits immediait is not transactional.

Cloudscape Version 3.0

Page 220: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-30

.

NOTE: getDatabaseProperty does not return the boot password.

SSLSecure Socket Layer (SSL) is a protocol designed to guarantee privacy and integrity of messages on the wire. Cloudscape has been verified to work with application servers that support SSL. In addition, Cloudconnector supports SSL beginning with Version 2.0.

This section provides an overview of the way SSL works. For specific information on using and configuring SSL for Cloudconnector, see the Cloudscape Server and Administration Guide.

There are two parts to secure communications:

• AuthenticationAuthentication takes place at two levels: first, verifying that the communi-cating parties are who they say they are, and second, verifying that each message sent is from the expected sender and has not been tampered with.

Initial authentication with SSL involves the use of a certificate. The certif-icate is made up of a public key and some information about the owner of the corresponding private key. The certificate is signed cryptographically by a certificate authority.

A cryptographic signature can be verified based on the public key of the certificate authority; forging a cryptographic signature without knowing the certificate authority’s private key is statistically close to impossible

• EncryptionEncryption makes clear text unintelligible to everyone except those who have a key to decipher it.

Encryption requires a key and an algorithm, and both parties must know the key and the algorithm used to create it. The number of possible keys an encryption algorithm can support depends on the number of bits in the key. The longer the key, the more secure the encrypted message.

SSL uses public-key cryptography for authentication and to establish a shared secret key. Public-key cryptography uses public/private key pairs. The public key is used to encrypt and to verify a cryptographical signa-ture. The private key is used to decrypt and sign cryptographically. You advertise your public key to the world so that everyone can send you mes-

cape Developer’s Guide

Page 221: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Notes on the Cloudscape Security Features 8-31

s, ange

t wn to

the ver ers not

le to

nd

e

sages that only you can decrypt, and everyone can verify your crypto-graphic signature.

SSL offers a choice of encryption algorithms. For encryption to work properly, both parties must know which algorithms—called a cipher suite—will be used; SSL negotiates this choice.

Some users may be interested in both levels of security—encryption and authentication—particularly if clients and servers will be exchanging sensitiveinformation over the Internet. In many cases, only the server will be asked toauthenticate itself to assure the client that it is a trusted server; in other caseusers may need two-way authentication, in which both client and server exchcertificates. In other situations, in which communications are between trustedclients and a server, an application may use encryption to protect privacy, buauthentication may be less important since clients and server are already knoeach other.

Notes on the Cloudscape Security FeaturesBecause Cloudscape does not support traditional grant and revoke features,security model has some basic limitations. For both embedded and client/sersystems, it assumes that users are trusted. You must trust your full-access usto perform undesirable actions.

In addition, in the Cloudscape system, it is not necessary to have a specific connection (or permission to access a particular database) to shut down the system. Any authenticated user can shut down the system.

However, a sophisticated user with the database encryption key might be abphysically change those properties in the database files.

Other security holes to think about are:

• JDK subversion, running the application under a home-grown JDK

• trolling for objects

• class substitution, locating a class that has access to sensitive data areplacing it with one that passes on information

For notes on the security limitations in a distributed, synchronized Cloudscapsystem, see the Cloudscape Synchronization Guide.

Cloudscape Version 3.0

Page 222: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-32

. erver ords, rity

P

er to

the

ly

User Authentication and Authorization Examples

• “Client/Server Environment” on page 8-32

• “Single-User, Embedded Environment” on page 8-33

• “Extended Example” on page 8-34

• “Synchronization Environment” on page 8-37

Client/Server Environment

In this example, Cloudscape is running in a user-designed application serverCloudscape provides the user authentication, not the application server. The sis running in a secure environment, the application server encrypts the passwand a database administrator is available. The administrator configures secuusing system-level properties in the cloudscape.properties file and has protected this file with operating system tools. Cloudscape connects to an existing LDAdirectory service within the enterprise to authenticate users.

The default access mode for all databases is set to fullAccess (the default).

The cloudscape.properties file for the server includes the following entries:

# turn on user authentication

cloudscape.connection.requireAuthentication=true

# set the authentication provider to an external LDAP server

cloudscape.authentication.provider=LDAP

# the host name and port number of the LDAP server

cloudscape.authentication.server=godfrey:389

# the search base for user names

cloudscape.authentication.ldap.searchBase=o=oakland.mycompany.com

# explicitly show the access mode for databases (this is default)

cloudscape.database.defaultAccessMode=fullAccess

With these settings, all users must be authenticated by the LDAP server in ordaccess any Cloudscape databases.

The database administrator has determined that one database, accountingDB, has additional security needs. Within a connection to that database, the databaseadministrator uses database-wide properties (which override properties set incloudscape.properties file) to limit access to this database. Only the users prez, cfo, and numberCruncher have full (read-write) access to this database, and on

cape Developer’s Guide

Page 223: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

User Authentication and Authorization Examples 8-33

ect to

loper will

ode

e by

e

clerk1 and clerk2 have read-only access to this database. No other users can access the database.

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.defaultAccessMode’, ’noAccess’)

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.fullAccessUsers’,

’prez,cfo,numberCruncher’)

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.readAccessUsers’, ’clerk1,clerk2’)

The database administrator then requires all current users to disconnect and re-connect. These property changes do not go into effect for current connections. The database administrator can force current users to reconnect by shutting down the database:

CALL (CLASS java.sql.DriverManager).getConnection(

’jdbc:cloudscape:;current=true;shutdown=true’)

Single-User, Embedded Environment

In this example, Cloudscape is embedded in a single-user application that is deployed in a number of different and potentially insecure ways. For that reason, the application developer has decided to encrypt the database and to turn on user authentication using Cloudscape’s built-in user authentication, which will not require connections to an LDAP server. The end-user must know the bootPassword to boot the database and the user name and password to connthe database. Even if the database ended up in an e-mail, only the intended recipient would be able to access data in the database. The application devehas decided not to use any user authorization features, since each databaseaccept only a single user. In that situation, the default full-access connection mis acceptable.

When creating the database, the application developer encrypts the databasusing the following database connection URL:

jdbc:cloudscape:wombat;create=true;dataEncryption=true;

bootPassword=sxy90W348HHn

Before deploying the database, the application developer turns on user authentication, sets the authentication provider to CLOUDSCAPE, creates asingle user and password, and disallows system-wide properties to protect thdatabase-wide security property settings:

Cloudscape Version 3.0

Page 224: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-34

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.connection.requireAuthentication’, ’true’)

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.authentication.provider’, ’CLOUDSCAPE’)

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.user.enduser’, ’cloud3x9’)

CALL PropertyInfo.setDatabaseProperty(

’cloudscape.database.propertiesOnly’, true’)

When the user connects (and boots) the database, the user has to provide the bootPassword, the user name, and the password. The following example shows how to provide those in a database connection URL, although the application programmer would probably provide GUI windows to allow the end user to type those in:

jdbc:cloudscape:wombat;bootPassword=sxy90W348HHn;

user=enduser;password=cloud3x9

Extended Example

You will find this example in the sample application (see JBMSTours.AdminHelper).

public static void turnOnBuiltInUsers(Connection conn) throws

SQLException {

System.out.println("Turning on authentication.");

Statement s = conn.createStatement();

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.connection.requireAuthentication’,

’true’)");

// Confirming requireAuthentication

ResultSet rs = s.executeQuery(

"VALUES PropertyInfo.getDatabaseProperty(

’cloudscape.connection.requireAuthentication’)");

rs.next();

System.out.println(rs.getString(1));

// Setting authentication scheme to Cloudscape

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.authentication.provider’, ’CLOUDSCAPE’)");

// Creating some sample users

cape Developer’s Guide

Page 225: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

User Authentication and Authorization Examples 8-35

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.user.sa’, ’cloud3x9’)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.user.guest’, ’java5w6x’)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.user.mary’, ’little7xylamb’)");

// Setting default connection mode to no access

// (user authorization)

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.database.defaultConnectionMode’,"+

" ’noAccess’)");

// Confirming default connection mode

rs = s.executeQuery("VALUES PropertyInfo.getDatabaseProperty("+

"’cloudscape.database.defaultConnectionMode’)");

rs.next();

System.out.println(rs.getString(1));

// Defining read-write users

s.executeUpdate("CALL UserUtility.add("+

’sa’, UserUtility->FULL_ACCESS_PERMISSION)");

s.executeUpdate("CALL UserUtility.add("+

’mary’, UserUtility->FULL_ACCESS_PERMISSION)");

// Defining read-only users

s.executeUpdate("CALL UserUtility.add(’guest’, "+

"UserUtility->READ_ACCESS_PERMISSION)");

// Confirming full-access users

rs = s.executeQuery("VALUES PropertyInfo.getDatabaseProperty("+

’cloudscape.database.fullAccessUsers’)");

rs.next();

System.out.println(rs.getString(1));

// Confirming read-only users

rs = s.executeQuery("VALUES PropertyInfo.getDatabaseProperty("+

"’cloudscape.database.readOnlyAccessUsers’)");

rs.next();

System.out.println(rs.getString(1));

//we would set the following property to TRUE only

//when we were ready to deploy.

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

Cloudscape Version 3.0

Page 226: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-36

"’cloudscape.database.propertiesOnly’, ’false’)");

s.close();

}

/**

* Turn off built-in user authentication and user authorization.

*

* @param conn a connection to the database.

*/

public static void turnOffBuiltInUsers(Connection conn) throws

SQLException {

Statement s = conn.createStatement();

System.out.println("Turning off authentication.");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.connection.requireAuthentication’,"+

"’false’)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.authentication.provider’, null)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.user.sa’, null)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.user.guest’, null)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.user.mary’, null)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.database.defaultConnectionMode’,"+

" ’fullAccess’)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.database.fullAccessUsers’, null)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.database.readOnlyAccessUsers’, null)");

s.executeUpdate("CALL PropertyInfo.setDatabaseProperty("+

"’cloudscape.database.propertiesOnly’, ’false’)");

// Confirming requireAuthentication

ResultSet rs = s.executeQuery("VALUES "+

PropertyInfo.getDatabaseProperty(" +

"’cloudscape.connection.requireAuthentication’)");

rs.next();

cape Developer’s Guide

Page 227: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

User Authentication and Authorization Examples 8-37

System.out.println(rs.getString(1));

// Confirming default connection mode

rs = s.executeQuery("VALUES PropertyInfo.getDatabaseProperty(" +

"’cloudscape.database.defaultConnectionMode’)");

rs.next();

System.out.println(rs.getString(1));

System.out.println("Turned off all the user-related properties.");

s.close();

}

Synchronization Environment

For examples in a synchronization environment, see the Cloudscape Synchronization Guide.

Cloudscape Version 3.0

Page 228: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Cloudscape and Security

Clouds

8-38

cape Developer’s Guide

Page 229: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

. As

ta

9 Information for Tool Developers

Applications such as database tools are designed to work with databases whose schemas and contents are unknown in advance. This chapter discusses a few topics useful for such applications.

• “Working with Metadata for Java Data Types” on page 9-1

• “Offering Connection Choices to the User” on page 9-2

• “Storing DatabaseMetaData Queries” on page 9-5

Working with Metadata for Java Data TypesTools often use the JDBC ResultSetMetaData class to get information about datain a particular table. However, JDBC is limited to standard SQL-92 data typesyou know, Cloudscape can store Java data types.

ResultSetMetaData.getColumnType returns the name of the Java class for the dastored in that column. For example, if a column serializes JBMSTours.City, getColumnType returns “JBMSTours.City”. (However, there is no explicit information is returned to indicate that this type is a Java data type.)

9-1

Page 230: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Information for Tool Developers

Clouds

9-2

ugh

sary to y,

in a

em. e

Result set metadata for columns that store Java data types and metadata items that describe the type of the column always return the following default values:

These attributes do not typically apply to Java data types.

To get more information about the Java class, use the Java reflection mechanism (java.lang.reflect.*).

Offering Connection Choices to the UserJDBC’s java.sql.Driver.getPropertyInfo method allows a generic GUI tool to determine the properties for which it should prompt a user in order to get enoinformation to connect to a database. Depending on the values the user has supplied so far, additional values may become necessary, so it may be necesiterate though several calls to getPropertyInfo. If no more properties are necessarthe call returns an array of zero length.

In a Cloudscape system, do not use the method against an instance of COM.cloudscape.core.JDBCDriver. Instead, request the JDBC driver from the driver manager:

java.sql.DriverManager.getDriver(

"jdbc:cloudscape:").getPropertyInfo(URL, Prop)

In a Cloudscape system, the properties returned in the DriverPropertyInfo object are database connection URL attributes, including a list of booted databasessystem (the databaseName attribute).

Databases in a system are not automatically booted until you connect with thYou can configure your system to retain the former behavior, in which case thsteps described in this section will continue to work. See “cloudscape.system.bootAll” on page 5-72 in Tuning Cloudscape.

Method Name Value

getColumnDisplaySize 15

getPrecision 0

getScale 0

isAutoIncrement false

isCaseSensitive false

isCurrency false

isSigned false

cape Developer’s Guide

Page 231: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Offering Connection Choices to the User 9-3

gth

hat ntext

getPropertyInfo requires a database connection URL and a Properties object as parameters. Typically, what you pass are values that you will use in a future call to java.sql.DriverManager.getConnection when you actually connect to the database. For information about setting attributes in calls to java.sql.DriverManager.getConnection, see “Examples” on page 2-20.

A call to getPropertyInfo with parameters that contain sufficient information to connect successfully returns an array of zero length. (Receiving this zero-lenarray does not guarantee that the getConnection call will succeed, because something else could go wrong.)

Repeat calls to getPropertyInfo until it returns a zero-length array or none of theproperties remaining are desired.

The DriverPropertyInfo Array

When a non-zero-length array is returned by getPropertyInfo, each element is a DriverPropertyInfo object representing a database connection URL attribute thas not already been specified. Only those that make sense in the current coare returned.

This DriverPropertyInfo object contains:

• name of the attribute

• description

• current valueIf an attribute has a default value, this is set in the value field of Driver-PropertyInfo, even if the attribute has not been set in the database connec-tion URL or the Properties object. If the attribute does not have a default value and it is not set in the URL or the Properties object, its value will be null.

• list of choices

• whether required for a connection request

Several fields in a DriverPropertyInfo object are allowed to be null.

databaseName

For example, if a Cloudscape system has the databases toursDB and flightsDB booted in its system directory, and some user has also connected to a database A:/dbs/tours94 the array returned from getPropertyInfo will contain at least one object corresponding to the databaseName attribute. The choices field of the

Cloudscape Version 3.0

Page 232: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Information for Tool Developers

Clouds

9-4

form)

DriverPropertyInfo object will contain an array of three Strings with the values “toursDB”, “flightsDB”, and “A:/dbs/tours94”. This object is returned only if theproposed connection objects do not already include a database name (in anyor include the shutdown attribute with the value true.

Example

A typical use of getPropertyInfo in a GUI can be seen in the “Connect to DB detailed ...” menu option of the JDBCTest tool from Intersolv.

Here is some example code:

import java.sql.*;

import java.util.Properties;

// start with the least amount of information

// to see the full list of choices

//

// we could also enter with a URL and Properties

// provided by a user.

String url = "jdbc:cloudscape:";

Properties info = new Properties();

Driver cDriver = DriverManager.getDriver(url);

for (;;)

{

DriverPropertyInfo[] attributes = cDriver.getPropertyInfo(

url, info);

// zero length means a connection attempt can be made

if (attributes.length == 0)

break;

// insert code here to process the array, e.g.,

// display all options in a GUI and allow the user to

// pick and then set the attributes in info or URL.

}

// try the connection

Connection conn = DriverManager.getConnection(url, info);

cape Developer’s Guide

Page 233: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Storing DatabaseMetaData Queries 9-5

Storing DatabaseMetaData QueriesDatabase tools sometimes use the JDBC DatabaseMetaData calls, which use complex SQL-J queries to return information about the DBMS and database. You can improve the performance of such applications using Cloudscape databases by storing precompiled versions of those queries in the database.

For information, see “cloudscape.jdbc.metadataStoredPreparedStatements” on page 5-29 in Tuning Cloudscape.

Cloudscape Version 3.0

Page 234: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Information for Tool Developers

Clouds

9-6

cape Developer’s Guide

Page 235: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

0-5

-7

-14

10 SQL-J Tips

There are many neat things you can do with SQL-J because of its Java extensions and its support of the features that were new in SQL-92. This chapter provides some examples (it also includes one or two non-SQL tips):

• “Performing Case-Insensitive Sorts” on page 10-2

• “Retrieving the Database Connection URL” on page 10-2

• “Using java.lang Methods as Functions” on page 10-2

• “Getting Methods to Look and Work More Like Stored Procedures” onpage 10-3

• “Use the Cloudscape-Supplied Methods to Work with Bits” on page 1

• “Working with Arrays” on page 10-6

• “Managing External Resources” on page 10-6

• “Access Data from Another DBMS with Cloudscape’s VTI” on page 10

• “Working with Date/Time Formats” on page 10-8

• “Supplying a Parameter Only Once” on page 10-8

• “Defining a Sequence-Number Column” on page 10-9

• “Using Literals to Save Keystrokes” on page 10-11

• “Integrating External Libraries” on page 10-11

• “Using Third-Party Tools” on page 10-12

• “Accessing and Modifying System Properties” on page 10-12

• “Tricks of the VALUES Clause” on page 10-13

• “Forcing Garbage Collection and Finalization” on page 10-14

• “Using a Derived Table to Avoid Redundant Method Calls” on page 10

10-1

Page 236: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips

Clouds

10-2

Performing Case-Insensitive Sorts

Use the UPPER function or a Java method to perform a case-insensitive sort. For example:

SELECT name, name.toUpperCase() AS up

FROM mixedcasenames ORDER BY up

In your application, retrieve only the first column from the ResultSet.

If you want Cloudscape to return only the results you want, wrap the query in the ExternalQuery VTI (essentially making it a specialized kind of subquery, one that allows ordering). Then select only the desired column from that subquery. For example:

SELECT name

FROM NEW ExternalQuery(’jdbc:cloudscape:;current=true’,

’SELECT name, name.toUpperCase() AS up FROM mixedcasenames

ORDER BY up’)

AS eq(name, up)

Retrieving the Database Connection URL

Cloudscape does not have a built-in function that returns the name of the database. However, you can use DatabaseMetaData to return the database connection URL of any local Connection.

/* in java */

String myURL = conn.getMetaData().getURL();

-- in SQL

VALUES getCurrentConnection().getMetaData().getURL()

Using java.lang Methods as Functions

You can use methods of java.lang classes for all the functions that are built into other databases. For example, you can call the static method java.lang.Math.abs, which is similar to ABS in other database systems. You can call the method this way:

SELECT (CLASS java.lang.Math).abs(balance) FROM account

cape Developer’s Guide

Page 237: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips 10-3

red ad, it esses C e they bit

(exe-an

ents

lling

onal

You can also define an alias for any static Java method, making it appear as a native built-in function. You use the CREATE METHOD ALIAS statement. Alias definitions are specific to a database; to use an alias when connected to a database, you must define the alias within that database. Once the aliases are defined, they are available to all connections.

CREATE METHOD ALIAS ABS FOR java.lang.Math.abs

After defining the alias, you can call the method this way:

SELECT ABS(balance) FROM account

Your installation includes a script that you can run to create aliases for all the java.lang.Math static methods. See readme.html in demo/util/methodalias for more details.

Appendix A, “Mapping of Functions to java.lang Methods”, lists the ways the java.lang methods correspond to functions built into other database systems.

Getting Methods to Look and Work More Like Stored Procedures

Some Cloudscape users may be used to working with another RDBMS’s stoprocedures. As you know, Cloudscape does not use stored procedures. Insteallows you to execute any Java method. When such a Java method itself accthe database, it is called a database-side JDBC method. Database-side JDBmethods are the ones that most closely resemble stored procedures, becausare executed by the DBMS and they access data. However, they still work a differently than traditional stored procedures. For example:

• They do not have to be stored in the database (though they can be).

• Although they are precompiled to the extent that all Java classes are cuting a method within an SQL-J statement doesn’t take any longer thexecuting the same method from your application), the SQL-J statemthey execute are not precompiled (though they can be).

• You may have to cast the data types of dynamic parameters when cathem.

• The syntax for calling them can be a bit unwieldy.

Here are some tips for making a method call look and work more like a traditistored procedure, if that is what you want:

Cloudscape Version 3.0

Page 238: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips

Clouds

10-4

t the

:

, you s ic

ure.”

• Create a stored prepared statement for any complex SQL-J statemenmethod executes:

CREATE STATEMENT getDirectFlights AS

yourSQLStatementHere

• Make a method alias for it to simplify the syntax of calling the method

CREATE METHOD ALIAS myMethodAlias FOR

myClass.myMethodThatCallsThatStatement

To call the method, instead of the following:

CALL (CLASS myClass).myMethodThatCallsThatStatement(

getCurrentConnection(), ?, CAST (? as int))

you can execute:

CALL MyMethodAlias(getCurrentConnection(), ?, CAST (? as int))

• If the need to cast the data types of the parameters is still bothersomecan create a stored prepared statement for executing it. This simplifiecalling the method, because you can cast the data type of the dynamparameter “inside” the stored prepared statement:

CREATE STATEMENT George AS CALL MyMethodAlias(

getCurrentConnection(), ?, CAST (? as int))

You have to create the statement only once. The call is simplified; youwill not have to cast the data type of the dynamic parameter:

EXECUTE STATEMENT George

• Store the actual Java class in the database to avoid problems with deployed classes. That way, you really are executing a “stored proced

Here are some samples of Java code:

Connection conn;

PreparedStatement = conn.prepareStatement(

"CALL (CLASS myClass).myMethodThatCallsThatStatement(" +

"getCurrentConnection(), ?, CAST (? AS INT))");

ps.setString(1, "a string");

ps.setInt(2, 2);

ps.executeUpdate();

* * *

Statement s = conn.createStatement();

s.executeUpdate(

cape Developer’s Guide

Page 239: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips 10-5

"CREATE METHOD ALIAS myMethodAlias " +

"FOR myClass.myMethod;");

PreparedStatement = conn.prepareStatement(

"CALL MyMethodAlias(getCurrentConnection(), ?, CAST (? AS INT))");

ps.setString(1, "a string");

ps.setInt(2, 2);

ps.executeUpdate();

* * *

ps = conn.prepareStatement(

"CREATE STATEMENT George AS CALL MyMethodAlias(" +

"getCurrentConnection(), ?, CAST (? AS INT))");

ps.executeUpdate();

*

* * *

PreparedStatement georgeStatement = conn.prepareStatement(

"EXECUTE STATEMENT George");

ps.setString(1, "a string");

ps.setInt(2, 2);

ps.executeUpdate();

* * *

Use the Cloudscape-Supplied Methods to Work with Bits

Cloudscape provides a utility class for working with bits, COM.cloudscape.util.BitUtil. It also provides a script to load the static methods of this class into method aliases. See readme.html in /demo/util/methodalias for more details.

The methods allow you to do bit manipulation on flags stored in a bit field.

ij> create table tmp(b bit(16));

0 rows inserted/updated/deleted

ij> create method alias bitSet for COM.cloudscape.util.BitUtil.set;

ij> create method alias bitClear for COM.cloudscape.util.BitUtil.clear;

ij> create method alias bitGet for COM.cloudscape.util.BitUtil.get;

ij> insert into tmp VALUES (B’1101000000000000’);

1 row inserted/updated/deleted

-- checks the value of the bit at position 2

Cloudscape Version 3.0

Page 240: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips

Clouds

10-6

ij> SELECT bitGet(b, 2) FROM tmp;

SQLC&

-----

false

-- sets the bit at position 2

ij> update tmp set b = bitSet(b,2);

1 row inserted/updated/deleted

-- checks the value of the bit at position 2

ij> SELECT bitGet(b,2) FROM tmp;

SQLC&

-----

true

-- clears the bit at position 2

ij> update tmp set b = bitClear(b,2);

1 row inserted/updated/deleted

ij> SELECT bitGet(b, 2) FROM tmp;

SQLC&

-----

false

ij>

Working with Arrays

SQL-J also does not yet have built-in support for arrays. However, java.lang.reflect.Array provides for dynamic array manipulation, and its methods can be applied to array objects that are returned by other methods. An example of an array-rich library is JNL, a public-domain numeric library available from VisualNumerics (www.vni.com/products/wpd/jnl/jnl_1_0.html).

Managing External Resources

You can store a java.io.File or java.net.URL object in a column to manage external resources from within a database. See /demo/programs/media in the installation directory for a more complete example.

CREATE TABLE images (

imageFile SERIALIZE(java.io.File),

imageDesc VARCHAR(100))

cape Developer’s Guide

Page 241: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips 10-7

to the

te a

t in .

eway.

tring ss to

INSERT INTO images VALUES (NEW java.io.File(’Cloudscape.gif’),

’Cloudscape Splash Logo’)

SELECT NEW java.io.FileOutputStream(imageFile)

FROM images

WHERE imageDesc.toLowerCase() LIKE ’%logo%’

Access Data from Another DBMS with Cloudscape’s VTI

It is always possible for a Java program to load two JDBC drivers, establish a connection to each database, and import data “by hand” from one database other with a construct like this:

ResultSet rs = queryToFirstDatabase.executeQuery();

while (rs.next()) {

/* get each column from each row here, and store in table

in the second database*/

insertIntoSecondDatabase.setInt(1, rs.getInt(1));

insertIntoSecondDatabase.executeUpdate();

Cloudscape’s Virtual Table Interface allows you to avoid all that coding. Creaclass that fulfills the VTI requirements; the main requirement is that the classimplement the java.sql.ResultSet interface. (For complete details about the requirements, see “ExternalVirtualTable” on page 1-76 in the Cloudscape Reference Manual.)

When a class fulfills the VTI requirements, you can construct an instance of ithe FROM clause of an SQL-J statement to construct an ExternalVirtualTableCloudscape then uses the ResultSet it creates to access data.

For an example of a class that does this, see COM.cloudscape.vti.ExternalQuery. This class is provided as an example, but you can also use it as a simple gat

This class has a constructor that takes two arguments: a JDBC URL and a Squery. Provided that you load the appropriate driver first, you can use this claimport data from any DBMS that has a JDBC driver. Instantiating the class connects to the JDBC URL, executes the query, and returns the ResultSet to the SQL-J statement that called it. For example:

-- loads the driver in Cloudscape

VALUES (new sun.jdbc.odbc.JdbcOdbcDriver() IS NOT NULL)

Cloudscape Version 3.0

Page 242: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips

Clouds

10-8

a

INSERT INTO MusicCategories SELECT * FROM NEW

COM.cloudscape.vti.ExternalQuery(’jdbc:odbc:CloudscapeTutorial’

, ’SELECT * FROM MusicCategories’) AS EQ

You can simplify the complexity of the grammar, if you wish, by creating a view:

CREATE VIEW MSMusicCategories (id, category) AS

SELECT * FROM NEW

COM.cloudscape.vti.ExternalQuery(’jdbc:odbc:CloudscapeTutorial’

, ’SELECT * FROM MusicCategories’) AS EQ

Then just select from the view:

SELECT * FROM MSMusicCategories

Working with Date/Time Formats

Note that java.text.SimpleDateFormat provides complete control over turning dates into strings in a wide variety of formats. See Table A-3, “Mapping of Time and Date Functions to Java Methods”, on page A-4 for details.

Here’s an example:

SELECT NEW java.text.SimpleDateFormat(

’MMMM d, yyyy’).format(travel_date)

FROM FlightBookings

Supplying a Parameter Only Once

If you want to supply a parameter value once and use it multiple times withinquery, put it in the FROM clause with an appropriate CAST:

SELECT phonebook.*

FROM phonebook,

((VALUES (CAST(? AS INT),

CAST(? AS VARCHAR(255)

)

)) AS Choice(choice, search_string)

WHERE

(choice = 1)? firstname.equalsIgnoreCase(search_string) :

(choice = 2)? lastname.equalsIgnoreCase(search_string) :

(choice = 3)? phonenumber.equalsIgnoreCase(search_string) :

FALSE

cape Developer’s Guide

Page 243: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips 10-9

This query selects what the second parameter will be compared to based on the value in the first parameter. Putting the parameters in the FROM clause means that they need to be applied only once to the query, and you can give them names so that you can refer to them elsewhere in the query. In the example above, the first parameter is given the name choice, and the second parameter is given the name search_string.

Defining a Sequence-Number Column

A sequence-number column is a column that stores numbers that increment by one with each insertion. Columns like this are sometimes called autoincrement columns. Cloudscape does not have an autoincrement data type, but you can define a sequence-number column by:

1 Creating a separate single-row table that stores the last-used number.

Creating a separate table allows you to avoid full-table scans. Only a sin-gle row has to be locked.

2 Providing a method that returns the next available number by updating the value in that separate table and then selecting it from that table. (For lock-ing reasons, the update should precede the select.)

For good concurrency, the method should use a separate connection/trans-action. For example:

public static int getNextId() throws SQLException {

Connection conn = DriverManager.getConnection(

"jdbc:cloudscape:myDB");

conn.setAutoCommit(false);

String setNext = "UPDATE getNextValues " +

SET group_id = group_id + 1";

String getNext = "SELECT group_id FROM getNextValues";

int n = 0;

PreparedStatement ps1 = conn.prepareStatement(setNext);

PreparedStatement ps2 = conn.prepareStatement(getNext);

ps1.executeUpdate();

ResultSet rs = ps2.executeQuery();

rs.next();

n = rs.getInt(1);

rs.close();

ps1.close();

ps2.close();

Cloudscape Version 3.0

Page 244: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips

Clouds

10-10

conn.commit();

conn.close();

return n;

}

3 Use the method call to generate the next sequence number, then insert that value into the column:

int a = MyClass.getNextId();

//since we know what the value of the sequence number key,

// we will be able to find our row again.

PreparedStatement ps = conn.prepareStatement(

"INSERT INTO myTable VALUES (?, ?)");

ps.setInt(1, a);

ps.setString(2, myotherdata);

ps.executeUpdate();

NOTE: It is also possible to have Cloudscape generate the value automatically during the insert, as in the following example:

INSERT INTO mytable VALUES ((CLASS MyClass).getNextId(), ?)

(You could even define the default value of the column to be the method call itself.)

NOTE: The drawback to having Cloudscape generate the sequence number automatically when you insert, which is what will happen if you call the method from within the insert statement as shown in this example, is that you have no way of knowing what value was actually inserted for your row. For that reason it makes most sense to use the method call from within your program, as shown in 3 above.

For a detailed example, see the toursDB sample database and the getNextAvailableId in the Person class and getNextAvailableId in the Group class.

Generating Unique Keys

In some situations, such as in a distributed system, sequential integers are not appropriate for primary keys. Cloudscape provides a utility for generating a CHAR(32) key that is unique across databases. This utility is the getUniversalKeyStringValue method in the COM.cloudscape.util.KeyGen class, which generated a string of 32 characters.

You can use this utility in a way similar to the one shown in the example in “Defining a Sequence-Number Column” on page 10-9:

cape Developer’s Guide

Page 245: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips 10-11

s.executeUpdate("CREATE TABLE keytester2 (mykey CHAR(32), "+

"people VARCHAR(10))");

PreparedStatement ps = conn.prepareStatement(

"INSERT INTO keytester2 VALUES (?, ’janets’)");

String b = COM.cloudscape.util.KeyGen.getUniversalKeyStringValue();

ps.setString(1, b);

int j = ps.executeUpdate();

//since we know what the value of the generated key, we will

// be able to find our row again.

ps = conn.prepareStatement(

"SELECT mykey, people FROM keytester2 WHERE mykey = ?");

ps.setString(1, b);

Using Literals to Save Keystrokes

You can use SQL-J literals to avoid having to type out (CLASS java.lang....) constructs:

(0)->MAX_VALUE

-- instead of (CLASS java.lang.Integer)->MAX_VALUE

’’.valueOf(number)

-- instead of (CLASS java.lang.String).valueOf(number)

TRUE.valueOf(string)

-- instead of (CLASS java.lang.Boolean).valueOf(string)

Remember that you can define method aliases to save on keystrokes for invoking static methods.

Integrating External Libraries

You can immediately integrate external libraries such as JGL (from ObjectSpace) and JNL (from Visual Numerics) into your database.

All of the JGL classes, version 2.0 and higher, implement java.io.Serializable, so they can be stored in columns.

JNL provides matrix manipulation, statistical functions to complete those of java.lang.Math, and also a complex type, VisualNumerics.math.Complex, with full math support for it. Here’s an example:

Cloudscape Version 3.0

Page 246: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips

Clouds

10-12

ols

n ies,

em

(CLASS VisualNumerics.math.SFun).log10(double)

Your installation includes a script that you can run to create aliases for some JNL static methods. See readme.html in /util/methodalias for more details.

Using Third-Party Tools

You can hook into any JDBC tool with just our JDBC Driver class name (COM.cloudscape.core.JDBCDriver) and Cloudscape’s JDBC database connection URL.

Cloudscape also provides an ODBC driver, which allows you to use ODBC towith Cloudscape databases. See http://www.cloudscape.com/support/Downloads/ for information.

Accessing and Modifying System Properties

You can access Java system properties within your queries (most useful wherunning in embedded mode; in server mode, you will see the server’s propertnot the client’s).

VALUES (CLASS java.lang.System).getProperty(’jdbc.drivers’)

Also, there are useful utility functions on the basic types, so you can get systproperties in the desired data type:

VALUES TRUE.getBoolean(’weblogic.verbose’)

To find out the system directory:

VALUES (CLASS java.lang.System).getProperty(

’cloudscape.system.home’,

(CLASS java.lang.System).getProperty(’user.dir’))

To find out the canonical path of the system directory:

VALUES NEW java.io.File(

(CLASS java.lang.System).getProperty(

’cloudscape.system.home’,

(CLASS java.lang.System).getProperty(

’user.dir’))).getCanonicalPath()

You can also modify system properties this way:

cape Developer’s Guide

Page 247: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips 10-13

CALL (CLASS java.lang.System).getProperties().put(

’cloudscape.storage.pageSize’, ’8192’)

NOTE: For more information on working with Cloudscape system properties, see Tuning Cloudscape.

Tricks of the VALUES Clause

Multiple Rows

Cloudscape supports the complete SQL-92 VALUES clause; this is very handy in several cases. The first useful case is that it can be used to insert multiple rows:

INSERT INTO OneColumnTable VALUES 1,2,3,4,5,6,7,8

INSERT INTO TwoColumnTable VALUES

(1, ’first row’),

(2, ’second row’),

(3, ’third row’)

Dynamic parameters reduce the number of times execute requests are sent across:

-- send 5 rows at a time:

INSERT INTO ThreeColumnTable VALUES

(?,?,?), (?,?,?), (?,?,?), (?,?,?), (?,?,?)

Mapping Column Values to Return Values

Multiple-row VALUES tables are useful in mapping column values to desired return values in queries:

-- get the names of all departments in Ohio

SELECT DeptName

FROM Depts,

(VALUES (1, ’Shoe’),

(2, ’Laces’),

(4, ’Polish’))

AS DeptMap(DeptCode,DeptName)

WHERE Depts.DeptCode = DeptMap.DeptCode

AND Depts.DeptLocn LIKE ’%Ohio%’

You may also find it useful to store values used often for mapping in a persistent table and then using that table in the query.

Cloudscape Version 3.0

Page 248: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips

Clouds

10-14

pty”

f a

n if

RE d

Creating Empty Queries

Developers using Cloudscape in existing applications may need to create “emqueries with the right result shape for filling in bits of functionality Cloudscapedoes not supply. Empty queries of the right size and shape can be formed ofsingle values table and a “WHERE FALSE” condition:

SELECT *

FROM (VALUES (’’,1,TRUE)) AS ProcedureInfo(ProcedureName,

NumParameters, ProcedureValid)

WHERE FALSE

Inserting a Row of Nulls

You can insert a row of nulls into a table by inserting a null into a single columall the columns are nullable:

INSERT INTO ManyColumnsTable (FirstColumn) VALUES (NULL)

Forcing Garbage Collection and Finalization

In SQL-J, you can force garbage collection and finalization to run:

CALL (CLASS java.lang.System).runFinalization()

CALL (CLASS java.lang.System).gc()

Using a Derived Table to Avoid Redundant Method Calls

If a query has the same method calls both in the SELECT list and in the WHEclause, you may want to avoid that redundancy. You can do that with a derivetable.

For example:

SELECT city.toString() FROM Cities

WHERE city.toString().indexOf(’antia’) > -1

You can rewrite the query like this:

SELECT c FROM (SELECT city.toString() FROM Cities) C (c)

WHERE c.indexOf(’antia’) > -1

cape Developer’s Guide

Page 249: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips 10-15

on’t e

Use RunTimeStatistics to Get an Approximate Row Count for a Table

If you need a fairly good estimate of the number of rows in a large table (but dwant to incur the cost of doing a count(*) or count(indexedColumn), then makuse of the new method getEstimatedRowCount() on RunTimeStatistics. Execute aquery that selects all rows from the table, then call the method.

st.executeQuery("SELECT * FROM table");

// no need to actually retrieve the results, that may be expensive

st.close();

ResultSet rs = st.executeQuery(

"VALUES runtimestatistics.getEstimatedRowCount()");

// just retrieve the return value

rs.next();

int prettyGoodEstimate = rs.getInt(1);

Cloudscape Version 3.0

Page 250: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

SQL-J Tips

Clouds

10-16

cape Developer’s Guide

Page 251: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

e

s”,

ge

T

es for to

Appendix A Mapping of Functions to java.lang Methods

The methods of the java.lang classes map to many of the functions built into other database systems. This appendix lists the ways the methods map to functions.

Functions are often divided into the following categories:

• numericSee Table A-1, “Mapping of Numeric Functions to Java Methods”, on page A-2.

• stringSee Table A-2, “Mapping of String Functions to Java Methods”, on pagA-3.

• time and dateSee Table A-3, “Mapping of Time and Date Functions to Java Methodon page A-4.

• systemSee Table A-4, “Mapping of System Functions to Java Methods”, on paA-5.

• convertSee Table A-5, “Mapping of CONVERT Functions to Methods and CASExpressions”, on page A-6.

The Cloudscape installation includes a script that you can run to create aliasall the java.lang.Math static methods. It also includes a script that you can run

A-1

Page 252: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Mapping of Functions to java.lang Methods

Clouds

A-2

create aliases for some of the VisualNumerics.math static functions. See readme.html in /demo/util/methodalias for more details.

Table A-1 Mapping of Numeric Functions to Java Methods

Function Method Alias with Script

ABS(number) (CLASS java.lang.Math).abs(number)

ABS(number)

ACOS(double) (CLASS java.lang.Math).acos(double)

ACOS(double)

ASIN(double) (CLASS java.lang.Math).asin(double)

ASIN(double)

ATAN(double) (CLASS java.lang.Math).atan(double)

ATAN(double)

ATAN2(double1, double2) (CLASS java.lang.Math).atan2(double1,double2)

ATAN2(double1, double2)

CEILING(double) (CLASS java.lang.Math).ceil(double)

CEILING(double)

COS(double) (CLASS java.lang.Math).cos(double)

COS(double)

COT(double) (CLASS VisualNumerics.math.SFun).cot(double)

COT(double) (with jnl.math.sql script)

DEGREES(number) not available in java.lang.*

not generally available (CLASS java.lang.Math)->E

EXP(double) (CLASS java.lang.Math).exp(double)

EXP(double)

FLOOR(double) (CLASS java.lang.Math).floor(double)

FLOOR(double)

LOG(double) (CLASS java.lang.Math).log(double)

LOG(double)

LOG10(double) (CLASS VisualNumerics.math.SFun).log10(double)

LOG10 (with jnl.math.sql script)

not generally available (CLASS java.lang.Math).min(number1, number2)

must modify script

not generally available (CLASS java.lang.Math).max(number1, number2)

must modify script

MOD(integer1, integer2)

PI() (CLASS java.lang.Math)->PI

POWER(number, power) (CLASS java.lang.Math).pow(number, power)

POW(number, power)

RADIANS(number)

RAND(integer) (CLASS java.lang.Math).random(integer)

RAND(integer)

cape Developer’s Guide

Page 253: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

A-3

ROUND(number, places) (CLASS java.lang.Math).round(number) rounds to 0 places

ROUND(number)

SIGN(number) (number >= 0) ? ‘+’ : ‘-’

SIN( double) (CLASS java.lang.Math).sin( double)

SIN( double)

SQRT(double) (CLASS java.lang.Math).sqrt( double)

SQRT(double)

TAN(double) (CLASS java.lang.Math).tan( double)

TAN(double)

TRUNCATE (number, places) (NEW java.math.BigDecimal( number.doubleValue()).setScale(places.intValue),(CLASS java.math.BigDecimal)->ROUND_FLOOR).doubleValue()

Table A-2 Mapping of String Functions to Java Methods

Function Method

ASCII( string) not available

CHAR(code) not available

CONCAT(string1, string2) string1 || string2 OR

string1.concat( string2)

DIFFERENCE(string1, string2)

INSERT( string1, start, length, string2)

NEW java.lang.StringBuffer( string1).insert( start, string2.substring(0, length)).toString()

LCASE(string) Built-in support with LOWER(string).

string.toLowerCase()

LEFT( string, count) Built-in support with SUBSTRING.

string.substring(0, count)

LENGTH(string) Built-in support with CHAR_LENGTH(string).

string. length()

LOCATE(string1, string2, start) string1.indexOf( string2, start)

LTRIM( string) Built-in support with LTRIM.

REPEAT(string, count)

REPLACE(string1, string2, string3) string1.replace( string2, string3)

strings 2 and 3 must be one char

Table A-1 Mapping of Numeric Functions to Java Methods (continued)

Function Method Alias with Script

Cloudscape Version 3.0

Page 254: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Mapping of Functions to java.lang Methods

Clouds

A-4

RIGHT(string, count) string.substring(string.length()-count, string.length())

RTRIM(string) Built-in support with RTRIM.

SOUNDEX(string)

SPACE(string)

SUBSTRING(string,length) Built-in support with SUBSTRING, SUB-STR.

UCASE(string) Built-in support with UPPER.

Table A-3 Mapping of Time and Date Functions to Java Methods

Function Method

CURDATE() Built-in support with CURRENT_DATE.

CURTIME() Built-in support with CURRENT_TIME.

DAYNAME(date) NEW java.text.SimpleDateFormat(’E’).format(date,

NEW java.lang.StringBuffer(),NEW java.text.FieldPosition

((CLASS java.text.DateFormat)->DAY_OF_WEEK_FIELD))

DAYOFMONTH(date) Built-in support with EXTRACT(DAY FROM date).date.getDate()+1

DAYOFWEEK(date) date.getDay()+1

DAYOFYEAR(date) NEW java.text.SimpleDateFormat(’D’).format(date,NEW java.lang.StringBuffer(), NEW java.text.FieldPosition((CLASS java.text.DateFormat)->DAY_OF_YEAR_FIELD))

HOUR(time) Built-in support with EXTRACT(HOUR FROM time).

time.getHours()

MINUTE(time) Built-in support with EXTRACT(MINUTE FROM time).

time.getMinutes()

MONTH(date) Built-in support with EXTRACT(MONTH FROM date).

date.getMonth()+1

Table A-2 Mapping of String Functions to Java Methods (continued)

Function Method

cape Developer’s Guide

Page 255: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

A-5

MONTHNAME(date) NEW java.text.SimpleDateFormat(’MMMM’).format(date, NEW java.lang.StringBuffer(),NEW java.text.FieldPosition((CLASS java.text.DateFormat)->MONTH_FIELD))

NOW() Built-in support with CURRENT_TIMESTAMP.

QUARTER(date) Built-in support with EXTRACT(MONTH FROM date)

date.getMonth()+1)/4 + 1

SECOND(time) Built-in support with EXTRACT(SECOND FROM time)

time.getSeconds()

TIMESTAMPADD(interval, count, timestamp)

intervals are not yet supported; can use longs

TIMESTAMPDIFF(interval, timestamp1,timestamp2)

intervals are not yet supported; can use longs

WEEK(date) NEW java.text.SimpleDateFormat(’w’).format(date,NEW java.lang.StringBuffer(),NEW java.text.FieldPosition( (CLASS java.text.DateFormat)->WEEK_OF_YEAR_FIELD))

YEAR(date) Built-in support with EXTRACT (YEAR FROM date).

date.getYear()

Table A-4 Mapping of System Functions to Java Methods

Function Method

DATABASE() not supported yet

(Use JDBC to get the database connection URL. See “Retrieving the Database Connection URL” on page 10-2.)

IFNULL(expression, value) (expression = IS NULL)?value:expression

USER() Built-in support with USER.

(OR use JDBC)

Table A-3 Mapping of Time and Date Functions to Java Methods (continued)

Function Method

Cloudscape Version 3.0

Page 256: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Mapping of Functions to java.lang Methods

Clouds

A-6

Table A-5 Mapping of CONVERT Functions to Methods and CAST Expressions

Function MethodEquivalent SQL-J CAST Expression

CONVERT(value, BIGINT) (value).longValue() CAST (value AS LONGINT)

CONVERT(value, BINARY) not available CAST (value AS BIT(length))

CONVERT(value, BIT) (value).booleanValue() CAST (value AS BOOLEAN)

CONVERT(value, CHAR) (value).toString() CAST (value AS CHAR(length))

CONVERT(value, DATE) (CLASS java.sql.Date).valueOf((CLASSjava.lang.String).valueOf(value))

(If source value is a string, do not use String.val-ueOf)

CAST (value AS DATE)

CONVERT(value, DECIMAL) NEW java.math.BigDecimal((value).doubleValue())

CAST (value AS DECIMAL(precision, scale))

CONVERT(value, DOUBLE) (value).doubleValue() CAST (value AS DOUBLE PRECISION)

CONVERT(value, FLOAT) (value).doubleValue() CAST (value AS FLOAT (precision))

CONVERT(value, INTEGER) (value).intValue() CAST (value AS INTEGER)

CONVERT(value, LONGVARBINARY)

CAST (value AS BITVARYING(length))

CONVERT(value, LONGVARCHAR)

(value).toString() CAST (value AS VARCHAR(length))

CONVERT(value, REAL) (value).floatValue() CAST (value AS REAL)

CONVERT(value, SMALLINT)

(value).shortValue() CAST (value AS SMALLINT)

CONVERT(value, TIME) (CLASS java.sql.Time).valueOf((CLASSjava.lang.String).valueOf(value))

CAST (value AS TIME)

cape Developer’s Guide

Page 257: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

A-7

CONVERT(value, TIMESTAMP)

(CLASS java.sql.Timestamp).valueOf((CLASSjava.lang.String).valueOf(value))

(If source value is a string, do not use String.valueOf)

CAST (value AS TIMESTAMP)

CONVERT(value, TINYINT) (value).byteValue() CAST (value AS TINYINT)

CONVERT(value, VARBINARY)

not available CAST (value AS BITVARYING(length))

CONVERT(value, VARCHAR) (value).toString() CAST (value AS VARCHAR(length))

Table A-5 Mapping of CONVERT Functions to Methods and CAST Expressions (contin-

Function MethodEquivalent SQL-J CAST Expression

Cloudscape Version 3.0

Page 258: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Mapping of Functions to java.lang Methods

Clouds

A-8

cape Developer’s Guide

Page 259: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Index

AAccess

full (read-write) vs. read-only 8-24Accessing databases 2-23Accessing read-only databases from class path

3-15APIs for public classes and interfaces 1-3Archiving read-only databases 3-13Arrays

using external libraries to support 10-6Attributes to database connection URL 2-21–

2-25setting 2-21specifying with Properties object 2-25

Authentication 8-5–8-20definition 8-1

Authentication providerspecifying 8-8

Authorization 8-23–8-26Authorization identifiers 8-21Auto-commit

and transactions 6-4turning off 2-24, 6-6turning off using database connection URL

attribute 2-24using 6-4

Autoincrement columnemulating 10-9

Automatic bootingof databases in system 2-7

Available databaseslist of provided by databaseName attribute

9-2

BBacking up databases 2-13Batch files 1-3

Bitsmanipulating 10-5

CCase-insensitive sorts 10-2CAST function

use of 4-9Class aliases 4-2Class path

accessing databases from 2-18setting 1-5

Class versioning 5-11Classes

storing in database 3-17–3-26classpath subsubprotocol 2-27client.jar 3-10Client/server environments 3-10

deploying client applications 3-10deploying Cloudscape for 3-10description 3-3–3-10

Cloudscapemultiple client applications accessing 3-4

Cloudscape environmentsdescription 3-1

Cloudscape system 2-5cloudscape.jar 3-8, 3-10cloudscape.LOG 2-6cloudscape.properties file 2-5, 2-9cloudscape.system.home

used to define system directory 2-9CLOUDSCAPE_INSTALL environment

variable 1-1COM.cloudscape.aggregates.AggregateDefinit

ion 5-27COM.cloudscape.aggregates.Aggregator 5-28COM.cloudscape.core.AbstractDataSource 7-2COM.cloudscape.core.BasicDataSource 7-2

IN-1

Page 260: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

IN-2

COM.cloudscape.core.DataSourceFactory 7-2COM.cloudscape.core.LocalConnectionPoolD

ataSource 7-2COM.cloudscape.core.XaDataSource 7-2COM.cloudscape.database.JBMSException

5-8COM.cloudscape.database.TriggerExecutionC

ontextuse of in trigger actions 5-32

COM.cloudscape.database.UserUtility 8-24COM.cloudscape.triggers.TriggerNewTransiti

onRows 5-32COM.cloudscape.triggers.TriggerOldTransitio

nRows 5-32COM.cloudscape.types.TypeDescriptor 5-28COM.cloudscape.vti.VTICosting 5-22COM.cloudscape.vti.VTIMetaDataTemplate

5-26, 5-26COM.cloudscape.vti.VTITemplate 5-25, 5-26Concurrency 6-13–6-25Connecting to databases

in embedded mode 2-28when path is ambiguous because of databases

in class path 3-16when path is ambiguous with databases in file

system 3-16Connections

getting 6-2Creating a database

using database connection URL attribute 2-23

Cursorsall result sets as 6-3and Cloudconnector 6-9naming 6-9requirements for being updatable 6-9scrolling insensitive 6-12updatable 6-9working with 6-7–6-13

DData

importing 10-7Data sources 7-2Database class loading 3-17–3-26Database connection URL

description 2-4features common to embedded and client/

server versions 2-4retrieving from database 10-2syntax 2-26

Database design issues 4-4Database encryption 8-27Database name attribute

use of in database connection URL 2-23Database pages

description 2-15DatabaseMetaData precompiled queries 9-5Databases

accessing 2-23backing up 2-13configuring 2-15connecting 2-17–2-20connecting to outside system 2-17connecting to within system 2-17controlling access to 8-23convention for specifying connection path

when outside system 2-18creating 2-23description of in Cloudscape system 2-12dropping 2-13encrypting 8-27encrypting upon creation 2-24shutting down individually 2-22upgrading 1-5, 2-25

Database-side JDBC methods 5-1–5-6and SQLExceptions 5-6definition 4-13, 5-2using nested connections 5-2using non-nested connections 5-6

Database-side methodsdefinition 4-13, 5-2

Deadlock detection 6-24Deadlocks

description 6-22detecting 6-25

definition 8-1Deployment environments 3-1

choosing 3-5Deployment modes

threading/connection modes and 6-28Derived tables

using to avoid redundant method calls 10-14directory subsubprotocol 2-18, 2-27Dirty reads

definition 6-14Disk encryption 8-2DriverPropertyInfo Array 9-3Dropping databases 2-13Dynamic parameters

need to cast data type of as method parameters 4-12

Cloudscape Developer’s Guide

Page 261: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Index IN-3

EEmbedded applications

deploying 3-2Embedded environments 3-2, 3-8

Cloudscape as single-user database 3-2how applications interact with Cloudscape in

3-3how to deploy Cloudscape 3-8multiple connections and threads 3-3

Encrypted databasesbooting 2-25, 8-29creating 8-28

Encrypting databases 8-2Error log 2-6Exclusive locks

definition 6-18Explicit close of JDBC objects 6-6External data

accessing 4-19, 10-7External directory services

used to provide user authentication 8-8External libraries

integrating 10-11External resources

managing by storing URLs 10-6External virtual tables

requirements for 5-16Externalizable

use of compared to Serializable 5-9

FFile descriptors

configuring to run Cloudscape 1-7Full access

definition 8-25Functions

emulating with java.lang methods 10-2how java.lang classes map to A-1–A-7

Functions (SQL-92 style)emulating 4-15

GGetting a nested connection

using database connection URL attribute 2-24

using getCurrentConnection() built-in method 5-3

IIndexes

limitations of 2-15not supported for long rows 2-15

Information log 2-6description 2-9

Input/output streamsand serializable objects 5-16

Installation directorylayout of 1-1

INSTANCEOFuse of 4-9

interrupt callscaught by Cloudscape 2-29

Invoking methodswhen method does not return a value 4-12

IOExceptionsindicating need to relax file descriptors limit

1-7Isolation levels 6-13–6-25

Jjar directory

function 2-12Jar files

databases in 3-13storing in database 3-17–3-26

jar subsubprotocol 2-27Java

extensions to SQL-J 4-1–4-18Java data types

and implementation of equals 5-43deploying classes for 3-6storing 4-4

Java objectsdefining a column to store 4-3inserting from application 4-4retrieving and updating 4-5storing in tables 4-3–4-7

Java stored proceduresas database-side methods with classes stored

in database 4-13java.sql.Connection.TRANSACTION_READ_C

OMMITTED 6-14java.sql.Connection.TRANSACTION_SERIALI

ZABLE 6-14java.sql.Driver.getPropertyInfo 9-2JDBC

tutorial for 2-1JDBC Connections 6-1–6-6

definition 6-2JDBC driver

description 2-3JDBC driver (embedded) 2-26

starting 2-28JDBC metadata for Java data types 9-1

Cloudscape Version 3.0

Page 262: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

IN-4

JDBC Statementdefinition 6-2

JNDI properties for user authorizationsetting 8-13

jndi.jarrequired for LDAP user authorization 8-9,

8-12JVMs (Java Virtual Machines)

verified for Cloudscape 1-4

LLDAP directory services

used to provide user authentication 8-9ldap.jar

required for LDAP user authorization 8-9Limitations

in current version 2-15Literals

using to save keystrokes 10-11Locking 6-13–6-25Locks

scope of 6-18log directory

function 2-12Logic

storing in database 3-17–3-26

MMethod invocation

need to cast data type of dynamic parameters 4-12

using to refine search conditions 4-9when class not stored in database 4-10

Methodsaccessing when column stores superclass or

interface 4-9invoking 4-8–4-12

Multiple connectionsfrom multiple applications connecting to

server 6-29from single application running in embedded

mode 6-29in single application 6-27–6-30

Multiple JVMs accessing single systemprohibition of 2-6

Multiple threads sharing single connection 6-30–6-32

Multi-threaded applications 6-28Multi-user database access

programming for 6-29

NNested connections

definition 6-3getting 2-24, 5-2, 5-2limitations of 5-3

Network encryption 8-2NIS Directory Service Plus

used to provide user authentication 8-12nisplus.jar

required for NIS+ user authorization 8-12Non-repeatable reads

definition 6-15

OObject storage 4-3–4-7Objects

inserting 4-4Orderable Java data types

and comparison operators 5-44and implementation of compareTo 5-42programming classes for 5-41requirements 5-42

PPasswords 8-18

no encryption of 8-20providing 8-20

Permissions 8-25Phantom reads

definition 6-15Properties

defined for system in cloudscape.properties 2-5

providerutil.jarrequired for LDAP user authentication 8-9

provider.jarrequired for LDAP user authentication 8-12

RRead-only access

definition 8-25Read-only databases

accessing in zip/jar files 3-14archiving to jar or zip files 3-13creating 3-12deploying 3-13putting in class path 3-15upgrading 3-16working with 3-12–3-16

Recovery 2-14, 2-14Referential actions

and triggers 5-31

Cloudscape Developer’s Guide

Page 263: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

Index IN-5

Referential integrityvia triggers 5-31

Replication systemswhat to deploy on server and on remote

machines 3-10Resource manager

Cloudscape as in J2EE system 7-1Restarting Cloudscape within same JVM 2-8ResultSets

behavior of with auto-commit 6-11scrolling insensitive (JDBC 2.0) 6-12silently closed with auto-commit 6-4working with 6-7–6-13

Rollbackimplicit vs. explicit 6-6

Row countapproximate 10-15

SSample applications and databases

description 1-3Schemas

and users 8-21Scrolling insensitive cursors 6-12Security

configuring 8-3Security features 8-1

limitations of 8-31seg0 directory 2-12Sequence-number column

emulating 10-9Serializable

use of compared to Externalizable 5-9Serialization

description 5-8–5-16incompatibility for pre-1.1.6 and post-1.2

databases 1-4requirements for 5-9

serialVersionUIDuse of 5-12

service.properties file 2-12Shared locks

definition 6-18Shell scripts 1-3Shutdown

description 2-14Shutting down a single database 2-14, 2-22Shutting down Cloudscape

using database connection URL attribute 2-22

Sortscase-insensitive 10-2

SQLExceptionschaining of 6-34importance of not catching within database-

side methods 5-6user-defined (38001-38999) 5-8working with 6-34

SQLWarnings 6-35SSL 8-2, 8-30Starting Cloudscape

embedded mode 2-28Start-up

description 2-14Statements shared by threads

dangers of 6-33Static fields 4-12

not serialized 5-10Static methods 4-12

executing 4-11Stored prepared statements

need for recompiling before transferring to read-only media 3-12

Stored proceduresreplaced by Java methods 4-13using method invocation to emulate 10-3

Subprotocolpart of database connection URL syntax

2-23, 2-27Subsubprotocol

part of database connection URL syntax 2-23, 2-27

Systemdescription 2-5

System directory 2-5creating and naming directory for 2-11default 2-9specifying 2-9

System propertiesaccessing from within SQL-J 10-12

System tablesquerying 4-17

TThreads

notifying 2-29sleep and interrupt calls 2-29

tmp directoryfunction 2-12

Transaction anomalies in generic database systems

description 6-14Transaction isolation levels 6-13–6-25Transactions 6-1–6-6

Cloudscape Version 3.0

Page 264: Cloudscape Developer's Guide · Accessing Databases-in-a-Jar in the Class Path 3-15 ... Orderable Java Data Types 4-7 Invoking Methods and Accessing Fields 4-8 Executing Methods 4-8

IN-6

definition 6-3TRANSACTION_READ_COMMITTED

isolation level 6-16TRANSACTION_SERIALIZABLE isolation

level 6-16Transient

use of to optimize object storage 5-10Triggers

accessing before and after rows 5-32and exceptions 5-38and separate connections 5-40and user-defined SQLExceptions 5-38automatic rollback of trigger actions 5-39examples of trigger actions 5-33limitations of trigger actions 5-31long-running trigger actions in separate

thread 5-41programming trigger actions 5-30–5-41transactionally-independent trigger actions

5-40use of SQL and Java in trigger actions 5-31use of to perform referential actions 5-31

Type correspondencebetween SQL-J and Java types 4-15–4-17

UUnique keys

generating 10-10Upgrades 1-5, 2-25

for synchronization databases 1-7upgrade=true (database connection URL

attribute) 1-7Upgrading read-only databases 3-16User authentication 8-1, 8-5–8-20

enabling 8-7programming applications for 8-19use of external directory service for 8-8

User authorization 8-23–8-26definition 8-2for databases 8-23providing your own 8-13

User namesproviding 8-20

User-defined aggregatesexamples of 5-29programming 5-27–5-30

Usersand schemas 8-21Cloudscape’s built-in repository 8-17defining for a system 8-8providing a name and password for in

connection 2-24UserUtility 8-24

VVALUES clause

power of 10-8, 10-13Versioning of classes 5-11

compatible changes for serialization 5-11mini-tutorial 5-12using 5-12

Virtual Table Interface (VTI) 4-19example 10-7power of 5-21requirements of 5-17

VTIsand costing 5-22and implementation of ResultSet and

ResultSetMetaData and 5-17and single compilation requirement 5-23built-in 5-26compile-time ResultSetMetaData 5-20default parameters 5-22determining compile time or run time 5-21estimating cost of 5-24examples of 5-26parameter rules 5-21programming 5-16–5-27templates for creating 5-25

ZZip files

databases in 3-13

Numerics100% Pure Java certification 1-4

Cloudscape Developer’s Guide