CUBRID 10.0 User Manual

Table of Contents

Introduction to Manual

Manual Contents

The contents of the CUBRID Database Management System (CUBRID DBMS) product manual are as follows:

  • Introduction to CUBRID: This chapter provides a description of the structure and characteristics of the CUBRID DBMS.
  • Getting Started: The "Getting Started with CUBRID" provides users with a brief explanation on what to do when first starting CUBRID. The chapter contains information on how to install and execute the system, used ports on accessing to CUBRID and provides simple explanations on the CUBRID query tools.
  • CSQL Interpreter: CSQL is an application that allows you to use SQL statements through a command-driven interface. This chapter explains how to use the CSQL Interpreter and associated commands.
  • CUBRID SQL: This chapter describes SQL syntaxes such as data types, functions and operators, data retrieval or table manipulation. The chapter also provides SQL syntaxes used for indexes, triggers, partitioning, serial and user information changes, etc.
  • CUBRID Management: This chapter provides instructions on how to create, drop, back up, restore and migrate a database, configuring globalization, and executing CUBRID HA. Also it includes instructions on how to use the cubrid utility, which starts and stops the server, broker, and CUBRID Manager server, etc. Also, this chapter provides instructions on setting system parameters that may influence the performance. It provides information on how to use the configuration file for the server and broker, and describes the meaning of each parameter.
  • API Reference: The "Performance Tuning" chapter provides instructions on setting system parameters that may influence the performance. This chapter provides information on how to use the configuration file for the server and broker, and describes the meaning of each parameter.
  • Release Notes: This chapter provides a description of additions, changes, improvements and bug fixes.

Glossary

CUBRID is an object-relational database management system (ORDBMS), which supports object-oriented concepts such as inheritance. In this manual, relational database terminologies are also used along with object-oriented terminologies for better understanding. Object-oriented terminologies such as class, instance and attribute is used to describe concepts including inheritance, and relational database terminologies are mainly used to describe common SQL syntax.

Relational Database CUBRID
table class, table
column attribute, column
record instance, record
data type domain, data type

Manual Conventions

The following table provides conventions on definitions used in the CUBRID Database Management System product manual to identify "statements," "commands" and "reference within texts."

Convention Description Example
Italics Italics type represents variable names and user-defined values (system, database, table, column and file) in examples. persistent : stringVariableName
Boldface Boldface type represents names such as the member function name, class name, constants, CUBRID keyword or names such as other required characters. fetch ( ) member function
Constant Width Constant Width type represents segments of code example or describes a command's execution and results. csql database_name
UPPER-CASE UPPER-CASE represents the CUBRID keyword (see Boldface). SELECT
Single Quotes (' ') Single quotes (' ') are used with braces and brackets and represent the necessary sections of a syntax. Single quotes are also used to enclose strings. {'{' const_list '}'}
Brackets ([ ]) Brackets ([ ]) represents optional parameters or keywords. [ ONLY ]
Vertical bar ( | ) Vertical bar (|) represents that one or another option can be specified. [ COLUMN | ATTRIBUTE ]
A parameter enclosed by braces ({ }) A parameter enclosed by braces represents that one of those parameters must be specified in a statement syntax. CREATE { TABLE | CLASS }
A value enclosed by braces ({ }) A value enclosed by braces an element consisting of collection. {2, 4, 6}
Braces with ellipsis ({ }...) Braces before an ellipsis represents that a parameter can be repeated. {, class_name }...
Angle brackets (< >) Angle brackets represent a single key or a series of key strokes. <Ctrl+n> }...

Version Name and Version String Conventions

Rules for version naming and string since CUBRID 9.0 are as follows:

  • Version name: CUBRID x.x Patch x (major version, minor version, patch version if necessary) CUBRID 9.2 Patch 1 (CUBRID 9.2 P1 in short)
  • Version string: x.x.x.x (major version, minor version, patch version, build number) 9.2.1.0012

Rules for version naming and string before CUBRID 9.0 are as follows:

  • Version name: CUBRID 2008 Rx.x Patch x (2008 for major version, minor version, patch version, build number) CUBRID 2008 R4.1 Patch 1
  • Version string: 8.x.x.x (major version, minor version, patch version, build number) 8.4.1.1001

Introduction to CUBRID

This chapter explains the architecture and features of CUBRID. CUBRID is an object-relational database management system (DBMS) consisting of the database server, the broker, and the CUBRID Manager. It is optimized for Internet data services, and provides various user-friendly features.

This chapter covers the following topics:

  • System Architecture: This page contains information about database volume structure, server process, broker process, interface modules, etc.
  • Features of CUBRID: This page contains information about transaction, backup and recovery, partitioning, index, HA, Java stored procedure, click counter, relational data model extension, etc.

System Architecture

Process Structure

CUBRID is an object-relational database management system (DBMS) consisting of the database server, the broker, and the CUBRID Manager.

  • As the core component of the CUBRID database management system, the database server stores and manages data in multi-threaded client/server architecture. The database server processes the queries requested by users and manages objects in the database. The CUBRID database server provides seamless transactions using locking and logging methods even when multiple users use the database at once. It also supports database backup and restore for the operation.
  • The broker is a CUBRID-specific middleware that relays the communication between the database server and external applications. It provides functions including connection pooling, monitoring, and log tracing and analysis.
  • The CUBRID Manager is a GUI tool that allows users to remotely manage the database and the broker. It also provides the Query Editor, a convenient tool that allows users to execute SQL queries on the database server. For more information about CUBRID Manager, see http://www.cubrid.org/wiki_tools/entry/cubrid-manager.

Note

CUBRID Query Browser is a light version of CUBRID Manager and provides only the features which application developers require: the database management and query editor features. For more details on CUBRID Query Browser, see http://www.cubrid.org/wiki_tools/entry/cubrid-query-browser .

_images/image1.png
Database Volume Structure

The following diagram illustrates the CUBRID database volume structure. As you can see, the database is divided into three volumes: permanent, temporary and backup. This chapter will examine each volume and its characteristics.

_images/image2.png

For commands to create, add or delete the database volume, see createdb, addvoldb and deletedb.

Permanent Volume

Permanent volume is a database volume that exists permanently once it is created. Its types include generic, data, temp, index, control, active log and archive log.

Generic Volume

For efficient management, the volume type to be added to the database can be specified as one of the following: data, temp or index. If the volume type is not specified, it is specified as a generic volume and it stores data and index. However, schema is stored only on the generic volume; there is no specific volume type for storing schema.

It is specified as the generic volume when a volume is automatically increased.

Data Volume

Data volume is a space for storing data such as instances, tables and multimedia data.

Temp Volume

Temp volume is a space where the intermediate and final results of query processing and sorting are temporarily stored. It is also called the permanent temp volume to distinguish it from the temporary temp volume that will be described below. The temp volume is a permanently-occupied space, meaning that data in the space is temporary stored and later destroyed. Therefore, when CUBRID restarts, the data in the temp volume space is initialized and the related log information is removed.

The examples of queries that can use permanent temp volume or temporary temp volume are as follows:

  • Queries creating the resultset like SELECT
  • Queries including GROUP BY or ORDER BY
  • Queries including a subquery
  • Queries executing sort-merge join
  • Queries including the CREATE INDEX statement

When executing the queries above, the temp volume is used after exhausting the memory space (the space size is determined by the system parameter temp_file_memory_size_in_pages specified in cubrid.conf) assigned to store SELECT results or sort the data. The order in which the storage space is used to store the results of query processing and sorting is as follows: When the current storage space is exhausted, the next storage space is used.

  • temp_file_memory_size_in_pages memory secured by the system parameter
  • Permanent temp volume
  • Temporary temp volume (for details, see the below)

Index Volume

Index volume is a space that holds the index information for query processing or integrity constraint checks.

Control File

The control file contains the volume, backup and log information in the database.

  • Volume Information: The information that includes names, locations and internal volume identifiers of all the volumes in the database. When the database restarts, the CUBRID reads the volume information control file. It records a new entry to that file when a new database volume is added.
  • Backup Information: Locations of all the backups for data, index, and generic volumes are recorded to a backup information control file. This control file is maintained where the log files are managed.
  • Log Information: This information contains names of all active and archive logs. With the log information control file, you can verify the archive log information. The log information control file is created and managed at the same location as the log files.

Control files include the information about locations of database volumes, backups and logs. Since these files will be read when the database restarts, users must not modify them arbitrarily.

Active Log

Active log is a log that contains recent changes to the database. If a problem occurs, you can use active and archive logs to restore the database completely up to the point of the last commit before the occurrence of the fault.

Archive Log

Archive log is a volume to store logs continuously created after exhausting available active log space that contains recent changes. If the value of system parameter log_max_archives is larger than 0, the archive log volume will be generated only after exhausting available active log volume space. The initial value is set to 0 when installing CUBRID. The number of archive log files is kept on the storage by setting the value of log_max_archives. The unnecessary archive log files should be deleted for getting the free space by the configuration of log_max_archives, but this value should be set properly to use for restoring the database.

To get more information on the above, see Managing Archive Logs.

Background Archive Log

Background archive log is a volume used in the background with log archiving temporarily before creating archive logs. It is created as the same volume size as active log and stored.

Temporary Volume

Temporary volume has the opposite meaning to the permanent volume. That is, the temporary volume is a storage created only when the accumulated data exceeds the space specified by the user as the permanent volume. The temporary volume is destroyed when the server process terminates. One of such volumes created or destroyed temporarily is the temporary temp volume.

Temporary Temp Volume

Temporary temp volume is a temporary volume created temporarily by the system after exhausting the space specified as the permanent temp volume, whereas the temporary volume belongs to the permanent volume with the permanent space specified. Because cost to create a temporary temp volume is high, DBA should assign an appropriate size of volume depending on situation to enhance performance.

DBA should consider space where temporary temp volume can be created when creating a database. Once temporary temp volume is created, it is maintained until a database restarts and its size cannot be reduced. It is recommended to make temporary temp volume automatically delete by restarting a database if its size is too big.

  • File name of the temporary temp volume: The file name of the temporary temp volume of CUBRID has the format of db_name_tnum, where db_name is the database name and num is the volume identifier. The volume identifier is decremented by 1 from 32766.
  • Configuring the temporary temp volume size: The number of temporary temp volumes to be created is determined by the system depending on the space size needed for processing transactions. However, users can limit the temporary temp volume size by configuring the temp_file_max_size_in_pages parameter value in the system parameter configuration file (cubrid.conf). The default value is -1, which means it can be created as long as free space is available. If the temp_file_max_size_in_pages parameter value is configured to 0, the temporary temp volume will not be created even after exhausting the permanent temp volume.
  • Configuring storing location of the temporary temp volume: By default, the temporary temp volume is created where the first database volume was created. However, you can specify a different directory to store the temporary temp volume by configuring the temp_volume_path parameter value.
  • Deleting the temporary temp volume: The temporary temp volume exists temporarily only while the database is running. Therefore, you must not delete the temporary temp volume when running servers. The temporary temp volume is deleted if database servers are normally terminated while it is deleted when the servers restart if database servers are abnormally terminated.
Backup Volume

Backup volume is a database snapshot; based on such backup and log volumes, you can restore transactions to a certain point of time.

You can use the cubrid backupdb utility to copy all the data needed for database restore, or configure the backup_volume_max_size_bytes parameter value in the database configuration file (cubrid.conf) to adjust the backup volume partitioning size.

Database Server

Database Server Process

Each database has a single server process. The server process is the core component of the CUBRID database server, and handles a user's requests by directly accessing database and log files. The client process connects to the server process via TCP/IP communication. Each server process creates threads to handle requests by multiple client processes. System parameters can be configured for each database, that is, for each server process. The server process can connect to as many client processes as specified by the max_clients parameter value.

Master Process

The master process is a broker process that allows the client process to connect to and communicate with the server process. One master process runs for each host. (To be exact, one master process exists for each connection port number specified in the cubrid.conf system parameter file.) While the master process listens on the TCP/IP port specified, the client process connects to the master process through that port. The master process changes a socket to server port so that the server process can handle connection.

Execution Mode

All CUBRID programs except the server process have two modes: client/server mode and standalone mode.

  • In client/server mode, applications access server processes by operating themselves as client processes.
  • In standalone mode, applications include functionalities of server processes so that the applications can access database files by themselves.

For example, database creation and restore utilities run in standalone mode so they can use the database exclusively by denying the access by multiple users. Another example is that the CSQL Interpreter can either connect to the server process in client/server mode or execute SQL statements by accessing the database in standalone mode. Note that one database cannot be accessed simultaneously by server processes and standalone programs.

Broker

The broker is a middleware that allows various application clients to connect to the database server. As shown below, the CUBRID system, which includes the broker, has multi-layered architecture consisting of application clients, cub_broker, cub_cas, and cub_server (database server).

_images/image3.png

Application Client

The interfaces that can be used in application clients include C-API (CCI, CUBRID Call Interface), ODBC, JDBC, PHP, Python, Ruby, OLE DB, ADO.NET, Node.js, etc.

cub_cas

cub_cas (CUBRID Common Application Server and broker application server (CAS in short)) acts as a common application server used by all the application clients that request connections. cub_cas also acts as the database server's client and provides the connection to the database server upon the client's request. The number of cub_cas(s) running in the service pool can be specified in the cubrid_broker.conf file, and this number is dynamically adjusted by cub_broker.

cub_cas is a program linked to the CUBRID database server's client library and functions as a client module in the database server process (cub_server). In the client module, tasks such as query parsing, optimization, execution plan creation are performed.

cub_broker

cub_broker relays the connection between the application client and the cub_cas. That is, when an application client requests access, the cub_broker checks the status of the cub_cas through the shared memory, and then delivers the request to an accessible cub_cas . It then returns the processing results of the request from the cub_cas to the application client.

The cub_broker also manages the server load by adjusting the number of cub_cas (s) in the service pool and monitors and manages the status of the cub_cas. If the cub_broker delivers the request to cub_cas but the connection to cub_cas 1 fails because of an abnormal termination, it sends an error message about the connection failure to the application client and restarts cub_cas 1. Restarted cub_cas 1 is now in a normal stand-by mode, and will be reconnected by a new request from a new application client.

Shared Memory

The status information of the cub_cas is stored in the shared memory, and the cub_broker refers to this information to relay the connection to the application client. With the status information stored in the shared memory, the system manager can identify which task the cub_cas is currently performing or which application client's request is currently being processed.

Interface Module

CUBRID provides various Application Programming Interfaces (APIs). The following APIs are supported by CUBRID as follows:

  • JDBC: A standard API used to create database applications in Java.
  • ODBC: A standard API used to create database applications on Windows. ODBC driver is written based on CCI library.
  • OLE DB: An API used to create COM-based database applications on Windows. OLE DB provider is written based on CCI library.
  • PHP: CUBRID provides a PHP interface module to create database applications in the PHP environment. PHP driver is written based on CCI library.
  • CCI: CCI is a C language interface provided by CUBRID. The interface module is provided as a C library.

All interface modules access the database server through the broker. The broker is a middleware that allows various application clients to connect to the database server. When it receives a request from an interface module, it calls a native C API provided by the database server's client library.

You can find the latest information on interface modules; visit the Web site at http://www.cubrid.org/wiki_apis.

CUBRID Characteristics

Transaction Support

CUBRID supports the following features to completely ensure the atomicity, consistency, isolation and durability in transactions.

  • Supporting commit, rollback, savepoint per transaction
  • Ensuring transaction consistency in the event of system or database failure
  • Ensuring transaction consistency between replications
  • Supporting multiple granularity locking of databases, tables and records
  • Resolving deadlocks automatically

Database Backup and Restore

A database backup is the process of copying CUBRID database volumes, control files and log files; a database restore is the process of restoring the database to a certain point in time using backup files, active logs and archive logs copied by the backup process. For a restore, there must be the same operating system and the same version of CUBRID installed as in the backup environment. The backup methods which CUBRID supports include online, offline and incremental backups; the restore methods include restore using incremental backups as well as partial and full restore.

Table Partitioning

Partitioning is a method by which a table is divided into multiple independent logical units. Each logical unit is called a partition, and each partition is divided into a different physical space. This will lead performance improvement by only allowing access to the partition when retrieving records. CUBRID provides three partitioning methods:

  • Range partitioning: Divides a table based on the range of a column value
  • Hash partitioning: Divides a table based on the hash value of a column
  • List partitioning: Divides a table based on the column value list

Supports a Variety of Index Functions

CUBRID supports the following index functions to utilize indexes while executing a variety of conditional queries.

  • Descending Index Scan: Descending Index Scan is available only with Ascending Index Scan, without creating separate descending indexes.
  • Covering Index: When the column of a SELECT list is included in the index, the requested data can be obtained with an index scan.
  • ORDER BY clause optimization: If the required record sorting order is identical to the order of indexes, no additional sorting is required (Skip ORDER BY).
  • GROUP BY clause optimization: If all columns in the GROUP BY clause are included in the indexes, they are available to use while executing queries. Therefore, no additional sorting is required (Skip GROUP BY).

HA feature

CUBRID provides High Availability(HA) feature to minimize system down time while continuing normal operation of server in the event of hardware, software, or network failure. The structure of CUBRID HA is shared-nothing. CUBRID monitors its system and status on a real time basis with the CUBRID Heartbeat and performs failover when failure occurs. It follows the two steps below to synchronize data from the master database server to slave database server.

  • A transaction log multiplication step where the transaction log created in the database server is replicated in real time to another node
  • A transaction log reflection step where data is applied to the slave database server through the analysis of the transaction log being replicated in real time

Java Stored Procedure

A stored procedure is a method to decrease the complexity of applications and to improve the reusability, security and performance through the separation of database logic and middleware logic. A stored procedure is written in Java (generic language), and provides Java stored procedures running on the Java Virtual Machine (JVM). To execute Java stored procedures in CUBRID, the following steps should be performed:

  • Install and configure the Java Virtual Machine
  • Create Java source files
  • Compile the files and load Java resources
  • Publish the loaded Java classes so they can be called from the database
  • Call the Java stored procedures

Click Counter

In the Internet environment, it is common to store and keep counting information like page view in the database to track search history.

The above scenario is generally implemented by using the SELECT and UPDATE statements; SELECT retrieves the data and UPDATE increases the number of clicks for the retrieved queries.

This approach can cause significant performance degradation due to increased lock contention for UPDATE when a number of SELECT statements are executed against the same data.

To address this issue, CUBRID introduces the new concept of the Click Counter that will support optimized features in the Web in terms of usability and performance, and provides the INCR() function and the WITH INCREMENT FOR statement.

Extending the Relational Data Model

  • Collection

    For the relational data model, it is not allowed that a single column has multiple values. In CUBRID, however, you can create a column with several values. For this purpose, collection data types are provided in CUBRID. The collection data type is mainly divided into SET, MULTISET and LIST; the types are distinguished by duplicated availability and order.

    • SET: A collection type that does not allow the duplication of elements. Elements are stored without duplication after being sorted regardless of their order of entry.
    • MULTISET: A collection type that allows the duplication of elements. The order of entry is not considered.
    • LIST: A collection type that allows the duplication of elements. Unlike with SET and MULTISET, the order of entry is maintained.
  • Inheritance

    Inheritance is a concept to reuse columns and methods of a super class (table) in those of a sub class. CUBRID supports reusability through inheritance. By using inheritance provided by CUBRID, you can create a super class with some common columns and then create a sub class inherited from the super class with some unique columns added. In this way, you can create a database model which can minimize the number of columns.

Installing and Upgrading

For information about ports used by CUBRID, please refer to Port Setting section; in Linux, every configuration except for APPL_SERVER_PORT is same as Windows.

You can download various CUBRID tools and drivers in http://www.cubrid.org/downloads.

Installing and Running CUBRID

Supported Platforms and System Requirements

The platforms supported by CUBRID and hardware/software requirements for the installation are as follows:

Supported Platforms Required Memory Required Disk Space Required Software
  • Windows 32/64 Bit Windows 7
  • Linux family 64 Bit(Linux kernel 2.4, glibc 2.3.4 or higher)
1GB or more 2GB or more(*) JRE/JDK 1.6 or higher (Required when Java Stored Procedure is required)

(*): Requires a 500 MB of free disk space on the initial installation; requires approximately 1.5 GB of free disk space with a database creating with default options.

Beginning with 2008 R4.0, CUBRID Manager Client is not automatically installed when installing the CUBRID package. For this reason, if you require CUBRID Manager you must install it separately. The CUBRID can be downloaded from http://ftp.cubrid.org.

Including CUBRID Query Browser, a variety of drivers such as PHP, ODBC and OLE DB can also be downloaded from http://ftp.cubrid.org.

For more information on the CUBRID engine, tools, and drivers, see http://www.cubrid.org.

Compatibility

Application Compatibility

  • Applications that use JDBC, PHP or CCI APIs from 2008 R4.1 or higher version of CUBRID can access the CUBRID 10.0 database. However, you must link the CUBRID 10.0 library or use the driver to use the added/improved features of JDBC, PHP or CCI interfaces. In order to use Date/Time Types with Timezone which are introduced as 10.0, users should upgrade drivers.
  • Note that query results may differ from those given in the earlier version because new reserved words have been added, and the specifications for some queries have been changed.
  • An application that is developed by using the GLO class can be used after it is converted to an application or schema suitable to the BLOB or CLOB type.

CUBRID Manager Compatibility

  • CUBRID Manager guarantees backward compatibility with the servers using CUBRID 2008 R2.2 or higher and uses the CUBRID JDBC driver that matches each server version. However, you must use a CUBRID Manager that is higher than CUBRID servers in version in order to utilize all the features of CUBRID Manager. The CUBRID JDBC driver is included in the $CUBRID/jdbc directory when CUBRID is installed($CUBRID on Linux, %CUBRID% on Windows).

  • The bit version of CUBRID Manager must be identical to the bit version of JRE.

    For example, if a 64-bit DB server uses CUBRID Manager 32-bit version, JRE or JDK 32-bit version should be installed.

  • Drivers for 2008 R2.2 and higher versions are included in CUBRID Manager by default, which you can download separately from the http://www.cubrid.org Website.

Note

Old version users should upgrade all of driver, broker, DB server; Data migration should be done because its DB volume is not compatible with 10.0 version. For upgrade and data migration, see Upgrade.

Interoperability between CUBRID DB server and broker

  • If the CUBRID DB server and its broker server are operated separately, CUBRID version between them should be the same, but if just the patch version is different, their interoperability is guaranteed.

    For example, 2008 R4.1 Patch1 broker is compatible with 2008 R4.1 Patch 10 DB server, but not compatible with 2008 R4.3 DB server. 9.1 Patch 1 broker is compatible with 9.1 Patch 10 DB server, but not compatible with 9.2 DB server.

  • Even if the operating systems are different, their interoperability is guaranteed if the bit version of a DB server is identical to the bit version of a broker server.

    For example, the 64-bit DB server for Linux is interoperable with the 64-bit broker server for Windows, but it is not interoperable with a 32-bit broker server.

    For the relation between DB server and broker, see Introduction to CUBRID.

Installing and Running CUBRID on Linux

Checklist before Installing

Check the following before installing CUBRID for Linux.

  • glibc version

    Only supports glibc 2.3.4 or later. The glibc version can be checked as follows:

    %rpm -q glibc
    
  • 64-bit or 32-bit

    As 10.0, CUBRID supports only 64-bit Linux. You can check the version as follows:

    % uname -a
    Linux host_name 2.6.18-53.1.14.el5xen #1 SMP Wed Mar 5 12:08:17 EST 2008 x86_64 x86_64 x86_64 GNU/Linux
    

    Make sure to install the CUBRID 64-bit version on 64-bit Linux.

  • The libraries that should be added.

    • Curses Library (rpm -q ncurses)
    • gcrypt Library (rpm -q libgcrypt)
    • stdc++ Library (rpm -q libstdc++)
  • Check if the mapping between host names and IP addresses are correct in the /etc/hosts file.

    If host names and IP addresses are matched incorrectly, DB server cannot be started normally. Therefore, check if they are correctly mapped.

Installing CUBRID

The installation program consists of shell scripts that contain binary; thus it can be installed automatically. The following example shows how to install CUBRID with the "CUBRID-10.0.0.1376-linux.x86_64.sh" file on the Linux.

$ sh CUBRID-10.0.0.1376-linux.x86_64.sh
Do you agree to the above license terms? (yes or no) : yes
Do you want to install this software(CUBRID) to the default(/home1/cub_user/CUBRID) directory? (yes or no) [Default: yes] : yes
Install CUBRID to '/home1/cub_user/CUBRID' ...
In case a different version of the CUBRID product is being used in other machines,
please note that the CUBRID 10.0 servers are only compatible with the CUBRID 10.0 clients and vice versa.
Do you want to continue? (yes or no) [Default: yes] : yes
Copying old .cubrid.sh to .cubrid.sh.bak ...

CUBRID has been successfully installed.

demodb has been successfully created.

If you want to use CUBRID, run the following commands
$ . /home1/cub_user/.cubrid.sh
$ cubrid service start

As shown in the example above, after installing the downloaded file (CUBRID-10.0.0.1376-linux.x86_64.sh), the CUBRID related environment variables must be set in order to use the CUBRID database. Such setting has been made automatically when logging in the concerned terminal. Therefore there is no need to re-set after the first installation.

$ . /home1/cub_user/.cubrid.sh

After CUBRID is installed, you can start CUBRID Manager server and CUBRID broker as follows.

$ cubrid service start

When you want to check whether CUBRID Manager server and CUBRID broker works well, you can use grep command in Linux as follows.

$ ps -ef | grep cub_
cub_user 15200 1 0 18:57   00:00:00 cub_master
cub_user 15205 1 0 18:57 pts/17 00:00:00 cub_broker
cub_user 15210 1 0 18:57 pts/17 00:00:00 query_editor_cub_cas_1
cub_user 15211 1 0 18:57 pts/17 00:00:00 query_editor_cub_cas_2
cub_user 15212 1 0 18:57 pts/17 00:00:00 query_editor_cub_cas_3
cub_user 15213 1 0 18:57 pts/17 00:00:00 query_editor_cub_cas_4
cub_user 15214 1 0 18:57 pts/17 00:00:00 query_editor_cub_cas_5
cub_user 15217 1 0 18:57 pts/17 00:00:00 cub_broker
cub_user 15222 1 0 18:57 pts/17 00:00:00 broker1_cub_cas_1
cub_user 15223 1 0 18:57 pts/17 00:00:00 broker1_cub_cas_2
cub_user 15224 1 0 18:57 pts/17 00:00:00 broker1_cub_cas_3
cub_user 15225 1 0 18:57 pts/17 00:00:00 broker1_cub_cas_4
cub_user 15226 1 0 18:57 pts/17 00:00:00 broker1_cub_cas_5
cub_user 15229 1 0 18:57   00:00:00 cub_auto start
cub_user 15232 1 0 18:57   00:00:00 cub_js start

Installing CUBRID (rpm File)

You can install CUBRID by using rpm file that is created on CentOS 5. The way of installing and uninstalling CUBRID is the same as that of using general rpm utility. While CUBRID is being installed, a new system group (cubrid) and a user account (cubrid) are created. After installation is complete, you should log in with a cubrid user account to start a CUBRID service.:

$ rpm -Uvh cubrid-10.0.0.1376-el5.x86_64.rpm

When rpm is executed, CUBRID is installed in the "cubrid" home directory (/opt/cubrid) and related configuration file (cubrid.[c]sh) is installed in the /etc/profile.d directory. Note that demodb is not automatically installed. Therefore, you must executed /opt/cubrid/demo/make_cubrid_demo.sh with "cubrid" Linux ID. When installation is complete, enter the code below to start CUBRID with "cubrid" Linux ID.

$ cubrid service start

Note

  • RPM and dependency

    You must check RPM dependency when installing with RPM. If you ignore (--nodeps) dependency, it may not be executed.

  • cubrid account and DB exists even if you remove RPM package

    Even if you remove RPM, user accounts and databases that are created after installing, you must remove it manually, if needed.

  • Running CUBRID automatically in Linux when the system is started

    When you use SH package to install CUBRID, the cubrid script will be included in the $CUBRID/share/init.d directory. In this file, you can find the environment variable, CUBRID_USER. You should change this variable to the Linux account with which CUBRID has been installed and register it in /etc/init.d, then you can use service or chkconfig command to run CUBRID automatically when the Linux system is started.

    When you use RPM package to install CUBRID, the cubrid script will be included in /etc/init.d. But you still need to change the environment variable, $CUBRID_USER from "cubrid" script file.

  • In /etc/hosts file, check if a host name and an IP address mapping is normal

    If a host name and an IP address is abnormally mapped, you cannot start DB server. Therefore, you should check if they are normally mapped.

Upgrading CUBRID

When you specify an installation directory where the previous version of CUBRID is already installed, a message which asks to overwrite files in the directory will appear. Entering no will stop the installation.

Directory '/home1/cub_user/CUBRID' exist!
If a CUBRID service is running on this directory, it may be terminated abnormally.
And if you don't have right access permission on this directory(subdirectories or files), install operation will be failed.
Overwrite anyway? (yes or no) [Default: no] : yes

Choose whether to overwrite the existing configuration files during the CUBRID installation. Entering yes will overwrite and back up them as extension .bak files.

The configuration file (.conf or .pass) already exists. Do you want to overwrite it? (yes or no) : yes

For more information on upgrading a database from a previous version to a new version, see Upgrade.

Configuring Environment

You can modify the environment such as service ports etc. edit the parameters of a configuration file located in the $CUBRID/conf directory. See Installing and Running CUBRID on Windows for more information.

Installing CUBRID Interfaces

You can see the latest information on interface modules such as CCI, JDBC, PHP, ODBC, OLE DB, ADO.NET, Ruby, Python and Node.js and install them by downloading files from http://www.cubrid.org/wiki_apis.

A simple description on each driver can be found on API Reference.

Installing CUBRID Tools

You can see the latest information on tools such as CUBRID Manager and CUBRID Query Browser and install them by downloading files from http://www.cubrid.org/wiki_tools.

CUBRID Web Manager is also installed when the CUBRID is installed. For more details, see CUBRID Web Manager Manual.

Installing and Running CUBRID on Windows

Checklist before Installing

You should check the below before installing CUBRID for Windows.

  • 64-bit or not

    CUBRID supports both 32-bit and 64-bit Windows. You can check the version by selecting [My Computer] > [System Properties]. Make sure to install the CUBRID 32-bit version on 32-bit Windows and the CUBRID 64-bit version on 64-bit Windows.

  • Run with administrative privilege

    If you want to install CUBRID on Windows Vista or higher, execute the installation file with administrative privileges. On the popup menu after clicking right mouse button on the CUBRID installation file, choose [Execute as an administrator (A)].

Installation Process

Step 1: Specifying the directory to install

Step 2: Selecting Setup Type

  • Server and Driver Installation : All of CUBRID Server, CSQL (a command line tool) and interface drivers (JDBC, C API) are installed.

Step 3: Creating a sample database

To create a sample database, it requires 300MB disk space.

Step 4: Completing the installation

CUBRID Service Tray appears on the right bottom.

Note

CUBRID Service is automatically started when the system is rebooted. If you want to stop the when the system is rebooted, change the "Start parameters" of "CUBRIDService" as "Stop"; "Control Panel > Administrative Tools > Services" and double-clicking "CUBRIDService", then pop-up window will be shown.

Checklist After Installation

  • Whether the start of CUBRID Service Tray or not

    If CUBRID Service Tray is not automatically started when starting a system, confirm the following.

    • Check if Task Scheduler is started in [Start button] > [Control panel] > [Administrative Tools] > [Services]; if not, start Task Scheduler.
    • Check if CUBRID Service Tray is registered in [Start button] > [All Programs] > [Startup]; if not, register CUBRID Service Tray.

Upgrading CUBRID

To install a new version of CUBRID in an environment in which a previous version has already been installed, select [CUBRID Service Tray] > [Exit] from the menu to stop currently running services, and then remove the previous version of CUBRID. Note that when you are prompted with "Do you want to delete all the existing version of databases and the configuration files?" you must select "No" to protect the existing databases.

For more information on upgrading a database from a previous version to a new version, see Upgrade.

Configuring Environment

You can change configuration such as service ports to meet the user environment by changing the parameter values of following files which are located in the %CUBRID%\conf directory. If a firewall has been configured, the ports used in CUBRID need to be opened.

  • cm.conf

    A configuration file for CUBRID Manager. The port that the Manager server process uses is called cm_port and its default value is 8001. For details, see CUBRID Manager Manual.

    To start CUBRID Web Manager, firstly you should set the value of support_web_manager parameter as "YES", then restart CUBRID Manager Server. To use CUBRID Web Manager, access "https://localhost:8001".

    $ cubrid manager stop
    $ cubrid manager start
    
  • cubrid.conf

    A configuration file for server. You can use it to configure the following values: database memory, the number threads based on the number of concurrent users, communication port between broker and server, etc. The port that a master process uses is called cubrid_port_id and its default value is 1523. For details, see cubrid.conf Configuration File and Default Parameters.

  • cubrid_broker.conf

    A configuration file for broker. You can use it to configure the following values: broker port, the number of application servers (CAS), SQL LOG, etc. The port that a broker uses is called BROKER_PORT. A port you see in the drivers such as JDBC is its corresponding broker's port. APPL_SERVER_PORT is a port that a broker application server (CAS) uses and it is added only in Windows. The default value is BROKER_PORT +1. The number of ports used is the same as the number of CAS, starting from the specified port's number plus 1. For details, see Parameter by Broker. For example, if the value of APPL_SERVER_PORT is 35000 and the maximum number of CASes by MAX_NUM_APPL_SERVER is 50, then listening ports on CASes are 35000, 35001, ..., 35049. For more details, see Parameter by Broker.

    The CCI_DEFAULT_AUTOCOMMIT broker parameter is supported since 2008 R4.0. The default value in the version is OFF and it is later changed to ON. Therefore, users who have upgraded from 2008 R4.0 to 2008 R4.1 or later versions should change this value to OFF or configure the auto-commit mode to OFF.

Installing CUBRID Interfaces

You can see the latest information on interface modules such as JDBC, PHP, ODBC, and OLE DB and install them by downloading files from http://www.cubrid.org/wiki_apis.

A simple description on each driver can be found on API Reference.

Installing CUBRID Tools

You can see the latest information on tools such as CUBRID Manager and CUBRID Query Browser and install them by downloading files from http://www.cubrid.org/wiki_tools.

CUBRID Web Manager is installed when CUBRID is installed. For more details, see CUBRID Web Manager Manual .

Installing with a Compressed Package
Installing CUBRID with tar.gz on Linux

Checklist before Installing

Check the following before installing CUBRID for Linux.

  • glibc version

    Only supports glibc 2.3.4 or later. The glibc version can be checked as follows:

    %rpm -q glibc
    
  • 64-bit

    As 10.0, CUBRID supports only 64-bit Linux. You can check the version as follows:

    % uname -a
    Linux host_name 2.6.18-53.1.14.el5xen #1 SMP Wed Mar 5 12:08:17 EST 2008 x86_64 x86_64 x86_64 GNU/Linux
    

    Make sure to install the CUBRID 64-bit version on 64-bit Linux.

  • The libraries that should be added.

    • Curses Library (rpm -q ncurses)
    • gcrypt Library (rpm -q libgcrypt)
    • stdc++ Library (rpm -q libstdc++)
  • Check if the mapping between host names and IP addresses are correct in the /etc/hosts file.

    If host names and IP addresses are matched incorrectly, DB server cannot be started normally. Therefore, check if they are correctly mapped.

Installation Process

Specifying the Directory to Install

  • Decompress the compressed file to the directory to install.

    tar xvfz CUBRID-10.0.0.0181-linux.x86_64.tar.gz /home1/cub_user/
    

    CUBRID directory is created under /home1/cub_user/ and files are created under CUBRID directory.

Specifying Environment Variables

  1. Add below environment variables to a shell script which is run automatically and located under the home direcoty of a user.

    The below is an example to add environemt variables to .bash_profile when you run on the bash shell.

    export CUBRID=/home1/cub_user/CUBRID
    export CUBRID_DATABASES=$CUBRID/databases
    
  2. Add CUBRID JDBC library file name to the CLASSPATH environment variable.

    export CLASSPATH=$CUBRID/jdbc/cubrid_jdbc.jar:$CLASSPATH
    
  3. Add CUBRID bin directory to PATH environment variables.

    export PATH=$CUBRID/bin:$PATH
    

Creating DB

  • Move to the directory to create DB on the console and create DB.

    cd $CUBRID_DATABASES
    mkdir testdb
    cd testdb
    cubrid createdb --db-volume-size=100M --log-volume-size=100M testdb en_US
    

Auto-starting when Booting

  • "cubrid" script is included in the $CUBRID/share/init.d directory. Change the value of $CUBRID_USER environment variable into the Linux accout which installed CUBRID and register this script to /etc/init.d; then you can start automatically by using "service" or "chkconfig" command.

Auto-starting DB

  • To start DB automatically when you booting a system, change the below in $CUBRID/conf/cubrid.conf.

    [service]
    service=server, broker, manager
    server=testdb
    
  • In the "service" parameter, processes to be auto-started are specified.

  • In the "server" parameter, DB name to be auto-started is specified.

For environment setting, tools installation and interfaces installation after CUBRID installation, see Installing and Running CUBRID on Linux.

Installing CUBRID with zip on Windows

Checklist before Installing

Check below list before installing CUBRID database of Windows version.

  • 64bit or 32bit

    CUBRID supports both 32-bit and 64-bit Windows. You can check the version by selecting [My Computer] > [System Properties]. Make sure to install the CUBRID 32-bit version on 32-bit Windows and the CUBRID 64-bit version on 64-bit Windows.

Installation Process

Specifying the Directory to Install

  • Decompress the compressed file to the directory to install.

    C:\CUBRID
    

Specifying Environment Variables

  1. Select [Start button] > [Computer] > (click right mouse button) > [Properties] > [Advanced system settings] > [Environment Variables].

  2. Click [New ...] under the system variables and add system variables as below.

    CUBRID = C:\CUBRID
    CUBRID_DATABASES = %CUBRID%\databases
    
  3. Add CUBRID JDBC library name to CLASSPATH system variable.

    %CUBRID%\jdbc\cubrid_jdbc.jar
    
  4. Add CUBRID bin directory to Path system variable.

    %CUBRID%\bin
    

Creating DB

  • Run cmd command and open the colsole; move to the directory to create DB and create DB.

    cd C:\CUBRID\databases
    md testdb
    cd testdb
    c:\CUBRID\databases\testdb>cubrid createdb --db-volume-size=100M --log-volume-size=100M testdb en_US
    

Auto-starting when Booting

  • To start CUBRID automatically when booting the Windows system, CUBRID Service should be registered to Windows Service.

    1. Register CUBRID Service to Windows Service.

      C:\CUBRID\bin\ctrlService.exe -i C:\CUBRID\bin
      
    2. The below shows how to start/stop CUBRID Service.

      C:\CUBRID\bin\ctrlService.exe -start/-stop
      

Auto-starting DB

  • To start DB when booting on Windows, change below in C:\CUBRIDconf\cubrid.conf.

    [service]
    service=server, broker, manager
    server=testdb
    
    • Specify the processes to start automatically on the "service" parameter.
    • Specify the DB name to start automatically on the "server" parameter.

Removing from Service

  • To remove registered CUBRID Service, run the following.

    C:\CUBRID\bin\ctrlService.exe -u
    

Registering CUBRID Service Tray

Since CUBRID Service Tray is not automatically registered when installing CUBRID with zip file, it is required to register manually if you want CUBRID Service Tray.

  1. Create a link of C:\CUBRID\bin\CUBRID_Service_Tray.exe in [Start button] > [All Programs] > [Startup].

  2. Input "regedit" in [Start button] > [Accessories] > [Run] to run a registry editor.

  3. Create CUBRID folder under [Computer] > [HKEY_LOCAL_MACHINE] > [SOFTWARE].

  4. Create [cmclient] folder under [CUBRID] folder(Edit > New > Key) and add below items(Edit > New > String Value).

    Name          Type       Data
    
    ROOT_PATH     REG_SZ     C:\CUBRID\cubridmanager
    
  5. Create [cmserver] folder under [CUBRID] folder(Edit > New > Key) and add below items(Edit > New > String Value).

    Name          Type       Data
    
    ROOT_PATH     REG_SZ     C:\CUBRID
    
  6. Create [CUBRID] folder under [CUBRID] folder(Edit > New > Key) and add below items(Edit > New > String Value).

    Name          Type       Data
    
    ROOT_PATH     REG_SZ     C:\CUBRID
    
  7. When rebooting Windows, CUBRID Service Tray is created under right side.

Checklist After Installation

  • Whether the start of CUBRID Service Tray or not

    If CUBRID Service Tray is not automatically started when starting a system, confirm the following.

    • Check if Task Scheduler is started in [Start button] > [Control panel] > [Administrative Tools] > [Services]; if not, start Task Scheduler.
    • Check if CUBRID Service Tray is registered in [Start button] > [All Programs] > [Startup]; if not, register CUBRID Service Tray.

For environment setting, tools installation and interfaces installation after CUBRID installation, see Installing and Running CUBRID on Windows.

Configuring Environment Variables

The following environment variables need to be set in order to use the CUBRID. The necessary environment variables are automatically set when the CUBRID system is installed or can be changed, as needed, by the user.

CUBRID Environment Variables
  • CUBRID: The default environment variable that designates the location where the CUBRID is installed. This variable must be set accurately since all programs included in the CUBRID system uses this environment variable as reference.
  • CUBRID_DATABASES: The environment variable that designates the location of the databases.txt file. The CUBRID system stores the absolute path of database volumes in the $CUBRID_DATABASES/databases.txt file. See databases.txt File.
  • CUBRID_MSG_LANG: The environment variable that specifies usage messages and error messages in CUBRID. The initial value upon start is not defined. If it is not defined, it follows the configured locale when createdb. For more information, see Language & Charset Setting.

Note

  • A user of CUBRID Manager or CUBRID Query Browser should specify CUBRID_MSG_LANG, an environment variable of DB server node into en_US to print out messages normally after running database related features. However, database related features are run normally and just the output messages are broken when CUBRID_MSG_LANG is not en_US.
  • To apply the changed CUBRID_MSG_LANG, CUBRID system of DB server node should be restarted(cubrid service stop, cubrid service start).
  • CUBRID_TMP: The environment variable that specifies the location where the cub_master process and the cub_broker process store the UNIX domain socket file in CUBRID for Linux. If it is not specified, the cub_master process stores the UNIX domain socket file under the /tmp directory and the cub_broker process stores the UNIX domain socket file under the $CUBRID/var/CUBRID_SOCK directory (not used in CUBRID for Windows).

CUBRID_TMP value has some constraints, which are as follows:

  • Since the maximum length of the UNIX socket path is 108, when a path longer than 108 is entered in $CUBRID_TMP, an error is displayed.

    $ export CUBRID_TMP=/home1/testusr/cubrid=/tmp/123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
    $ cubrid server start apricot
    
    The $CUBRID_TMP is too long. (/home1/testusr/cubrid=/tmp/123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789)
    
  • When the relative path is entered, an error is displayed.

    $ export CUBRID_TMP=./var
    $ cubrid server start testdb
    
    The $CUBRID_TMP should be an absolute path. (./var)
    

CUBRID_TMP can be used to avoid the following problems that can occur at the default path of the UNIX domain socket that CUBRID uses.

  • /tmp is used to store the temporary files in Linux. If the system administrator periodically and voluntarily cleans the space, the UNIX domain socket may be removed. In this case, configure $CUBRID_TMP to another path, not /tmp.
  • The maximum length of the UNIX socket path is 108. When the installation path of CUBRID is too long and the $CUBRID/var/CUBRID_SOCK path that store the UNIX socket path for cub_broker exceeds 108 characters, the broker cannot be executed. Therefore, the path of $CUBRID_TMP must not exceed 1008 characters.

The above mentioned environment variables are set when the CUBRID is installed. However, the following commands can be used to verify the setting.

  • Linux

    % printenv CUBRID
    % printenv CUBRID_DATABASES
    % printenv CUBRID_MSG_LANG
    % printenv CUBRID TMP
    
  • Windows

    C:\> set CUBRID
    
OS Environment and Java Environment Variables
  • PATH: In the Linux environment, the directory $CUBRID/bin, which includes a CUBRID system executable file, must be included in the PATH environment variable.
  • LD_LIBRARY_PATH: In the Linux environment, $CUBRID/lib, which is the CUBRID system's dynamic library file (libjvm.so), must be included in the LD_LIBRARY_PATH (or SHLIB_PATH or LIBPATH) environment variable.
  • Path: In the Windows environment, the %CUBRID%\bin, which is a directory that contains CUBRID system's execution file, must be included in the Path environment variable.
  • JAVA_HOME: To use the Java stored procedure in the CUBRID system, the Java Virtual Machine (JVM) version 1.6 or later must be installed, and the JAVA_HOME environment variable must designate the concerned directory. See the Environment Configuration for Java Stored Function/Procedure.
Configuring the Environment Variable

For Windows

If the CUBRID system has been installed on Windows, then the installation program automatically sets the necessary environment variable. Select [Systems Properties] in [My Computer] and select the [Advanced] tab. Click the [Environment Variable] button and check the setting in the [System Variable]. The settings can be changed by clicking on the [Edit] button. See the Windows help for more information on how to change the environment variable on Windows.

_images/image4.png

For Linux

If the CUBRID system has been installed on Linux, the installation program automatically creates the .cubrid.sh or .cubrid.csh file and makes configurations so that the files are automatically called from the installation account's shell log-in script. The following is the contents of . cubrid.sh environment variable configuration that was created in an environment that uses sh, bash, etc.

CUBRID=/home1/cub_user/CUBRID
CUBRID_DATABASES=/home1/cub_user/CUBRID/databases
ld_lib_path=`printenv LD_LIBRARY_PATH`

if [ "$ld_lib_path" = "" ]
then
    LD_LIBRARY_PATH=$CUBRID/lib
else
    LD_LIBRARY_PATH=$CUBRID/lib:$LD_LIBRARY_PATH
fi

SHLIB_PATH=$LD_LIBRARY_PATH
LIBPATH=$LD_LIBRARY_PATH
PATH=$CUBRID/bin:$CUBRID/cubridmanager:$PATH

export CUBRID
export CUBRID_DATABASES
export LD_LIBRARY_PATH
export SHLIB_PATH
export LIBPATH
export PATH
Language & Charset Setting

The language and the charset that will be used in the CUBRID DBMS is specified after the database name when DB is created(e.g. cubrid createdb testdb ko_KR.utf8). The following are examples of values that can currently be set as a language and a charset.

  • en_US.iso88591: English ISO-88591 encoding(.iso88591 can be omitted)
  • ko_KR.euckr: Korean EUC-KR encoding
  • ko_KR.utf8: Korean UTF-8 encoding(.utf8 can be omitted)
  • de_DE.utf8: German UTF-8 encoding
  • es_ES.utf8: Spanish UTF-8 encoding
  • fr_FR.utf8: French UTF-8 encoding
  • it_IT.utf8: Italian UTF-8 encoding
  • ja_JP.utf8: Japanese UTF-8 encoding
  • km_KH.utf8: Cambodian UTF-8 encoding
  • tr_TR.utf8: Turkish UTF-8 encoding(.utf8 can be omitted)
  • vi_VN.utf8: Vietnamese UTF-8 encoding
  • zh_CN.utf8: Chinese UTF-8 encoding
  • ro_RO.utf8: Romanian UTF-8 encoding

Language and charset setting of CUBRID affects read and write data. The language is used for messages displayed by the program.

For more details related to charset, locale and collation settings, see An Overview of Globalization.

Port Setting

If ports are closed, the ports used by CUBRID should be opened.

The following table summarizes the ports used by CUBRID. Each port on the listener that waits for connection from the opposite side should be opened.

To open the ports for a specific process on the Linux firewall, follow the guide described for the corresponding firewall program.

If available ports for Windows are used, you cannot know which port will be opened. In this case, enter "firewall" in the "Control Panel" of the Windows menu and then choose "Windows Firewall> Allow a program or functionality through Windows Firewall" and then add the program for which port should be opened.

This method can be used for the case that it is difficult to specify a specific port in Windows. This method is recommended since it is safer to add a program to the Allowed programs list than to open a port without specifying a program on the Windows firewall.

  • Add "%CUBRID%\bin\cub_broker.exe" to open all ports for cub_broker.
  • Add "%CUBRID%\bin\cub_cas.exe" to open all ports for CAS.
  • Add "%CUBRID%\bin\cub_master.exe" to open all ports for cub_master.
  • Add "%CUBRID%\bin\cub_server.exe" to open all ports for cub_server.
  • Add "%CUBRID%\bin\cub_cmserver.exe" to open all ports for the CUBRID Manager.

If you use CUBRID for Linux at the broker machine or the DB server machine, all of Linux ports should be opened. If you use CUBRID for Windows at the broker machine or the DB server machine, all of Linux ports should be opened or the related processes should be added to the program list allowed for the Windows firewall.

Label Listener Requester Linux Port Windows Port Firewall Port Setting Description
Default use cub_broker application BROKER_PORT BROKER_PORT Open One-time connection
CAS application BROKER_PORT APPL_SERVER_PORT ~ (APP_SERVER_PORT + # of CAS - 1) Open Keep connected
cub_master CAS cubrid_port_id cubrid_port_id Open One-time connection
cub_server CAS cubrid_port_id A random available port

Linux: Open

Windows: Program

Keep connected
Client machine(*) cub_server ECHO(7) ECHO(7) Open Periodical connection
Server machine(**) CAS, CSQL ECHO(7) ECHO(7) Open Periodical connection
HA use cub_broker application BROKER_PORT Not supported Open One-time connection
CAS application BROKER_PORT Not supported Open Keep connected
cub_master CAS cubrid_port_id Not supported Open One-time connection

cub_master

(slave)

cub_master

(master)

ha_port_id Not supported Open Periodical connection, check the heartbeat

cub_master

(master)

cub_master

(slave)

ha_port_id Not supported Open Periodical connection, check the heartbeat
cub_server CAS cubrid_port_id Not supported Open Keep connected
Client machine(*) cub_server ECHO(7) Not supported Open Periodical connection
Server machine(**) CAS, CSQL, copylogdb, applylogdb ECHO(7) Not supported Open Periodical connection
Manager use Manager server application 8001 8001 Open  
Web Manager use Web Manager server

(*): The machine which has the CAS, CSQL, copylogdb, or applylogdb process

(**): The machine which has the cub_server

The detailed description on each classification is given as follows.

Default Ports for CUBRID

The following table summarizes the ports required for each OS, based on the listening processes. Each port on the listener should be opened.

Listener Requester Linux port Windows port Firewall Port Setting Description
cub_broker application BROKER_PORT BROKER_PORT Open One-time connection
CAS application BROKER_PORT APPL_SERVER_PORT ~ (APP_SERVER_PORT + # of CAS - 1) Open Keep connected
cub_master CAS cubrid_port_id cubrid_port_id Open One-time connection
cub_server CAS cubrid_port_id A random available port

Linux: Open

Windows: Program

Keep connected
Client machine(*) cub_server ECHO(7) ECHO(7) Open Periodical connection
Server machine(**) CAS, CSQL ECHO(7) ECHO(7) Open Periodical connection

(*): The machine which has the CAS or CSQL process

(**): The machine which has the cub_server

Note

In Windows, you cannot specify the ports to open because CAS randomly specifies the ports as accessing the cub_server. In this case, add "%CUBRID%\bin\cub_server.exe" to "Windows Firewall > Allowed programs".

As the server process (cub_server) and the client processes (CAS, CSQL) cross-check if the opposite node is normally running or not by using the ECHO(7) port, you should open the ECHO(7) port if there is a firewall. If the ECHO port cannot be opened for both the server and the client, set the check_peer_alive parameter value of the cubrid.conf to none.

The relation of connection between processes is as follows:

application - cub_broker
            -> CAS  -  cub_master
                    -> cub_server
  • application: The application process
  • cub_broker: The broker server process. It selects CAS to connect with the application.
  • CAS: The broker application server process. It relays the application and the cub_server.
  • cub_master: The master process. It selects the cub_server to connect with the CAS.
  • cub_server: The database server process

The symbols of relation between processes and the meaning are as follows:

  • - : Indicates that the connection is made only once for the initial.
  • ->, <- : Indicates that the connection is maintained. The right side of -> or the left side of <- is the party that the arrow symbol indicates. The party that the arrow symbol indicates is the listener which listens to the opposite process.
  • (master): Indicates the master node in the HA configuration.
  • (slave): Indicates the slave node in the HA configuration.

The connection process between the application and the DB is as follows:

  1. The application tries to connect to the cub_broker through the broker port (BROKER_PORT) set in the cubrid_broker.conf.

  2. The cub_broker selects a connectable CAS.

  3. The application and CAS are connected.

    In Linux, BROKER_PORT, which is used as an application, is connected to CAS through the Unix domain socket. In Windows, since the Unix domain socket cannot be used, an application and CAS are connected through a port of which the number is the sum of the corresponding CAS ID and the APPL_SERVER_PORT value set in the cubrid_broker.conf. If the APPL_SERVER_PORT value has not been set, the port value connected to the first CAS is BROKER_PORT + 1.

    For example, if the BROKER_PORT is 33000 and the APPL_SERVER_PORT value has not been set in Windows, the ports used between the application and CAS are as follows:

    • The port used to connect the application to the CAS(1): 33001
    • The port used to connect the application to the CAS(2): 33002
    • The port used to connect the application to the CAS(3): 33003
  4. CAS sends a request of connecting with the cub_server to the cub_master through the cubrid_port_id port set in the cubrid.conf.

  5. CAS and the cub_server are connected.

    In Linux, you should use the cubrid_port_id port as CAS is connected to the cub_server through the Unix domain socket. In Windows, CAS is connected to the cub_server through a random available port as the Unix domain socket cannot be used. If the DB server is running in Windows, a random available port is used between the broker machine and the DB server machine. In this case, note that the operation may not be successful if a firewall blocks the port for the process between the two machines.

  6. After that, CAS keeps connection with the cub_server even if the application is terminated until the CAS restarts.

Ports for CUBRID HA

The CUBRID HA is supported in Linux only.

The following table summarizes the ports required for each OS, based on the listening processes. Each port on the listener should be opened.

Listener Requester Linux port Firewall Port Setting Description
cub_broker application BROKER_PORT Open One-time connection
CAS application BROKER_PORT Open Keep connected
cub_master CAS cubrid_port_id Open One-time connection

cub_master

(slave)

cub_master

(master)

ha_port_id Open Periodical connection, check the heartbeat

cub_master

(master)

cub_master

(slave)

ha_port_id Open Periodical connection, check the heartbeat
cub_server CAS cubrid_port_id Open Keep connected
Client machine(*) cub_server ECHO(7) Open Periodical connection
Server machine(**) CAS, CSQL, copylogdb, applylogdb ECHO(7) Open Periodical connection

(*): The machine which has the CAS, CSQL, copylogdb, or applylogdb process

(**): The machine which has the cub_server

As the server process (cub_server) and the client processes (CAS, CSQL, copylogdb, applylogdb, etc.) cross-check if the opposite node is normally running or not by using the ECHO(7) port, you should open the ECHO(7) port if there is a firewall. If the ECHO port cannot be opened for both the server and the client, set the ref:check_peer_alive <check_peer_alive> parameter value of the cubrid.conf to none.

The relation of connection between processes is as follows:

application - cub_broker
            -> CAS  -  cub_master(master) <-> cub_master(slave)
                    -> cub_server(master)     cub_server(slave) <- applylogdb(slave)
                                          <----------------------- copylogdb(slave)
  • cub_master(master): the master process on the master node in the CUBRID HA configuration. It checks if the peer node is alive.
  • cub_master(slave): the master process on the slave node in the CUBRID HA configuration. It checks if the peer node is alive.
  • copylogdb(slave): the process which copies the replication log on the slave node in the CUBRID HA configuration
  • applylogdb(slave): the process which applies the replication log on the slave node in the CUBRID HA configuration

For easy understanding for the replication process from the master node to the slave node, the applylogdb and copylogdb on the master node and CAS on the slave node have been omitted.

The symbols of relation between processes and the meaning are as follows:

  • - : Indicates that the connection is made only once for the initial.
  • ->, <- : Indicates that the connection is maintained. The right side of -> or the left side of <- is the party that the arrow symbol indicates. The party that the arrow symbol indicates is the listener which listens to the opposite process.
  • (master): Indicates the master node in the HA configuration.
  • (slave): Indicates the slave node in the HA configuration.

The connection process between the application and the DB is identical with Default Ports for CUBRID. This section describes the connection process between the master node and the slave node when the master DB and the slave DB are configured 1:1 by the CUBRID HA.

  1. The ha_port_id set in the cubrid_ha.conf is used between the cub_master(master) and the cub_master(slave).
  2. The copylogdb(slave) sends a request for connecting with the master DB to the cub_master(master) through the port set in the cubrid_port_id of the cubrid.conf on the slave node. Finally, the copylogdb(slave) is connected with the cub_server(master).
  3. The applylogdb(slave) sends a request for connecting with the slave DB to the cub_master(slave) through the port set in the cubrid_port_id of the cubrid.conf on the slave node. Finally, the applylogdb(slave) is connected with the cub_server(slave).

On the master node, the applylogdb and the copylogdb run for the case that the master node is switched to the slave node.

Ports for CUBRID Web Manager and CUBRID Manager Server

The following table summarizes the ports, based on the listening processes, used for the CUBRID Web Manager and the CUBRID Manager server. The ports are identical regardless of the OS type.

Listener Requester Port Firewall Port Setting
Manager server, Web Manager server application 8001 Open
  • The port used when the CUBRID Manager client accesses the CUBRID Manager server process is cm_port of the cm.conf. The default value is 8001.
  • The port used when the CUBRID Web Manager client accesses the CUBRID Web Manager server process is also cm_port of the cm.conf.

Upgrade

Cautions during upgrade

Behavioral Changes

To see the behavioral changes from 10.0, please see Behavior Changes in the release notes.

Saving the Existing Configuration File

  • Save the configuration files in the $CUBRID/conf directory (cubrid.conf, cubrid_broker.conf and cm.conf) and the DB location file (databases.txt) in the $CUBRID_DATABASES directory.

Checking New Reserved Words

  • You can check whether reserved words are being used or not by applying the CUBRID 10.0 reserved word detection script, check_reserved.sql, which is distributed through the CUBRID installation package or http://ftp.cubrid.org/CUBRID_Engine/10.0.0/. If the reserved words are being used as identifiers, the identifiers must be modified. See Identifier.

Configuring environment variables of CUBRID_MSG_LANG

  • CUBRID_LANG and CUBRID_CHARSET environment variables are no more used, and the language and the charset should be configured during creating DB. CUBRID_MSG_LANG is used when displaying the messages of utilities or errors. If CUBRID_MSG_LANG is not configured, it follows the language and the charset specified when creating DB.

Changing schema

  • 9.0 Beta or earlier version user which had used not ISO-8859-1 charset but EUC-KR charset or UTF-8 charset, should change the schema. In the earlier version of 9.0 Beta, the precision of CHAR or VARCHAR was specified as byte size. From 9.0 Beta, the precision is specified as character length.

Adding/Keeping locales

  • If you have locales to want to add, add them into $CUBRID/conf/cubrid_locales.txt file and run make_locale script. For more details, see Locale Setting.
  • If you want to keep the old version's locale, add the old version's locale to $CUBRID/conf/cubrid_locales.txt file and run make_locale script, and specify the old locale when running createdb command.

DB migration

  • Since the DB volume of CUBRID 9.x and earlier versions are not compatible with the DB volume of CUBRID 10.0, it should be migrated with cubrid unloaddb/loaddb utility. For more detail procedure, see DB migration.
  • CUBRID 2008 R3.1 and later don't support GLO and the LOB type replaces the GLO feature. For this reason, applications or schemas that use GLO must be modified to be compatible with LOB.

Note

In 2008 R4.0 or before, TIMESTAMP '1970-01-01 00:00:00'(GMT) is the minimum value of TIMESTAMP, but in 2008 4.1 or later, it is recognized as zerodate and TIMESTAMP '1970-01-01 00:00:01'(GMT) is the minimum value of TIMESTAMP.

Reconfiguring environments for replication or HA

  • From 2008 R4.0, the replication feature is no longer supported; therefore, it is recommended to reconfigure the DB migration and HA environment for systems in which previous replication versions are used. In addition, for systems that use Linux Heartbeat-based HA feature, which is provided in CUBRID 2008 R2.0 and 2008 R2.1, you must reconfigure to DB migration and the CUBRID Heartbeat-based HA environment for better operational stability(see Database Migration under HA Environment).
  • To reconfigure the HA environment configuration, see CUBRID HA in the manual.

Java Stored Function/Procedure

Upgrading from CUBRID 9.2/9.3 to CUBRID 10.0

Users who are using versions CUBRID 9.2/9.3 should install 10.0 in the different directory, migrate the databases to 10.0 and modify parameter values in the previous environment configuration file.

DB migration

The following table shows how to perform the migration using the reserved word detection script, check_reserved.sql, which is separately distributed from http://ftp.cubrid.org/CUBRID_Engine/10.0.0/Linux/ and the cubrid unloaddb/loaddb utilities. (See unloaddb and loaddb)

Step Linux Environment Windows Environment
Step C1: Stop CUBRID Service % cubrid service stop Stop CUBRID Service Tray.
Step C2: Execute the reserved
words detection script

Execute the following command in the directory where the reserved word detection script is located.

Execute migration or identifier modification by checking the detection result (For the allowable identifier).

% csql -S -u dba -i check_reserved.sql testdb
Step C3: Unload the earlier
version of the DB

Store the databases.txt file and the configuration files under the conf directory of the earlier version in a separate directory (C3a).

Execute the cubrid unloaddb utility and store the file generated at this point in a separate directory(C3b).

% cubrid unloaddb -S testdb

Delete the existing database (C3c).

% cubrid deletedb testdb
  Uninstall the earlier version of CUBRID.
Step C4: Install new version See Installing and Running CUBRID
Step C5: Database creation and
data loading

Go to the directory where you want to create a database, and create one. At this time, be cautious about locale setting(*). (c5a)

% cd $CUBRID/databases/testdb

% cubrid createdb testdb en_US

Execute the cubrid loaddb utility with the stored files in (C3b). (C5b)

% cubrid loaddb -s testdb_schema -d testdb_objects -i testdb_indexes testdb
Step C6: Back up the new version
of the DB
% cubrid backupdb -S testdb
Step C7: Configure the CUBRID
environment and start the CUBRID Service

Modify the configuration file. At this point, partially modify the configuration files from the earlier version stored in step (C3a) to fit the new version.

(For configuring system parameter, see Parameter configuration and System Parameters)

% cubrid service start

% cubrid server start testdb

Start the service by selecting CUBRID Service Tray > [Service Start].

Start the database server from the command prompt.

% cubrid server start testdb
Parameter configuration

cubrid.conf

  • The minimum size of log_buffer_size is changed from 48KB(3*1page, 16KB=1page) into 2MB(128*1page, 16KB=1page); therefore, this value should be larger than the changed minimum size.
Upgrading from CUBRID 9.1 to CUBRID 10.0

Users who are using versions CUBRID 9.1 should install 10.0 in the different directory, migrate databases to 10.0 and modify parameter values in the previous environment configuration file.

DB migration

Please refer DB migration for migration steps.

Parameter configuration

cubrid.conf

  • The minimum size of log_buffer_size is changed from 48KB(3*1page, 16KB=1page) into 2MB(128*1page, 16KB=1page); therefore, this value should be larger than the changed minimum size.

  • The value of sort_buffer_size should be configured as 2G or less since the maximum value of sort_buffer_size is 2G.

  • In the following parameters, the old parameters will be deprecated and the new parameters are recommended to use. the value in the parenthesis is the unit of the value when the unit is omitted, and the new parameters can specify the unit after the value. For details, see each parameter's explanation in System Parameters

    Old parameters(unit) New parameters(unit)
    lock_timeout_in_secs(sec) lock_timeout(msec)
    checkpoint_every_npages(page_count) checkpoint_every_size(byte)
    checkpoint_interval_in_mins(min) checkpoint_interval(msec)
    max_flush_pages_per_second(page_count) max_flush_size_per_second(byte)
    sync_on_nflush(page_count) sync_on_flush_size(byte)
    sql_trace_slow_msecs(msec) sql_trace_slow(msecs)

cubrid_broker.conf

  • In KEEP_CONNECTION parameter, OFF value should be changed as ON or AUTO since OFF setting value is no longer used.
  • SELECT_AUTO_COMMIT should be deleted since this parameter is no longer used.
  • The value of APPL_SERVER_MAX_SIZE_HARD_LIMIT should be 2,097,151 or less since the maximum value of APPL_SERVER_MAX_SIZE_HARD_LIMIT is 2,097,151.

Environment variable

  • CUBRID_CHARSET is removed, and now CUBRID_CHARSET is used for configuring the charset of database and CUBRID_MSG_LANG is used for configuring the charset of messages for utilities and errors.

    Warning

    When you create database, a language and a charset must be specified. It affects the length of string type, string comparison operation, etc. The specified charset when creating database cannot be changed later, so you should be careful when specifying it.

    For charset, locale and collation setting, see An Overview of Globalization.

For more details, see changed-config100.

Upgrading From CUBRID 2008 R4.1/R4.3/R4.4 To CUBRID 10.0

Users who are using a version of CUBRID 2008 R4.1, R4.3 or R4.4 should install 10.0 in the different directory, migrate databases to 10.0 and modify parameter values in the existing environment configuration file.

DB migration

Please refer DB migration for migration steps.

(*): The user which uses CUBRID 2008 R4.x or before should be cautious for determining a locale(language and charset). For example, when the user which used the language as ko_KR(Korean) and the charset as utf8 processes DB migration, the locale should be set as "cubrid createdb testdb ko_KR.utf8". If the locale is not built-in locale, you should run make_locale(.sh) command first. For more details, see Locale Setting.

  • You should be careful about the change of the space for storing about the multibyte character. For example, in 2008 R4.3, CHAR(6) means CHAR type with 6 bytes size, but from 9.3, CHAR(6) means CHAR type with 6 characters. In utf8 charset, Korean uses 3 bytes per 1 character, so CHAR(6) has 18 bytes. Therefore, more disk space is required.
  • If you used utf8 charset in CUBRID 2008 R4.x or before, you should set the charset as utf8 when you run "cubrid createdb". If not, retrieval queries or string functions are unable to work properly.
Parameter configuration

cubrid.conf

  • The minimum size of log_buffer_size is changed from 48KB(3*1page, 16KB=1page) into 2MB(128*1page, 16KB=1page); therefore, this value should be larger than the changed minimum size.

  • The value of sort_buffer_size should be configured as 2G or less since the maximum value of sort_buffer_size is 2G.

  • single_byte_compare should be deleted since this parameter is no longer used.

  • intl_mbs_support should be deleted since this parameter is no longer used.

  • lock_timeout_message_type should be deleted since this parameter is no longer used.

  • In the following parameters, the old parameters will be deprecated and the new parameters are recommended to use. the value in the parenthesis is the unit of the value when the unit is omitted, and the new parameters can specify the unit after the value. For details, see each parameter's explanation in System Parameters

    Old parameters(unit) New parameters(unit)
    lock_timeout_in_secs(sec) lock_timeout(msec)
    checkpoint_every_npages(page_count) checkpoint_every_size(byte)
    checkpoint_interval_in_mins(min) checkpoint_interval(msec)
    max_flush_pages_per_second(page_count) max_flush_size_per_second(byte)
    sync_on_nflush(page_count) sync_on_flush_size(byte)
    sql_trace_slow_msecs(msec) sql_trace_slow(msecs)

cubrid_broker.conf

  • In KEEP_CONNECTION parameter, OFF value should be changed as ON or AUTO since OFF setting value is no longer used.
  • SELECT_AUTO_COMMIT should be deleted since this parameter is no longer used.
  • The value of APPL_SERVER_MAX_SIZE_HARD_LIMIT should be 2,097,151 or less since the maximum value of APPL_SERVER_MAX_SIZE_HARD_LIMIT is 2,097,151.

cubrid_ha.conf

  • Users who have configured the ha_apply_max_mem_size parameter value more than 500 must the value to 500 or less.

Environment variable

  • CUBRID_LANG is removed; now the language and the charset of database is set when creating DB, and CUBRID_MSG_LANG is used for configuring the charset of messages for utilities and errors.

    Warning

    When you create database, the language and the charset of database should be specified. It affects the length of string type, string comparison operation, etc. The specified charset when creating database cannot be changed later, so you should be careful when specifying it.

    For charset, locale and collation setting, see An Overview of Globalization.

For more details, see changed-config100.

Upgrading From CUBRID 2008 R4.0 or Earlier Versions To CUBRID 10.0

Users who are using versions CUBRID 2008 R4.0 or earlier should install 10.0 in the different directory, migrate databases to 10.0 and modify parameter values in the existing environment configuration file.

DB migration

Do the same procedures with DB migration. If you use GLO classes, you must modify applications and schema in order to use BLOB or CLOB types, since GLO classes are not supported in 2008 R3.1. If this modification is not easy, it is not recommended to perform the migration.

Parameter configuration

cubrid.conf

  • The minimum size of log_buffer_size is changed from 48KB(3*1page, 16KB=1page) into 2MB(128*1page, 16KB=1page); therefore, this value should be larger than the changed minimum size.

  • The value of sort_buffer_size should be configured as 2G or less since the maximum value of sort_buffer_size is 2G.

  • single_byte_compare should be deleted since this parameter is no longer used.

  • intl_mbs_support should be deleted since this parameter is no longer used.

  • lock_timeout_message_type should be deleted since this parameter is no longer used.

  • Because the default value of thread_stacksize has been changed from 100K to 1M, it is recommended that users who have not configured this value check memory usage of CUBRID-associative processes.

  • Because the minimum value of data_buffer_size has been changed from 64K to 16M, users who have configured this value less than 16M must change the value equal to or greater than 16M.

  • In the following parameters, the old parameters will be deprecated and the new parameters are recommended to use. the value in the parenthesis is the unit of the value when the unit is omitted, and the new parameters can specify the unit after the value. For details, see each parameter's explanation in System Parameters

    Old parameters(unit) New parameters(unit)
    lock_timeout_in_secs(sec) lock_timeout(msec)
    checkpoint_every_npages(page_count) checkpoint_every_size(byte)
    checkpoint_interval_in_mins(min) checkpoint_interval(msec)
    max_flush_pages_per_second(page_count) max_flush_size_per_second(byte)
    sync_on_nflush(page_count) sync_on_flush_size(byte)

cubrid_broker.conf

  • In KEEP_CONNECTION parameter, OFF value should be changed as ON or AUTO since OFF setting value is no longer used.
  • SELECT_AUTO_COMMIT should be deleted since this parameter is no longer used.
  • The value of APPL_SERVER_MAX_SIZE_HARD_LIMIT should be 2,097,151 or less since the maximum value of APPL_SERVER_MAX_SIZE_HARD_LIMIT is 2,097,151.
  • The minimum value of APPL_SERVER_MAX_SIZE_HARD_LIMIT is 1024M. It is recommended that users who configure APPL_SERVER_MAX_SIZE configure this value less than the value of APPL_SERVER_MAX_SIZE_HARD_LIMIT.
  • Because the default value of CCI_DEFAULT_AUTOCOMMIT has been changed to ON, users who have not configured this value should change it to OFF if they want to keep auto commit mode.

cubrid_ha.conf

  • Users who have configured the ha_apply_max_mem_size parameter value more than 500 must the value to 500 or less.

Environment variable

  • CUBRID_LANG is removed; now the language and the charset of database is set when creating DB, and CUBRID_MSG_LANG is used for configuring the charset of messages for utilities and errors.

    Warning

    When you create database, the language and the charset of database should be specified. It affects the length of string type, string comparison operation, etc. The specified charset when creating database cannot be changed later, so you should be careful when specifying it.

    For charset, locale and collation setting, see An Overview of Globalization.

For more details, see changed-config100.

Database Migration under HA Environment

HA migration from CUBRID 2008 R2.2 or higher to CUBRID 10.0

In the scenario described below, the current service is stopped to perform an upgrade in an environment in which a broker, a master DB and a slave DB are operating on different servers.

Step Description
Steps C1-C6: Perform DB migration Run the CUBRID upgrade and database migration in the master node, and back up the new version's database. on the master node.
Step C7: Install new version in the slave node

Delete the previous version of the database from the slave node and install a new version.

For more information, see Installing and Running CUBRID.

Step C8: Restore the backup copy of the master node
in the slave node

Restore the new database backup copy (testdb_bk*) of the master node, which is created in step H6 , to the slave node.

% scp user1@master:$CUBRID/databases/databases.txt $CUBRID/databases/.

% cd ~/DB/testdb

% scp user1@master:~/DB/testdb/testdb_bk0v000 .

% scp user1@master:~/DB/testdb/testdb_bkvinf .

% cubrid restoredb testdb

Step C9: Reconfigure HA environment and start
HA mode
In the master node and the slave node, set the CUBRID environment configuration file (cubrid.conf) and the HA environment configuration file(cubrid_ha.conf) See Creating Databases and Configuring Servers.
Step C10: Install new version in the broker server,
and start the broker

For more information about installation, see Installing and Running CUBRID.

Start the broker in the Broker server. See Configuring and Starting Broker, and Verifying the Broker Status.

% cubrid broker start
HA Migration from CUBRID 2008 R2.0/R2.1 to CUBRID 10.0

If you are using the HA feature of CUBRID 2008 R2.0 or 2008 R2.1, you must upgrade the server version, migrate the database, set up a new HA environment, and then change the Linux Heartbeat auto start setting used in 2008 R2.0 or 2008 R2.1. If the Linux Heartbeat package is not needed, delete it.

Perform steps C1~C10 above, then perform step C11 below:

Step Description
Step C11: Change the previous Linux heartbeat
auto start settings

Perform the following task in the master and slave nodes from a root account.

[root@master ~]# chkconfig --del heartbeat // Performing the same job in the slave node

Uninstalling CUBRID

Uninstalling CUBRID in Linux

Uninstalling CUBRID of SH package or compressed package

To uninstall SH package(file extension of installing package is .sh) or compressed package(file extension of installing package is .tar.gz), proceed the following steps.

  • Remove databases after stopping CUBRID service.

    Remove all created databases after stopping CUBRID service.

    For example, if there are testdb1, testdb2 as databases, do the following commands.

    $ cubrid service stop
    $ cubrid deletedb testdb1
    $ cubrid deletedb testdb2
    
  • Remove CUBRID engine.

    Remove $CUBRID and its subdirectories.

    $ echo $CUBRID
        /home1/user1/CUBRID
    
    $ rm -rf /home1/user1/CUBRID
    
  • Remove auto-starting script.

    If you stored cubrid script in /etc/init.d directory, remove this file.

    cd /etc/init.d
    rm cubrid
    

Uninstalling CUBRID of RPM package

If you have installed CUBRID in RPM package, you can uninstall CUBRID by "rpm" command.

  • Remove databases after stopping CUBRID service.

    Remove all created databases after stopping CUBRID service.

    For example, if there are testdb1, testdb2 as databases, do the following commands.

    $ cubrid service stop
    $ cubrid deletedb testdb1
    $ cubrid deletedb testdb2
    
  • Remove CUBRID engine.

    $ rpm -q cubrid
    cubrid-9.2.0.0123-el5.x86_64
    
    $ rpm -e cubrid
    warning: /opt/cubrid/conf/cubrid.conf saved as /opt/cubrid/conf/cubrid.conf.rpmsave
    
  • Remove auto-starting script.

    If you stored cubrid script in /etc/init.d directory, remove this file.

    cd /etc/init.d
    rm cubrid
    
Uninstalling CUBRID in Windows

Choose "CUBRID" in "Control panel > Uninstall a program" and uninstall it.

Getting Started

This chapter contains useful information on starting CUBRID; also it provides brief instructions on how to use the CSQL Interpreter and GUI tools.

CUBRID provides various tools for you to use easily through GUI. You can download them from http://www.cubrid.org/downloads.

If you use the following tools which CUBRID provides, you can use CUBRID features easily through GUI.

CUBRID also provides various drivers such as JDBC, CCI, PHP, PDO, ODBC, OLE DB, ADO.NET, Perl, Python, and Ruby (see API Reference).

Starting the CUBRID Service

Configure environment variables and language, and then start the CUBRID service. For more information on configuring environment variables and language, see CUBRID Services.

Shell Command

The following shell command can be used to start the CUBRID service and the demodb included in the installation package.

% cubrid service start

@ cubrid master start
++ cubrid master start: success

@ cubrid broker start
++ cubrid broker start: success

@ cubrid manager server start
++ cubrid manager server start: success

% cubrid server start demodb

@ cubrid server start: demodb

This may take a long time depending on the amount of recovery works to do.

CUBRID 9.2

++ cubrid server start: success

@ cubrid server status

Server demodb (rel 9.2, pid 31322)
CUBRIDService or CUBRID Service Tray

On the Windows environment, you can start or stop a service as follows:

  • Go to [Control Panel] > [Performance and Maintenance] > [Administrator Tools] > [Services] and select the CUBRIDService to start or stop the service.

    _images/image5.png
  • In the system tray, right-click the CUBRID Service Tray. To start CUBRID, select [Service Start]; to stop it, select [Service Stop].

    Selecting [Service Start] or [Service Stop] menu would be like executing cubrid service start or cubrid service stop in a command prompt; this command runs or stops the processes configured in service parameters of cubrid.conf.

  • If you click [Exit] while CUBRID is running, all the services and process in the server stop.

Note

An administrator level (SYSTEM) authorization is required to start/stop CUBRID processes through the CUBRID Service tray; a login level user authorization is required to start/stop them with shell commands. If you cannot control the CUBRID processes on the Windows Vista or later version environment, select [Execute as an administrator (A)] in the [Start] > [All Programs] > [Accessories] > [Command Prompt]) or execute it by using the CUBRID Service Tray. When all processes of CUBRID Server stops, an icon on the CUBRID Service tray turns out gray.

Creating Databases

You can create databases by using the cubrid createdb utility and execute it where database volumes and log volumes are located. If you do not specify additional options such as --db-volume-size or --log-volume-size, 1.5 GB volume files are created by default (generic volume is set to 512 MB, active log is set to 512 MB, and background archive log is set to 512 MB).

% cd testdb
% cubrid createdb testdb en_US
% ls -l

-rw------- 1 cubrid dbms 536870912 Jan 11 15:04 testdb
-rw------- 1 cubrid dbms 536870912 Jan 11 15:04 testdb_lgar_t
-rw------- 1 cubrid dbms 536870912 Jan 11 15:04 testdb_lgat
-rw------- 1 cubrid dbms       176 Jan 11 15:04 testdb_lginf
-rw------- 1 cubrid dbms       183 Jan 11 15:04 testdb_vinf

In the above, testdb represents a generic volume file, testdb_lgar_t represents a background archive log file, testdb_lgat represents an active log file, testdb_lginf represents a log information file, and testdb_vinf represents a volume information file.

For details on volumes, see Database Volume Structure . For details on creating volumes, see createdb. It is recommended to classify and add volumes based on its purpose by using the cubrid addvoldb utility. For details, see addvoldb.

Starting Database

You can start a database process by using the cubrid server utility.

% cubrid server start testdb

To have testdb started upon startup of the CUBRID service (cubrid service start), configure testdb in the server parameter of the cubrid.conf file.

% vi cubrid.conf

[service]

service=server,broker,manager
server=testdb

...

Query Tools

CSQL Interpreter

The CSQL Interpreter is a program used to execute the SQL statements and retrieve results in a way that CUBRID supports. The entered SQL statements and the results can be stored as a file. For more information, see Introduction to the CSQL Interpreter and CSQL Execution Mode.

CUBRID also provides a GUI-based program called "CUBRID Manager" or "CUBRID Query Browser." By using these tools, you can execute all SQL statements and retrieve results in the query editor of CUBRID Manager. For more information, see Management Tools.

This section describes how to use the CSQL Interpreter on the Linux environment

Starting the CSQL Interpreter

You can start the CSQL program in the shell as shown below. At the initial installation, PUBLIC and DBA users are provided and the passwords of the users not set. If no user is specified while the CSQL Interpreter is executed, PUBLIC is used for log-in.

% csql demodb

CUBRID SQL Interpreter

Type `;help' for help messages.

csql> ;help

=== <Help: Session Command Summary> ===


   All session commands should be prefixed by `;' and only blanks/tabs
   can precede the prefix. Capitalized characters represent the minimum
   abbreviation that you need to enter to execute the specified command.

   ;REAd   [<file-name>]       - read a file into command buffer.
   ;Write  [<file-name>]       - (over)write command buffer into a file.
   ;APpend [<file-name>]       - append command buffer into a file.
   ;PRINT                      - print command buffer.
   ;SHELL                      - invoke shell.
   ;CD                         - change current working directory.
   ;EXit                       - exit program.

   ;CLear                      - clear command buffer.
   ;EDIT                       - invoke system editor with command buffer.
   ;LISt                       - display the content of command buffer.

   ;RUn                        - execute sql in command buffer.
   ;Xrun                       - execute sql in command buffer,
                                 and clear the command buffer.
   ;COmmit                     - commit the current transaction.
   ;ROllback                   - roll back the current transaction.
   ;AUtocommit [ON|OFF]        - enable/disable auto commit mode.
   ;REStart                    - restart database.

   ;SHELL_Cmd  [shell-cmd]     - set default shell, editor, print and pager
   ;EDITOR_Cmd [editor-cmd]      command to new one, or display the current
   ;PRINT_Cmd  [print-cmd]       one, respectively.
   ;PAger_cmd  [pager-cmd]

   ;DATE                       - display the local time, date.
   ;DATAbase                   - display the name of database being accessed.
   ;SChema class-name          - display schema information of a class.
   ;SYntax [sql-cmd-name]      - display syntax of a command.
   ;TRigger [`*'|trigger-name] - display trigger definition.
   ;Get system_parameter       - get the value of a system parameter.
   ;SEt system_parameter=value - set the value of a system parameter.
   ;PLan [simple/detail/off]   - show query execution plan.
   ;Info <command>             - display internal information.
   ;TIme [ON/OFF]              - enable/disable to display the query
                                 execution time.
   ;LINe-output [ON/OFF]       - enable/disable to display each value in a line
   ;HISTORYList                - display list of the executed queries.
   ;HISTORYRead <history_num>  - read entry on the history number into command buffer.
   ;TRAce [ON/OFF] [text/json] - enable/disable sql auto trace.
   ;HElp                       - display this help message.

Running SQL with CSQL

After the CSQL has been executed, you can enter the SQL into the CSQL prompt. Each SQL statement must end with a semicolon (;). Multiple SQL statements can be entered in a single line. You can find the simple usage of the session commands with the ;help command. For more information, see Session Commands.

% csql demodb

csql> SELECT SUM(n) FROM (SELECT gold FROM participant WHERE nation_code='KOR'
csql> UNION ALL SELECT silver FROM participant WHERE nation_code='JPN') AS t(n);

=== <Result of SELECT Command in Line 2> ===

       sum(n)
=============
           82

1 rows selected. (0.106504 sec) Committed.

csql> ;exit

Management Tools

  Summary of features Downloads of the recent files Links to the latest documents
CUBRID Web Manager

Web based tool for SQL execution and DB operation.

  1. Possible to access to DB with a web browser
  2. Possible to use instantly after installing CUBRID (CUBRID 2008 R4.3 or higher)
  3. Useful to manage a single host
  4. DB access via CUBRID Manager server
CUBRID Web Manager Download CUBRID Web Manager Documents
CUBRID Manager

Java client tool for SQL execution & DB operation.

  1. Java-based management tool (JRE 1.6 or higher required)
  2. Auto upgrade after the initial download
  3. Useful to manage multiple hosts
  4. DB access via CUBRID Manager server
CUBRID Manager Download CUBRID Manager Documents
CUBRID Query Browser

Java client tool for SQL execution only.

  1. Java-based management tool (JRE 1.6 or higher required)
  2. Auto upgrade after the initial download
  3. Useful to manage multiple hosts
  4. Direct DB access via JDBC
CUBRID Query Browser Download CUBRID Query Browser Documents
CUBRID Migration Toolkit

Java-based client tool to migrate schema and data from source DB (MySQL, Oracle, CUBRID) to CUBRID.

  1. Java-based management tool (JRE 1.6 or higher required)
  2. Auto upgrade after the initial download
  3. Available migration only for multiple queries results, the reuse of migration scenario; good to batch job
  4. Direct DB access with JDBC
CUBRID Migration Toolkit Download CUBRID Migration Toolkit Documents
Running SQL with CUBRID Web Manager

Because CUBRID 2008 R4.3 or higher version includes Web Manager on the installation package, you can use the Web Manager instantly after the installation of CUBRID DBMS.

  1. Configure the value of support_web_manager in cm.conf as "YES".

  2. Start CUBRID Service. Web Manager works normally only when CUBRID Manager server is started. For more information, see CUBRID Manager Server.

    C:\CUBRID>cubrid service start
    ++ cubrid service is running.
    
  3. Access to https://localhost:8001/ which is written on the address bar. Note that the header of address is not http, but https.

  4. First, log-in to the host. To access to the host, you should perform the CUBRID Manager server user (=the host user)'s authentication primarily. The default user ID/password is admin/admin.

    _images/gs_manager_login.png
  5. Connect to the DB server. In the tree on the left, you can see the list of databases which have been generated within the corresponding host. Click the DB name that you want to access and perform the DB user authentication (default ID/password: dba/pressing enter key)

    _images/gs_manager_db.png
  6. Run the SQL on the access DB and confirm the result. On the left side, the list of connected databases are displayed. You can edit, run, and find the result on the SQL tab.

    _images/gs_manager_screen.png

For more information, see http://www.cubrid.org/wiki_tools/entry/cubrid-web-manager-manual.

Running SQL with CUBRID Manager Client

CUBRID Manager is the client tool that you should download and run. It is a Java application which requires JRE or JDK 1.6 or higher.

  1. Download and install the latest CUBRID Manager file. CUBRID Manager is compatible with CUBRID DB engine 2008 R2.2 or higher version. It is recommended to upgrade to the latest version periodically; it supports the auto-update feature. (CUBRID FTP: http://ftp.cubrid.org/CUBRID_Tools/CUBRID_Manager )

  2. Start CUBRID service on the server. CUBRID Manager server should be started for CUBRID Manager client to access to DB. For more information, see CUBRID Manager Server.

    C:\CUBRID>cubrid service start
    ++ cubrid service is running.
    
  3. After the installation of CUBRID Manager, register host information on the [File > Add Host] menu. To register the host, you should enter host address, connection port (default: 8001), and CUBRID Manager user name/password and install the JDBC driver of the same version with DB engine (supporting auto-driver-search/auto-update).

  4. Choose the host on the left tress and perform the CUBRID Manager user (=host user) authentication. The default ID/password is admin/admin.

  5. Create a new database as clicking the right mouse button on the database node, or try to connect as choosing the existing database on the bottom of the host node. At this time, do the DB user's login. The default db user is "dba", and there is no password.

  6. Run SQL on the access DB and confirm the result. The host, DB and table list are displayed on the left side, and the query editor and the result window is shown on the right side. You can reuse the SQLs which have been succeeded with [SQL History] tab and compare the multiple results of several DBs as adding the DBs for the comparison of the result with [Multiple Query] tab.

    _images/gs_manager_sql.png

For more information, see http://www.cubrid.org/wiki_tools/entry/cubrid-manager-manual_kr.

Running SQL with CUBRID Query Browser

CUBRID Query Browser (hereafter CQB) is the development tool only for SQL execution, light-weight version of CUBRID Manager (hereafter CM). The differences with CM are as follows:

  • CQB can access DB via JDBC only, without CM server.
  • As a result, DB/broker operating and monitoring features are not supported.
  • As a result, CQB only logs in DB user and CM user login is unnecessary.
  • Running CUBRID Manager server on the server side is unnecessary.

CQB client tool also needs to be downloaded and installed separately from the CUBRID installation package. It is executed on a Java application which requires JRE or JDK 1.6 version or later.

  1. Install the latest CQB file after download. It is compatible with any versions of the engine if you just add the same version's JDBC driver with the DB server. It is recommended to upgrade to the latest version periodically because it supports the auto-update feature. (CUBRID ftp: http://ftp.cubrid.org/CUBRID_Tools/CUBRID_Query_Browser )

  2. Register DB access information on the [File > New Connection] menu after installing CQB. In this case, broker address, broker access port (default: 33,000), DB user, and password should be entered and the JDBC driver which has the same version with DB server should be installed (supporting auto-driver-search/auto-update).

  3. Try to access as choosing DB. In this case, perform DB authentication (default: dba/pressing enter key).

  4. Run SQL on the access DB and confirm the result. The lists of Host, DB, and table are displayed on the left side, and the query editor/result window are shown on the right side. You can reuse the SQLs which have been succeeded with [SQL History] tab and compare the multiple results of several DBs as adding the DBs for the comparison of the result with [Multiple Query] tab.

    _images/gs_manager_qb.png

For more information, see http://www.cubrid.org/wiki_tools/entry/cubrid-query-browser-manual_kr.

Migrating schema/data with CUBRID Migration Toolkit

CUBRID Migration Toolkit is a tool to migrate the data and the schema from the source DB (MySQL, Oracle, and CUBRID) to the target DB (CUBRID). It is also Java applications which require JRE or JDK 1.6 or later. You should download separately. (CUBRID FTP: http://ftp.cubrid.org/CUBRID_Tools/CUBRID_Migration_Toolkit )

It is useful in case of switching from other DB into CUBRID, in case of migrating into other hardware, in case of migrating some schema and data from the operating DB, in case of upgrading CUBRID version, and in case of running the batch jobs. The main features are as follows:

  • Supports the tools/some schema and data migration
  • Available to migrate only the desired data as running several SQLs
  • Executable without suspending of operation as supporting online migration through JDBC
  • Available offline migration with CSV, SQL, CUBRID loaddb format data
  • Available to run directly on the target server as extracting the run-script of migration
  • Shorten the batch job time as reusing the migration run-script.
_images/gs_manager_migration.png

For more information, see http://www.cubrid.org/wiki_tools/entry/cubrid-migration-toolkit-manual.

Drivers

The drivers supported by CUBRID are as follows:

Among above drivers, JDBC and CCI drivers are automatically downloaded while CUBRID is being installed. Thus, you do not have to download them manually.

CSQL Interpreter

To execute SQL statements in CUBRID, you need to use either a Graphical User Interface(GUI)-based CUBRID Query Browser or a console-based CSQL Interpreter.

CSQL is an application that allows users to use SQL statements through a command-driven interface. This section briefly explains how to use the CSQL Interpreter and associated commands.

Introduction to the CSQL Interpreter

A Tool for SQL

The CSQL Interpreter is an application installed with CUBRID that allows you to execute in an interactive or batch mode and viewing query results. The CSQL Interpreter has a command-line interface. With this, you can store SQL statements together with their results to a file for a later use.

The CSQL Interpreter provides the best and easiest way to use CUBRID. You can develop database applications with various APIs (e.g. JDBC, ODBC, PHP, CCI, etc.; you can use the CUBRID Manager, which is a management and query tool provided by CUBRID. With the CSQL Interpreter, users can create and retrieve data in a terminal-based environment.

The CSQL Interpreter directly connects to a CUBRID database and executes various tasks using SQL statements. Using the CSQL Interpreter, you can:

  • Retrieve, update and delete data in a database by using SQL statements
  • Execute external shell commands
  • Store or display query results
  • Create and execute SQL script files
  • Select table schema
  • Retrieve or modify parameters of the database server system
  • Retrieve database information (e.g. schema, triggers, queued triggers, workspaces, locks, and statistics)

A Tool for DBA

A database administrator(DBA) performs administrative tasks by using various administrative utilities provided by CUBRID; a terminal-based interface of CSQL Interpreter is an environment where DBA executes administrative tasks.

It is also possible to run the CSQL Interpreter in standalone mode. In this mode, the CSQL Interpreter directly accesses database files and executes commands including server process properties. That is, SQL statements can be executed to a database without running a separate database server process. The CSQL Interpreter is a powerful tool that allows you to use the database only with a csql utility, without any other applications such as the database server or the brokers.

Executing CSQL

CSQL Execution Mode

Interactive Mode

With CSQL Interpreter, you can enter and execute SQL statements to handle schema and data in the database. Enter statements in a prompt that appears when running the csql utility. After executing the statements, the results are listed in the next line. This is called the interactive mode.

Batch Mode

You can store SQL statements in a file and execute them later to have the csql utility read the file. This is called the batch mode..

Standalone Mode

In the standalone mode, CSQL Interpreter directly accesses database files and executes commands including server process functions. That is, SQL statements can be sent and executed to a database without a separate database server process running for the task. Since the standalone mode allows only one user access at a given time, it is suitable for management tasks by Database Administrators (DBAs).

Client/Server Mode

CSQL Interpreter usually operates as a client process and accesses the server process.

System Administration Mode

You can use this mode when you run checkpoint through CSQL interpreter or exit the transaction monitoring. Also, it allows one connection on CSQL interpreter even if the server access count exceeds the value of max_clients system parameter. In this mode, allowed connection count by CSQL interpreter is only one.

csql -u dba --sysadm demodb
Using CSQL (Syntax)

Connecting to Local Host

Execute the CSQL Interpreter using the csql utility. You can set options as needed. To set the options, specify the name of the database to connect to as a parameter. The following is a csql utility statement to access the database on a local server:

csql [options] database_name

Connecting to Remote Host

The following is a csql utility syntax to access the database on a remote host:

csql [options] database_name@remote_host_name

Make sure that the following conditions are met before you run the CSQL Interpreter on a remote host.

  • The CUBRID installed on the remote host must be the same version as the one on the local host.
  • The port number used by the master process on the remote host must be identical to the one on the local host.
  • You must access the remote host in client/server mode using the -C option.

Example

The following example shows how to access the demodb database on the remote host with the IP address 192.168.1.3 and calls the csql utility.

csql -C demodb@192.168.1.3
CSQL Options

To display the option list in the prompt, execute the csql utilities without specifying the database name as follows:

$ csql
A database-name is missing.
interactive SQL utility, version 9.1
usage: csql [OPTION] database-name[@host]

valid options:
  -S, --SA-mode                standalone mode execution
  -C, --CS-mode                client-server mode execution
  -u, --user=ARG               alternate user name
  -p, --password=ARG           password string, give "" for none
  -e, --error-continue         don't exit on statement error
  -i, --input-file=ARG         input-file-name
  -o, --output-file=ARG        output-file-name
  -s, --single-line            single line oriented execution
  -c, --command=ARG            CSQL-commands
  -l, --line-output            display each value in a line
  -r, --read-only              read-only mode
  -t, --plain-output           display results in a script-friendly format (only works with -c and -i)
  -N, --skip-column-names      do not display column names in results (only works with -c and -i)
      --string-width           display each column which is a string type in this width
      --no-auto-commit         disable auto commit mode execution
      --no-pager               do not use pager
      --no-single-line         turn off single line oriented execution
      --no-trigger-action      disable trigger action

For additional information, see http://www.cubrid.org

Options

-S, --SA-mode

The following example shows how to connect to a database in standalone mode and execute the csql utility. If you want to use the database exclusively, use the -S option. If csql is running in standalone mode, it is impossible to use another csql or utility. If both -S and -C options are omitted, the -C option will be specified.

csql -S demodb
-C, --CS-mode

The following example shows how to connect to a database in client/server mode and execute the csql utility. In an environment where multiple clients connect to the database, use the -C option. Even when you connect to a database on a remote host in client/server mode, the error log created during csql execution will be stored in the cub.err file on the local host.

csql -C demodb
-i, --input-file=ARG

The following example shows how to specify the name of the input file that will be used in a batch mode with the -i option. In the infile file, more than one SQL statement is stored. Without the -i option specified, the CSQL Interpreter will run in an interactive mode.

csql -i infile demodb
-o, --output-file=ARG

The following example shows how to store the execution results to the specified file instead of displaying on the screen. It is useful to retrieve the results of the query performed by the CSQL Interpreter afterwards.

csql -o outfile demodb
-u, --user=ARG

The following example shows how to specify the name of the user that will connect to the specified database with the -u option. If the -u option is not specified, PUBLIC that has the lowest level of authorization will be specified as a user. If the user name is not valid, an error message is displayed and the csql utility is terminated. If there is a password for the user name you specify, you will be prompted to enter the password.

csql -u DBA demodb
-p, --password=ARG

The following example shows how to enter the password of the user specified with the -p option. Especially since there is no prompt to enter a password for the user you specify in a batch mode, you must enter the password using the -p option. When you enter an incorrect password, an error message is displayed and the csql utility is terminated.

csql -u DBA -p *** demodb
-s, --single-line

As an option used with the -i option, it executes multiple SQL statement one by one in a file with the -s option. This option is useful to allocate less memory for query execution and each SQL statement is separated by semicolons (;). If it is not specified, multiple SQL statements are retrieved and executed at once.

csql -s -i infile demodb
-c, --command=ARG

The following example shows how to execute more than one SQL statement from the shell with the -c option. Multiple statements are separated by semicolons (;).

csql -c "select * from olympic;select * from stadium" demodb
-l, --line-output

With -l option, you can display the values of SELECT lists by line. If -l option is omitted, all SELECT lists of the result record are displayed in one line.

csql -l demodb
-e, --error-continue

The following example shows how to ignore errors and keep execution even though semantic or runtime errors occur with the -e option. However, if any SQL statements have syntax errors, query execution stops after errors occur despite specifying the -e option.

$ csql -e demodb

csql> SELECT * FROM aaa;SELECT * FROM athlete WHERE code=10000;

In line 1, column 1,

ERROR: before ' ;SELECT * FROM athlete WHERE code=10000; '
Unknown class "aaa".


=== <Result of SELECT Command in Line 1> ===

         code  name                  gender                nation_code           event
=====================================================================================================
        10000  'Aardewijn Pepijn'    'M'                   'NED'                 'Rowing'


1 rows selected. (0.006433 sec) Committed.
-r, --read-only

You can connect to the read-only database with the -r option. Retrieving data is only allowed in the read-only database; creating databases and entering data are not allowed.

csql -r demodb
-t, --plain-output

It only shows column names and values and works with -c or -i option. Each column and value is separated by a tab and a new line, a tab and a backslash which are included in results are replaced by 'n', 't' and '\' for each. This option is ignored when it is given with -l option.

$ csql testdb@localhost -c "select * from test_tbl" -t

col1 col2 col3
string1 12:16:10.090 PM 10/23/2014
string2 12:16:10.090 PM 10/23/2014
string3 12:16:10.090 PM 10/23/2014
string4 12:16:10.090 PM 10/23/2014
string5 12:16:10.090 PM 10/23/2014
string6 12:16:10.090 PM 10/23/2014
string7 12:16:10.090 PM 10/23/2014
string8 12:16:10.090 PM 10/23/2014
string9 12:16:10.090 PM 10/23/2014
string10 12:16:10.090 PM 10/23/2014
-N, --skip-column-names

It will hide column names from the results. It only works with -c or -i option and is usually used with -t option. This option is ignored when it is given with -l option.

$ csql testdb@localhost -c "select * from test_tbl" -t -N

string1 12:16:10.090 PM 10/23/2014
string2 12:16:10.090 PM 10/23/2014
string3 12:16:10.090 PM 10/23/2014
string4 12:16:10.090 PM 10/23/2014
string5 12:16:10.090 PM 10/23/2014
string6 12:16:10.090 PM 10/23/2014
string7 12:16:10.090 PM 10/23/2014
string8 12:16:10.090 PM 10/23/2014
string9 12:16:10.090 PM 10/23/2014
string10 12:16:10.090 PM 10/23/2014
--no-auto-commit

The following example shows how to stop the auto-commit mode with the --no-auto-commit option. If you don't configure --no-auto-commit option, the CSQL Interpreter runs in an auto-commit mode by default, and the SQL statement is committed automatically at every execution. Executing the ;AUtocommit session command after starting the CSQL Interpreter will also have the same result.

csql --no-auto-commit demodb
--no-pager

The following example shows how to display the execution results by the CSQL Interpreter at once instead of page-by-page with the --no-pager option. The results will be output page-by-page if --no-pager option is not specified.

csql --no-pager demodb
--no-single-line

The following example shows how to keep storing multiple SQL statements and execute them at once with the ;xr or ;r session command. If you do not specify this option, SQL statements are executed without ;xr or ;r session command.

csql --no-single-line demodb
--sysadm

This option should be used together with -u dba. It is specified when you want to run CSQL in a system administrator's mode.

csql -u dba --sysadm demodb
--write-on-standby

This option should be used together with a system administrator's mode option(--sysadm--). dba which run CSQL with this option can write directly to the standby DB (slave DB or replica DB). However, the data to be written directly to the replica DB are not replicated.

csql --sysadm --write-on-standby -u dba testdb@localhost

Note

Please note that replication mismatch occurs when you write the data directly to the replica DB.

--no-trigger-action

If you specify this option, triggers of the queries executed in this CSQL are not triggered.

Session Commands

In addition to SQL statements, CSQL Interpreter provides special commands allowing you to control the Interpreter. These commands are called session commands. All the session commands must start with a semicolon (;).

Enter the ;help command to display a list of the session commands available in the CSQL Interpreter. Note that only the uppercase letters of each session command are required to make the CSQL Interpreter to recognize it. Session commands are not case-sensitive.

"Query buffer" is a buffer to store the query before running it. If you run CSQL as giving the --no-single-line option, the query string is kept on the buffer until running ;xr command.

Reading SQL statements from a file (;REAd)

The ;REAd command reads the contents of a file into the buffer. This command is used to execute SQL commands stored in the specified file. To view the contents of the file loaded into the buffer, use the ;List command.

csql> ;read nation.sql
The file has been read into the command buffer.
csql> ;list
insert into "sport_event" ("event_code", "event_name", "gender_type", "num_player") values
(20001, 'Archery Individual', 'M', 1);
insert into "sport_event" ("event_code", "event_name", "gender_type", "num_player") values
20002, 'Archery Individual', 'W', 1);
....

Storing SQL statements into a file (;Write)

The ;Write command stores the contents of the query buffer into a file. This command is used to store queries that you entered or modified in the CSQL Interpreter.

csql> ;write outfile
Command buffer has been saved.

Appending to a file (;APpend)

This command appends the contents of the current query buffer to an outfile file.

csql> ;append outfile
Command buffer has been saved.

Executing a shell command (;SHELL)

The ;SHELL session command calls an external shell. Starts a new shell in the environment where the CSQL Interpreter is running. It returns to the CSQL Interpreter when the shell terminates. If the shell command to execute with the ;SHELL_Cmd command has been specified, it starts the shell, executes the specified command, and returns to the CSQL Interpreter.

csql> ;shell
% ls -al
total 2088
drwxr-xr-x 16 DBA cubrid   4096 Jul 29 16:51 .
drwxr-xr-x  6 DBA cubrid   4096 Jul 29 16:17 ..
drwxr-xr-x  2 DBA cubrid   4096 Jul 29 02:49 audit
drwxr-xr-x  2 DBA cubrid   4096 Jul 29 16:17 bin
drwxr-xr-x  2 DBA cubrid   4096 Jul 29 16:17 conf
drwxr-xr-x  4 DBA cubrid   4096 Jul 29 16:14 cubridmanager
% exit
csql>

Registering a shell command (;SHELL_Cmd)

The ;SHELL_Cmd command registers a shell command to execute with the SHELL session command. As shown in the example below, enter the ;shell command to execute the registered command.

csql> ;shell_c ls -la
csql> ;shell
total 2088
drwxr-xr-x 16 DBA cubrid   4096 Jul 29 16:51 .
drwxr-xr-x  6 DBA cubrid   4096 Jul 29 16:17 ..
drwxr-xr-x  2 DBA cubrid   4096 Jul 29 02:49 audit
drwxr-xr-x  2 DBA cubrid   4096 Jul 29 16:17 bin
drwxr-xr-x  2 DBA cubrid   4096 Jul 29 16:17 conf
drwxr-xr-x  4 DBA cubrid   4096 Jul 29 16:14 cubridmanager
csql>

Registering a pager command (;PAger_cmd)

The ;PAger_cmd command registers a pager command to display the query result. The way of displaying is decided by the registered command. The default is more. Also cat and less can be used. But ;Pager_cmd command works well only on Linux.

When you register pager command as more, the query result shows by page and wait until you press the space key.

csql>;pager more

When you register pager command as cat, the query result shows all in one display without paging.

csql>;pager cat

When you redirect the output with a file, the total query result will be written on the file.

csql>;pager cat > output.txt

If you register pager command as less, you can forward, backward the query result. Also pattern matching on the query result is possible.

csql>;pager less

The keyboard commands used on the less are as follows.

  • Page UP, b: go up to one page. (backwording)
  • Page Down, Space: go down to one page (forwarding)
  • /string: find a sting on the query results
  • n: find the next string
  • N: find the previous string
  • q: quit the paging mode.

Changing the current working directory (;CD)

This command changes the current working directory where the CSQL Interpreter is running to the specified directory. If you don't specify the path, the directory will be changed to the home directory.

csql> ;cd /home1/DBA/CUBRID
Current directory changed to  /home1/DBA/CUBRID.

Exiting the CSQL Interpreter (;EXit)

This command exits the CSQL Interpreter.

csql> ;ex

Clearing the query buffer (;CLear)

The ;CLear session command clears the contents of the query buffer.

csql> ;clear
csql> ;list

Displaying the contents of the query buffer (;List)

The ;List session command lists the contents of the query buffer that have been entered or modified. The query buffer can be modified by ;READ or ;Edit command.

csql> ;list

Executing SQL statements (;RUn)

This command executes SQL statements in the query buffer. Unlike the ;Xrun session command described below, the buffer will not be cleared even after the query execution.

csql> ;run

Clearing the query buffer after executing the SQL statement (;Xrun)

This command executes SQL statements in the query buffer. The buffer will be cleared after the query execution.

csql> ;xrun

Committing transaction (;COmmit)

This command commits the current transaction. You must enter a commit command explicitly if it is not in auto-commit mode. In auto-commit mode, transactions are automatically committed whenever SQL is executed.

csql> ;commit
Execute OK. (0.000192 sec)

Rolling back transaction (;ROllback)

This command rolls back the current transaction. Like a commit command (;COmmit), it must enter a rollback command explicitly if it is not in auto-commit mode (OFF).

csql> ;rollback
Execute OK. (0.000166 sec)

Setting the auto-commit mode (;AUtocommit)

This command sets auto-commit mode to ON or OFF. If any value is not specified, current configured value is applied by default. The default value is ON.

csql> ;autocommit off
AUTOCOMMIT IS OFF

CHeckpoint Execution (;CHeckpoint)

This command executes the checkpoint within the CSQL session. This command can only be executed when a DBA group member, who is specified for the custom option (-u user_name), connects to the CSQL Interpreter in system administrator mode (--sysadm).

Checkpoint is an operation of flushing all dirty pages within the current data buffer to disks. You can also change the checkpoint interval using a command (;set parameter_name value) to set the parameter values in the CSQL session. You can see the examples of the parameter related to the checkpoint execution interval (checkpoint_interval and checkpoint_every_size). For more information, see Logging-Related Parameters.

sysadm> ;checkpoint
Checkpoint has been issued.

Transaction Monitoring Or Termination (;Killtran)

This command checks the transaction status information or terminates a specific transaction in the CSQL session. This command prints out the status information of all transactions on the screen if a parameter is omitted it terminates the transaction if a specific transaction ID is specified for the parameter. It can only be executed when a DBA group member, who is specified for the custom option (-u user_name), connects to the CSQL Interpreter in system administrator mode (--sysadm).

sysadm> ;killtran
Tran index      User name      Host name      Process id      Program name
-------------------------------------------------------------------------------
      1(+)            dba      myhost             664           cub_cas
      2(+)            dba      myhost            6700              csql
      3(+)            dba      myhost            2188           cub_cas
      4(+)            dba      myhost             696              csql
      5(+)         public      myhost            6944              csql

sysadm> ;killtran 3
The specified transaction has been killed.

Restarting database (;REStart)

A command that tries to reconnect to the target database in a CSQL session. Note that when you execute the CSQL Interpreter in CS (client/server) mode, it will be disconnected from the server. When the connection to the server is lost due to a HA failure and failover to another server occurs, this command is particularly useful in connecting to the switched server while maintaining the current session.

csql> ;restart
The database has been restarted.

Displaying the current date (;DATE)

The ;DATE command displays the current date and time in the CSQL Interpreter.

csql> ;date
     Tue July 29 18:58:12 KST 2008

Displaying the database information (;DATAbase)

This command displays the database name and host name where the CSQL Interpreter is working. If the database is running, the HA mode (one of those following: active, standby, or maintenance) will be displayed as well.

csql> ;database
     demodb@cubridhost (active)

Displaying schema information of a class (;SChema)

The ;SChema session command displays schema information of the specified table. The information includes the table name, its column name and constraints.

csql> ;schema event
=== <Help: Schema of a Class> ===
 <Class Name>
     event
 <Attributes>
     code           INTEGER NOT NULL
     sports         CHARACTER VARYING(50)
     name           CHARACTER VARYING(50)
     gender         CHARACTER(1)
     players        INTEGER
 <Constraints>
     PRIMARY KEY pk_event_event_code ON event (code)

Displaying the trigger (;TRigger)

This command searches and displays the trigger specified. If there is no trigger name specified, all the triggers defined will be displayed.

csql> ;trigger
=== <Help: All Triggers> ===
    trig_delete_contents

Checking the parameter value(;Get)

You can check the parameter value currently set in the CSQL Interpreter using the ;Get session command. An error occurs if the parameter name specified is incorrect.

csql> ;get isolation_level
=== Get Param Input ===
isolation_level=4

Setting the parameter value (;SEt)

You can use the ;Set session command to set a specific parameter value. Note that changeable parameter values are only can be changed. To change the server parameter values, you must have DBA authorization. For information on list of changeable parameters, see Broker Configuration.

csql> ;set block_ddl_statement=1
=== Set Param Input ===
block_ddl_statement=1

-- Dynamically change the log_max_archives value in the csql accessed by dba account
csql> ;set log_max_archives=5

Setting the output width of string (;STring-width)

You can use the ;STring-width command to set the output width of character string or BIT string.

;string-width session command without a length shows the current setting length. When it is set to 0, the columns will be displayed as it is. If it sets greater than 0, the string typed columns will be displayed with the specified length.

csql> SELECT name FROM NATION WHERE NAME LIKE 'Ar%';
  'Arab Republic of Egypt'
  'Aruba'
  'Armenia'
  'Argentina'

csql> ;string-width 5
csql>  SELECT name FROM NATION WHERE NAME LIKE 'Ar%';
  'Arab '
  'Aruba'
  'Armen'
  'Argen'

csql> ;string-width
STRING-WIDTH : 5

Setting the output width of the column (;COLumn-width)

You can use the ;COLumn-width command to set the output width regardless of its data types. If you don't give a value after ;COL command, it shows the current setting length. When it sets to 0, the columns will be displayed as it is. If it sets to greater than 0, the columns will be displayed with the specified length.

csql> CREATE TABLE tbl(a BIGINT, b BIGINT);
csql> INSERT INTO tbl VALUES(12345678890, 1234567890)
csql> ;column-width a=5
csql> SELECT * FROM tbl;
      12345            1234567890
csql> ;column-width
COLUMN-WIDTH a : 5

Setting the view level of executing query plan (;PLan)

You can use the ;PLan session command to set the view level of executing query plan the level is composed of simple, detail, and off. Each command refers to the following:

  • off: Not displaying the query execution plan
  • simple: Displaying the query execution plan in simple version (OPT LEVEL=257)
  • detail: Displaying the query execution plan in detailed version (OPT LEVEL=513)

Setting SQL trace(;trace)

The ;trace session command specifies if SQL trace result is printed out together with query result or not. When you set SQL trace ON by using this command, the result of query profiling is automatically shown even if you do not run "SHOW TRACE;" syntax.

For more information, see Query Profiling.

The command format is as follows.

;trace {on | off} [{text | json}]
  • on: set on SQL trace.
  • off: set off SQL trace.
  • text: print out as a general TEXT format. If you omit OUTPUT clause, TEXT format is specified.
  • json: print out as a JSON format.

Note

CSQL interpreter which is run in the standalone mode(use -S option) does not support SQL trace feature.

Displaying information (;Info)

The ;Info session command allows you to check information such as schema, triggers, the working environment, locks and statistics.

csql> ;info lock
*** Lock Table Dump ***
 Lock Escalation at = 100000, Run Deadlock interval = 1
Transaction (index  0, unknown, unknown@unknown|-1)
Isolation COMMITTED READ
State TRAN_ACTIVE
Timeout_period -1
......

Dumping CSQL execution statistics information(;.Hist)

This command is a CSQL session command for starting to collect the statistics information in CSQL. The information is collected only for the currently connected CSQL after ";.Hist on" command is entered. Following options are provided for this session command.

  • on: Starts collecting statistics information for the current connection.
  • off: Stops collecting statistics information of server.

This command is executable while the communication_histogram parameter in the cubrid.conf file is set to yes. You can also view this information by using the cubrid statdump utility.

After running ";.Hist on", the execution commands such as ;.dump_hist or ;.x must be entered to output the statistics information. After ;.dump_hist or ;.x, all accumulated data are dumped and initiated.

As a reference, you should use cubrid statdump utility to check all queries' statistics information of a database server.

This example shows the server statistics information for current connection. For information on dumped specific items or cubrid statdump command, see statdump.

csql> ;.hist on
csql> ;.x
Histogram of client requests:
Name                            Rcount   Sent size  Recv size , Server time
 No server requests made

 *** CLIENT EXECUTION STATISTICS ***
System CPU (sec)              =          0
User CPU (sec)                =          0
Elapsed (sec)                 =         20

 *** SERVER EXECUTION STATISTICS ***
Num_file_creates              =          0
Num_file_removes              =          0
Num_file_ioreads              =          0
Num_file_iowrites             =          0
Num_file_iosynches            =          0
Num_data_page_fetches         =         56
Num_data_page_dirties         =         14
Num_data_page_ioreads         =          0
Num_data_page_iowrites        =          0
Num_data_page_victims         =          0
Num_data_page_iowrites_for_replacement =          0
Num_log_page_ioreads          =          0
Num_log_page_iowrites         =          0
Num_log_append_records        =          0
Num_log_archives              =          0
Num_log_checkpoints           =          0
Num_log_wals                  =          0
Num_page_locks_acquired       =          2
Num_object_locks_acquired     =          2
Num_page_locks_converted      =          0
Num_object_locks_converted    =          0
Num_page_locks_re-requested   =          0
Num_object_locks_re-requested =          1
Num_page_locks_waits          =          0
Num_object_locks_waits        =          0
Num_tran_commits              =          1
Num_tran_rollbacks            =          0
Num_tran_savepoints           =          0
Num_tran_start_topops         =          3
Num_tran_end_topops           =          3
Num_tran_interrupts           =          0
Num_btree_inserts             =          0
Num_btree_deletes             =          0
Num_btree_updates             =          0
Num_btree_covered             =          0
Num_btree_noncovered          =          0
Num_btree_resumes             =          0
Num_query_selects             =          1
Num_query_inserts             =          0
Num_query_deletes             =          0
Num_query_updates             =          0
Num_query_sscans              =          1
Num_query_iscans              =          0
Num_query_lscans              =          0
Num_query_setscans            =          0
Num_query_methscans           =          0
Num_query_nljoins             =          0
Num_query_mjoins              =          0
Num_query_objfetches          =          0
Num_network_requests          =          8
Num_adaptive_flush_pages      =          0
Num_adaptive_flush_log_pages  =          0
Num_adaptive_flush_max_pages  =          0

 *** OTHER STATISTICS ***
Data_page_buffer_hit_ratio    =     100.00
csql> ;.hist off

Displaying query execution time (;TIme)

The ;TIme session command can be set to display the elapsed time to execute the query. It can be set to ON or OFF. The current setting is displayed if there is no value specified. The default value is ON.

The SELECT query includes the time of outputting the fetched records. Therefore, to check the execution time of complete output of all records in the SELECT query, use the --no-pager option while executing the CSQC interpreter.

$ csql -u dba --no-pager demodb
csql> ;time ON
csql> ;time
TIME IS ON

Displaying a column of result record in one line(;LINe-output)

If this value is set to ON, it makes the record display in several lines by column. The default value is OFF, which makes one record display in one line.

csql> ;line-output ON
csql> select * from athlete;

=== <Result of SELECT Command in Line 1> ===

<00001> code       : 10999
        name       : 'Fernandez Jesus'
        gender     : 'M'
        nation_code: 'ESP'
        event      : 'Handball'
<00002> code       : 10998
        name       : 'Fernandez Jaime'
        gender     : 'M'
        nation_code: 'AUS'
        event      : 'Rowing'
...

Displaying query history (;HISTORYList)

This command displays the list that contains previously executed commands (input) and their history numbers.

csql> ;historylist
----< 1 >----
select * from nation;
----< 2 >----
select * from athlete;

Reading input with the specified history number into the buffer (;HISTORYRead)

You can use ;HISTORYRead session command to read input with history number in the ;HISTORYList list into the command buffer. You can enter ;run or ;xrun directly because it has the same effect as when you enter SQL statements directly.

csql> ;historyread 1

Calling the default editor (;EDIT)

This command calls the specified editor. The default editor is vi on Linux Notepad on Windows environment. Use ;EDITOR_Cmd command to specify a different editor.

csql> ;edit

Specifying the editor (;EDITOR_Cmd)

This command specifies the editor to be used with ;EDIT session command. As shown in the example below, you can specify other editor (ex: emacs) which is installed in the system.

csql> ;editor_cmd emacs
csql> ;edit

CUBRID SQL

This chapter describes SQL syntax such as data types, functions and operators, data retrieval or table manipulation. You can also find SQL statements used for index, trigger, partition, serial and changing user information.

The main topics covered in this chapter are as follows:

  • Writing Rules
    • Identifier: Describes how to write, the identifier, string allowed to be used as a name of a table, index, and column.
    • Reserved words: Lists reserved words in CUBRID. To use a reserved word as an identifier, enclose the identifier by using double quotes, backticks (`), or brackets ([]).
    • Comment
    • LIteral: Describes how to write constant values.
  • Data types: Describes the data types, the format to store data.
  • Data Definition Statements: Describes how to create, alter, drop, and rename a table, an index, a view and a serial.
  • Operators and Functions: Describes the operators and functions used for query statements.
  • Data Manipulation Statements: Describes the SELECT, INSERT, UPDATE, and DELETE statements.
  • Query Optimization: Describes the query optimization by using the index, hint, and the index hint syntax.
  • Partitioning: Describes how to partition one table into several independent logical units.
  • Trigger: Describes how to create, alter, drop, and rename a trigger that is automatically executed in response to certain events.
  • Java Stored Functions/Procedures: Describes how to create a Java method and call it in the query statement.
  • Method: Describes the method, a built-in function of the CUBRID database system.
  • Class Inheritance: Describes how to inherit the attribute from the parent to the child table (class).
  • Database Adminstration: Describes about user management, SET and SHOW statements.
  • System Catalog: Describes the CUBRID system catalog, the internal information of the CUBRID database.

Writing Rules

Identifier
Guidelines for Creating Identifiers

Table name, index name, view name, column name, user name etc. are included in identifier. The guidelines for creating identifiers are as follows:

  • An identifier must begin with a letter; it must not begin with a number or a symbol.
  • It is not case-sensitive.
  • Reserved Words are not allowed.
identifier        ::=  identifier_letter [ { other_identifier }; ]
identifier_letter ::=  upper_case_letter | lower_case_letter
other_identifier  ::=  identifier_letter | digit | _ | #
digit             ::=  0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
upper_case_letter ::=  A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P| Q | R | S | T | U | V | W | X | Y | Z
lower_case_letter ::=  a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p| q | r | s | t | u | v | w | x | y | z
Illegal Identifiers

Beginning with special characters or numbers

An identifier starting with a special character or a number is not allowed. As an exception, a underline (_) and a sharp symbol (#) are allowed for the first character.

_a
#ack
%nums
2fer
88abs

An identifier containing a space

An identifier that a space within characters is not allowed.

col1 t1

An identifier containing operator special characters

An identifier which contains operator special characters (+, -, *, /, %, ||, !, < , > , =, |, ^, & , ~ ) is not allowed.

col+
col~
col& &
The maximum length of an identifier name

The following table summarizes the maximum byte length allowable for each identifier name. Note that the unit is byte and the number of characters and the bytes are different by the character set used (for example, the length of one Korean character in UTF-8 is 3 bytes).

Identifier Maximum Bytes
Database 17
Table 254
Column 254
Index 254
Constraint 254
Java Stored Procedure 254
Trigger 254
View 254
Serial 254

Note

Automatically created constraint name like a name of primary key(pk_<table_name>_<column_name>) or foreign key(fk_<table_name>_<column_name>) also does not allow over the maximum name length of the identifier, 254 bytes.

Reserved Words

The following keywords are previously reserved as a command, a function name or a type name in CUBRID. You are restricted to use these words for a class name, an attribute name, a variable name. Note than these reserved keywords can be used an identifier when they are enclosed in double quotes, square brackets, or backtick symbol (`).

ABSOLUTE ACTION ADD
ADD_MONTHS AFTER ALL
ALLOCATE ALTER AND
ANY ARE AS
ASC ASSERTION AT
ATTACH ATTRIBUTE AVG
BEFORE BETWEEN BIGINT
BINARY BIT BIT_LENGTH
BLOB BOOLEAN BOTH
BREADTH BY  
CALL CASCADE CASCADED
CASE CAST CATALOG
CHANGE CHAR CHARACTER
CHECK CLASS CLASSES
CLOB CLOSE COALESCE
COLLATE COLLATION COLUMN
COMMIT CONNECT CONNECT_BY_ISCYCLE
CONNECT_BY_ISLEAF CONNECT_BY_ROOT CONNECTION
CONSTRAINT CONSTRAINTS CONTINUE
CONVERT CORRESPONDING COUNT
CREATE CROSS CURRENT
CURRENT_DATE CURRENT_DATETIME CURRENT_TIME
CURRENT_TIMESTAMP CURRENT_USER CURSOR
CYCLE    
DATA DATA_TYPE DATABASE
DATE DATETIME DAY
DAY_HOUR DAY_MILLISECOND DAY_MINUTE
DAY_SECOND DEALLOCATE DEC
DECIMAL DECLARE DEFAULT
DEFERRABLE DEFERRED DELETE
DEPTH DESC DESCRIBE
DESCRIPTOR DIAGNOSTICS DIFFERENCE
DISCONNECT DISTINCT DISTINCTROW
DIV DO DOMAIN
DOUBLE DUPLICATE DROP
EACH ELSE ELSEIF
END EQUALS ESCAPE
EVALUATE EXCEPT EXCEPTION
EXEC EXECUTE EXISTS
EXTERNAL EXTRACT  
FALSE FETCH FILE
FIRST FLOAT FOR
FOREIGN FOUND FROM
FULL FUNCTION  
GENERAL GET GLOBAL
GO GOTO GRANT
GROUP    
HAVING HOUR HOUR_MILLISECOND
HOUR_MINUTE HOUR_SECOND  
IDENTITY IF IGNORE
IMMEDIATE IN INDEX
INDICATOR INHERIT INITIALLY
INNER INOUT INPUT
INSERT INT INTEGER
INTERSECT INTERSECTION INTERVAL
INTO IS ISOLATION
JOIN    
KEY    
LANGUAGE LAST LEADING
LEAVE LEFT LESS
LEVEL LIKE LIMIT
LIST LOCAL LOCAL_TRANSACTION_ID
LOCALTIME LOCALTIMESTAMP LOOP
LOWER    
MATCH MAX METHOD
MILLISECOND MIN MINUTE
MINUTE_MILLISECOND MINUTE_SECOND MOD
MODIFY MODULE MONTH
MULTISET MULTISET_OF  
NA NAMES NATIONAL
NATURAL NCHAR NEXT
NO NONE NOT
NULL NULLIF NUMERIC
OBJECT OCTET_LENGTH OF
OFF ON ONLY
OPEN OPTIMIZATION OPTION
OR ORDER OUT
OUTER OUTPUT OVERLAPS
PARAMETERS PARTIAL POSITION
PRECISION PREPARE PRESERVE
PRIMARY PRIOR PRIVILEGES
PROCEDURE    
QUERY    
READ REAL RECURSIVE
REF REFERENCES REFERENCING
RELATIVE RENAME REPLACE
RESIGNAL RESTRICT RETURN
RETURNS REVOKE RIGHT
ROLE ROLLBACK ROLLUP
ROUTINE ROW ROWNUM
ROWS    
SAVEPOINT SCHEMA SCOPE
SCROLL SEARCH SECOND
SECOND_MILLISECOND SECTION SELECT
SENSITIVE SEQUENCE SEQUENCE_OF
SERIALIZABLE SESSION SESSION_USER
SET SET_OF SETEQ
SHARED SIBLINGS SIGNAL
SIMILAR SIZE SMALLINT
SOME SQL SQLCODE
SQLERROR SQLEXCEPTION SQLSTATE
SQLWARNING STATISTICS STRING
SUBCLASS SUBSET SUBSETEQ
SUBSTRING SUM SUPERCLASS
SUPERSET SUPERSETEQ SYS_CONNECT_BY_PATH
SYS_DATE SYS_DATETIME SYS_TIME
SYS_TIMESTAMP SYSDATE SYSDATETIME
SYSTEM_USER SYSTIME  
TABLE TEMPORARY THEN
TIME TIMESTAMP TIMEZONE_HOUR
TIMEZONE_MINUTE TO TRAILING
TRANSACTION TRANSLATE TRANSLATION
TRIGGER TRIM TRUE
TRUNCATE    
UNDER UNION UNIQUE
UNKNOWN UPDATE UPPER
USAGE USE USER
USING UTIME  
VALUE VALUES VARCHAR
VARIABLE VARYING VCLASS
VIEW    
WHEN WHENEVER WHERE
WHILE WITH WITHOUT
WORK WRITE  
XOR    
YEAR YEAR_MONTH  
ZONE    
Comment

There are 3 types of comments. One is a SQL-style which starts with '--', the other is C++ style starts with '//'. Both regards the entire line starts with the comment symbols is a comment line. The C style starts with '/*' and ends with '*/'

The following are examples of comments.

  • How to use --

    -- This is a SQL-style comment.
    
  • How to use //

    // This is a C++ style comment.
    
  • How to use /* */

    /* This is a C-style comment.*/
    
    /* This is an example to use two lines
    as comment by using the C-style. */
    
Literal

This section describes how to write a literal value in CUBRID.

Number

There are two ways of writing a number; how to write an exact value and how to write an approximate value.

  • An exact number is written as a serial numbers and a dot (.); this input literal is translated as an INT, BIGINT or NUMERIC typed value based on its range.

    10, 123456789012, 1234234324234.23
    
  • An approximate number is written as a serial numbers, a dot (.) and E (scientific notation, multiples of 10); this input literal is translated as a DOUBLE typed value.

    1.2345E15, 12345E5
    
    • or - symbol can be written in front of a number, and this can be written between E which indicates multiples of 10 and a number.
    +10.2345, -1.2345E-15
    
Date/Time

For representing data and time, there are DATE, TIME, DATETIME and TIMESTAMP types; these values can be represented as adding date, time, datetime and timestamp literals (case-insensitive) in front of their strings.

If you use date/time literals, you don't need to use converting functions such as TO_DATE(), TO_TIME(), TO_DATETIME() and TO_TIMESTAMP(). However, the writing order of a string which indicates date or time.

  • The date literal only allows 'YYYY-MM-DD' or 'MM/DD/YYYY'.

    date'1974-12-31', date'12-31-1974'
    
  • The time literal only allows 'HH:MI:SS', 'HH:MI:SS AM' or 'HH:MI:SS PM'.

    time'12:13:25', time'12:13:25 AM', time'12:13:25 PM'
    
  • The date/time literal used in DATETIME type allows 'YYYY-MM-DD HH:MI:SS[.msec AM|PM]' or 'MM/DD/YYYY HH:MI:SS[.msec AM|PM]'. msec means milliseconds, which can be written until 3 digits.

    datetime'1974-12-31 12:13:25.123 AM', datetime'12/31/1974 12:13:25.123 AM'
    
  • The date/time literal used in TIMESTAMP type allows 'YYYY-MM-DD HH:MI:SS[ AM|PM]' or 'MM/DD/YYYY HH:MI:SS[ AM|PM]'.

    timestamp'1974-12-31 12:13:25 AM', timestamp'12/31/1974 12:13:25 AM'
    
  • The literal of date/time with timezone type has the same format as the above, and add an offset or a region name which indicates a timezone information.

    • Add datetimetz, datetimeltz, timestamptz or timestampltz literal at the front of a string to represent each type's value.

      datetimetz'10/15/1986 5:45:15.135 am +02:30:20';
      datetimetz'10/15/1986 5:45:15.135 am +02:30';
      datetimetz'10/15/1986 5:45:15.135 am +02';
      datetimeltz'10/15/1986 5:45:15.135 am Europe/Bucharest'
      datetimetz'2001-10-11 02:03:04 AM Europe/Bucharest EEST';
      timestampltz'10/15/1986 5:45:15 am Europe/Bucharest'
      timestamptz'10/15/1986 5:45:15 am Europe/Bucharest'
      
    • The literal at the front of a string can be replaced with "<date/time type> WITH TIMEZONE" or <date/time type> WITH LOCAL TIME ZONE.

      ::

      DATETIME WITH TIMEZONE = datetimetz DATETIME WITH LOCAL TIMEZONE = datetimeltz TIMESTAMP WITH TIMEZONE = timestamptz TIMESTAMP WITH LOCAL TIMEZONE = timestampltz

      DATETIME WITH TIME ZONE'10/15/1986 5:45:15.135 am +02';
      DATETIME WITH LOCAL TIME ZONE'10/15/1986 5:45:15.135 am +02';
      

    Note

    • <date/time type> WITH LOCAL TIME ZONE: internally stores UTC time; it is converted as a local (current session) timezone when it is output.
    • <date/time type> WITH TIME ZONE: internally stores UTC time and timezone information (decided by a user or a session timezone) when this value is created.
Bit String

Bit string uses two formats of binary format and hexadecimal format.

Binary format is written as adding B or 0b in front of a number; the input value is a string with 0 and 1 after B, and a number with 0 and 1 after 0b.

B'10100000'
0b10100000

Binary number is written by 8 digits; if the input digits are not divided into 8, this value is saved as 0s are attached. For example, B'1' is saved as B'10000000'.

Hexadecimal format is written as adding X or 0x in front of a number; the input value is a string with hexadecimal after X, and a number with hexadecimal after 0x.

X'a0'
0xA0

Hexadecimal number is written by 2 digits; if the input digits are not divided into 2, this value is saved as 0s are attached. For example, X'a' is saved as X'a0'.

Character String

Character string is written as wrapped in single quotes.

  • If you want to include a single quote in a string, input it twice serially.

    SELECT 'You''re welcome.';
    
  • An escape using a backslash can be used if you set no_backslash_escapes in cubrid.conf as no. But this default value is yes.

    For details, see Escape Special Characters.

  • Charset introducer can be located in front of a string, and COLLATE modifier can be localted after a string.

    For details, see Charset Introducer.

Collection

In collection types, there are SET, MULTISET and LIST; their values are written as elements are wrapped in braces ({, }).

{'c','c','c','b','b','a'}

For details, see Collection Types.

NULL

NULL value means there is no data. NULL is case-insensitive, so it also can be written as null. Please note that NULL value is not 0 in a number type or an empty string ('') in a string type.

Data Types

Numeric Types

CUBRID supports the following numeric data types to store integers or real numbers.

Type Bytes Min Max Exact/approx.
SHORT, SMALLINT 2 -32,768 32,767 exact numeric
INTEGER, INT 4 -2,147,483,648 +2,147,483,647 exact numeric
BIGINT 8 -9,223,372,036,854,775,808 +9,223,372,036,854,775,807 exact numeric
NUMERIC, DECIMAL 16

precision p: 1

scale s: 0

precision p: 38

scale s: 38

exact numeric
FLOAT, REAL 4 -3.402823466E+38 (ANSI/IEEE 754-1985 standard) +3.402823466E+38 (ANSI/IEEE 754-1985 standard) approximate numeric floating point : 7
DOUBLE, DOUBLE PRECISION 8 -1.7976931348623157E+308 (ANSI/IEEE 754-1985 standard) +1.7976931348623157E+308 (ANSI/IEEE 754-1985 standard) approximate numeric floating point : 15

Numeric data types are divided into exact and approximate types. Exact numeric data types (SMALLINT, INT, BIGINT, NUMERIC) are used for numbers whose values must be precise and consistent, such as the numbers used in financial accounting. Note that even when the literal values are equal, approximate numeric data types (FLOAT, DOUBLE) can be interpreted differently depending on the system.

CUBRID does not support the UNSIGNED type for numeric data types.

On the above table, two types on the same cell are identical types but it always prints the above type name when you execute SHOW COLUMNS statement. For example, you can use both SHORT and SMALLINT when you create a table, but it prints "SHORT" when you execute SHOW COLUMNS statement.

Precision and Scale

The precision of numeric data types is defined as the number of significant figures. This applies to both exact and approximate numeric data types.

The scale represents the number of digits following the decimal point. It is significant only in exact numeric data types. Attributes declared as exact numeric data types always have fixed precision and scale. NUMERIC (or DECIMAL) data type always has at least one-digit precision, and the scale should be between 0 and the precision declared. Scale cannot be greater than precision. For INTEGER, SMALLINT, or BIGINT data types, the scale is 0 (i.e. no digits following the decimal point), and the precision is fixed by the system.

Numeric Literals

Special signs can be used to input numeric values. The plus sign (+) and minus sign (-) are used to represent positive and negative numbers respectively. You can also use scientific notations. In addition, you can use currency signs specified in the system to represent currency values. The maximum precision that can be expressed by a numeric literal is 255.

Numeric Coercions

All numeric data type values can be compared with each other. To do this, automatic coercion to the common numeric data type is performed. For explicit coercion, use the CAST operator. When different data types are sorted or calculated in a numerical expression, the system performs automatic coercion. For example, when adding a FLOAT attribute value to an INTEGER attribute value, the system automatically coerces the INTEGER value to the most approximate FLOAT value before it performs the addition operation.

The following is an example to print out the value of FLOAT type when adding the value of INTEGER type to the value of FLOAT type.

CREATE TABLE tbl (a INT, b FLOAT);
INSERT INTO tbl VALUES (10, 5.5);
SELECT a + b FROM tbl;
1.550000e+01

This is an example of overflow error occurred when adding two integer values, the following can be an INTEGER type value for the result.

SELECT 100000000*1000000;
ERROR: Data overflow on data type integer.

In the above case, if you specify one of two integers as the BIGINT type, it will determine the result value into the BIGINT type, and then output the normal result.

SELECT CAST(100000000 AS BIGINT)*1000000;
100000000000000

Warning

Earlier version than CUBRID 2008 R2.0, the input constant value exceeds INTEGER, it is handled as NUMERIC. However, 2008 R2.0 or later versions, it is handled as BIGINT .

INT/INTEGER

The INTEGER data type is used to represent integers. The value range is available is from -2,147,483,648 to +2,147,483,647. SMALLINT is used for small integers, and BIGINT is used for big integers.

  • If a real number is entered for an INT type, the number is rounded to zero decimal place and the integer value is stored.
  • INTEGER and INT are used interchangeably.
  • DEFAULT constraint can be specified in a column of this type.
If you specify 8934 as INTEGER, 8934 is stored.
If you specify 7823467 as INTEGER, 7823467 is stored.
If you specify 89.8 to an INTEGER, 90 is stored (all digits after the decimal point are rounded).
If you specify 3458901122 as INTEGER, an error occurs (if the allowable limit is exceeded).
SHORT/SMALLINT

The SMALLINT data type is used to represent a small integer type. The value range is available is from -32,768 to +32,767.

  • If a real number is entered for an SMALLINT type, the number is rounded to zero decimal place and the integer value is stored.
  • SMALLINT and SHORT are used interchangeably.
  • DEFAULT constraint can be specified in a column of this type.
If you specify 8934 as SMALLINT, 8934 is stored.
If you specify 34.5 as SMALLINT, 35 is stored (all digits after the decimal point are rounded).
If you specify 23467 as SMALLINT, 23467 is stored.
If you specify 89354 as SMALLINT, an error occurs (if the allowable limit is exceeded).
BIGINT

The BIGINT data type is used to represent big integers. The value range is available from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.

  • If a real number is entered for a BIG type, the number is rounded to zero decimal place and the integer value is stored.

  • Based on the precision and the range of representation, the following order is applied.

    SMALLINT ??**INTEGER** ??**BIGINT** ??**NUMERIC**

  • DEFAULT constraint can be specified in a column of this type.

If you specify 8934 as BIGINT, 8934 is stored.
If you specify 89.1 as BIGINT, 89 is stored.
If you specify 89.8 as BIGINT, 90 is stored (all digits after the decimal point are rounded).
If you specify 3458901122 as BIGINT, 3458901122 is stored.
NUMERIC/DECIMAL

NUMERIC or DECIMAL data types are used to represent fixed-point numbers. As an option, the total number of digits (precision) and the number of digits after the decimal point (scale) can be specified for definition. The minimum value for the precision p is 1. When the precision p is omitted, you cannot enter data whose integer part exceeds 15 digits because the default value is 15. If the scale s is omitted, an integer rounded to the first digit after the decimal point is returned because the default value is 0.

NUMERIC [(p[, s])]
  • Precision must be equal to or greater than scale.
  • Precision must be equal to or greater than the number of integer digits + scale.
  • NUMERIC, DECIMAL, and DEC are used interchangeably.
  • To check how the precision and the scale became changed when you operate with NUMERIC typed values, see Arithmetic Operations and Type Casting of Numeric Data Types.
  • DEFAULT constraint can be specified in a column of this type.
If you specify 12345.6789 as NUMERIC, 12346 is stored (it rounds to the first place after the decimal point since 0 is the default value of scale).
If you specify 12345.6789 as NUMERIC(4), an error occurs (precision must be equal to or greater than the number of integer digits).
If you declare NUMERIC(3,4), an error occurs (precision must be equal to or greater than the scale).
If you specify 0.12345678 as NUMERIC(4,4), .1235 is stored (it rounds to the fifth place after the decimal point).
If you specify -0.123456789 as NUMERIC(4,4), -.1235 is stored (it rounds to the fifth place after decimal point and then prefixes a minus (-) sign).
FLOAT/REAL

The FLOAT (or REAL) data type represents floating point numbers.

The ranges of values that can be described as normalized values are from -3.402823466E+38 to -1.175494351E-38, 0, and from +1.175494351E-38 to +3.402823466E+38, whereas the values other than normalized values, which are closer to 0, are described as de-normalized values. It conforms to the ANSI/IEEE 754-1985 standard.

The minimum value for the precision p is 1 and the maximum value is 38. When the precision p is omitted or it is specified as seven or less, it is represented as single precision (in 7 significant figures). If the precision p is greater than 7 and equal to or less than 38, it is represented as double precision (in 15 significant figures) and it is converted into DOUBLE data type.

FLOAT data types must not be used if you want to store a precise value that exceeds the number of significant figures, as they only store the approximate value of any input value over 7 significant figures.

FLOAT[(p)]
  • FLOAT is in 7 significant figures.
  • Extra cautions are required when comparing data because the FLOAT type stores approximate numeric.
  • FLOAT and REAL are used interchangeably.
  • DEFAULT constraint can be specified in a column of this type.
If you specify 16777217 as FLOAT, 16777216 is stored and 1.677722e+07 is displayed (if precision is omitted, 8-th digit is rounded up because it is represented as 7 significant figures).
If you specify 16777217 as FLOAT(5), 16777216 is stored and 1.677722e+07 is displayed (if precision is in seven or less, 8-th digit is rounded up because it is represented as 7 significant figures).
If you specify 16777.217 as FLOAT(5), 16777.216 is stored and 1.677722e+04 is displayed (if precision is in seven or less, 8-th digit is rounded up because it is represented as 7 significant figures).
If you specify 16777.217 as FLOAT(10), 16777.217 is stored and 1.677721700000000e+04 is displayed (if precision is greater than 7 and less than or equal to 38, zeroes are added because it is represented as 15 significant figures).
DOUBLE/DOUBLE PRECISION

The DOUBLE data type is used to represent floating point numbers.

The ranges of values that can be described as normalized values are from -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and from 2.2250738585072014E-308 to 1.7976931348623157E+308, whereas the values other than normalized values, which are closer to 0, are described as de-normalized values. It conforms to the ANSI/IEEE 754-1985 standard.

The precision p is not specified. The data specified as this data type is represented as double precision (in 15 significant figures).

DOUBLE data types must not be used if you want to store a precise value that exceeds the number of significant figures, as they only store the approximate value of any input value over 15 significant figures.

  • DOUBLE is in 15 significant figures.
  • Extra caution is required when comparing data because the DOUBLE type stores approximate numeric.
  • DOUBLE and DOUBLE PRECISION are used interchangeably.
  • DEFAULT constraint can be specified in a column of this type.
If you specify 1234.56789 as DOUBLE, 1234.56789 is stored and 1.234567890000000e+03 is displayed.
If you specify 9007199254740993 as DOUBLE, 9007199254740992 is stored and 9.007199254740992e+15 is displayed.

Note

MONETARY type is deprecated, and it is not recommended anymore.

Date/Time Types

Date/time data types are used to represent the date or time (or both together). CUBRID supports the following data types:

Type bytes Min. Max. Note
DATE 4 0001-01-01 9999-12-31 As an exception, DATE '0000-00-00' format is allowed.
TIME 4 00:00:00 23:59:59  
TIMESTAMP 4 1970-01-01 00:00:01 (GMT) 1970-01-01 09:00:01 (KST) 2038-01-19 03:14:07 (GMT) 2038-01-19 12:14:07 (KST) As an exception, TIMESTAMP '0000-00-00 00:00:00' format is allowed.
DATETIME 8 0001-01-01 00:00:0.000 9999-12-31 23:59:59.999 As an exception, DATETIME '0000-00-00 00:00:00' format is allowed.
TIMESTAMPLTZ 4 Depends on timezone 1970-01-01 00:00:01 (GMT) Depends on timezone 2038-01-19 03:14:07 (GMT) Timestamp with local timezone. As an exception, TIMESTAMPLTZ'0000-00-00 00:00:00' format is allowed.
TIMESTAMPTZ 8 Depends on timezone 1970-01-01 00:00:01 (GMT) Depends on timezone 2038-01-19 03:14:07 (GMT) Timestamp with timezone. As an exception, TIMESTAMPTZ '0000-00-00 00:00:00' format is allowed.
DATETIMELTZ 8 Depends on timezone 0001-01-01 00:00:0.000 UTC Depends on timezone 9999-12-31 23:59:59.999 Datetime with local timezone. As an exception, DATETIMELTZ '0000-00-00 00:00:00' format is allowed.
DATETIMETZ 12 Depends on timezone 0001-01-01 00:00:0.000 UTC Depends on timezone 9999-12-31 23:59:59.999 Datetime with timezone. As an exception, DATETIMETZ '0000-00-00 00:00:00' format is allowed.

Range and Resolution

  • By default, the range of a time value is represented by the 24-hour system. Dates follow the Gregorian calendar. An error occurs if a value that does not meet these two constraints is entered as a date or time.
  • The range of year in DATE is 0001 - 9999 AD.
  • From the CUBRID 2008 R3.0 version, if time value is represented with two-digit numbers, a number from 00 to 69 is converted into a number from 2000 to 2069; a number from 70 to 99 is converted into a number from 1970 to 1999. In earlier than CUBRID 2008 R3.0 version, if time value is represented with two-digit numbers, a number from 01 to 99 is converted into a number from 0001 to 0099.
  • The range of TIMESTAMP is between 1970-01-01 00:00:01 and 2038-01-19 03 03:14:07 (GMT). For KST (GMT+9), values from 1970-01-01 09:00:01 to 2038-01-19 12:14:07 can be stored. timestamp'1970-01-01 00:00:00' (GMT) is the same as timestamp'0000-00-00 00:00:00'.
  • The range of TIMESTAMPLTZ, TIMESTAMPTZ varies with timezone, but the value converted to UTC should be between 1970-01-01 00:00:01 and 2038-01-19 03 03:14:07.
  • The range of DATETIMELTZ, DATETIMETZ varies with timezone, but the value converted to UTC should be between 0001-01-01 00:00:0.000 and 9999-12-31 23:59:59.999. A value stored in database may no longer be valid if session timezone changes.
  • The results of date, time and timestamp operations may depend on the rounding mode. In these cases, for Time and Timestamp, the most approximate second is used as the minimum resolution; for Date, the most approximate date is used as the minimum resolution.

Coercions

The Date / Time types can be cast explicitly using the CAST operator only when they have the same field. For implicit coercion, see Implicit Type Conversion. The following table shows types that allows explicit coercions. For implicit coercion, see Arithmetic Operations and Type Casting of DATE/TIME Data Types.

Explicit Coercions

FROM \ TO DATE TIME DATETIME TIMESTAMP
DATE - X O O
TIME X - X X
DATETIME O O - O
TIMESTAMP O O O -

In general, zero is not allowed in DATE, DATETIME, and TIMESTAMP types. However, if both date and time values are 0, it is allowed as an exception. This is useful in terms that this value can be used if an index exists upon query execution of a column corresponding to the type.

  • Some functions in which the DATE, DATETIME, and TIMESTAMP types are specified as an argument return different value based on the return_null_on_function_errors system parameter if every input argument value for date and time is 0. If return_null_on_function_errors is yes, NULL is returned; if no, an error is returned. The default value is no.
  • The functions that return DATE, DATETIME, and TIMESTAMP types can return a value of 0 for date and time. However, these values cannot be stored in Date objects in Java applications. Therefore, it will be processed with one of the following based on the configuration of zeroDateTimeBehavior, the connection URL property: being handled as an exception, returning NULL, or returning a minimum value (see Configuration Connection).
  • If the intl_date_lang system is configured, input string of TO_DATE(), TO_TIME(), TO_DATETIME(), TO_TIMESTAMP(), DATE_FORMAT(), TIME_FORMAT(), TO_CHAR() and STR_TO_DATE() functions follows the corresponding locale date format. For details, see Statement/Type-Related Parameters and the description of each function.
  • Types with timezone follow the same conversion rules as their parent type.

Note

For literals of date/time types and date/time types with timezone, see Date/Time.

DATE

The DATE data type is used to represent the year (yyyy), month (mm) and day (dd). Supported range is "01/01/0001" to "12/31/9999." The year can be omitted. If it is, the year value of the current system is specified automatically. The specified input/output types are as follows:

date'mm/dd[/yyyy]'
date'[yyyy-]mm-dd'
  • All fields must be entered as integer.
  • The date value is displayed in the type of 'MM/DD/YYYY' in CSQL, and it is displayed in the type of 'YYYY-MM-DD' in JDBC application programs and the CUBRID Manager.
  • The TO_DATE() function is used to convert a character string type into a DATE type.
  • 0 is not allowed to input in year, month, and day; however, '0000-00-00', which every digit consisting of year, month, and day is 0, is allowed as an exception.
  • DEFAULT constraint can be specified in a column of this type.
DATE'2008-10-31' is displayed as '10/31/2008'.
DATE'10/31' is displayed as '10/31/2011'(if a value for year is omitted, the current year is automatically specified).
DATE'00-10-31' is displayed as '10/31/2000'.
DATE'0000-10-31' is displayed as an error (a year value should be at least 1).
DATE'70-10-31' is displayed as '10/31/1970'.
DATE'0070-10-31' is displayed as '10/31/0070'.
TIME

The TIME data type is used to represent the hour (hh), minute (mm) and second (ss). Supported range is "00:00:00" to "23:59:59." Second can be omitted; if it is, 0 seconds is specified. Both 12-hour and 24-hour notations are allowed as an input format. The input format of TIME is as follows:

time'hh:mi[:ss] [am | pm]'
  • All items must be entered as integer.
  • AM/PM time notation is used to display time in the CSQL; while the 24-hour notation is used in the CUBRID Manager.
  • AM/PM can be specified in the 24-hour notation. An error occurs if the time specified does not follow the AM/PM format.
  • Every time value is stored in the 24-hour notation.
  • The TO_TIME() function is used to return a character string type into a TIME type.
  • DEFAULT constraint can be specified in a column of this type.
TIME'00:00:00' is outputted as '12:00:00 AM'.
TIME'1:15' is regarded as '01:15:00 AM'.
TIME'13:15:45' is regarded as '01:15:45 PM'.
TIME'13:15:45 pm' is stored normally.
TIME'13:15:45 am' is an error (an input value does not match the AM/PM format).
TIMESTAMP

The TIMESTAMP data type is used to represent a data value in which the date (year, month, date) and time (hour, minute, second) are combined. The range of representable value is between GMT '1970-01-01 00:00:01' and '2038-01-19 03:14:07'. The DATETIME type can be used if the value is out of range or data in milliseconds is stored. The input format of TIMESTAMP is as follows:

timestamp'hh:mi[:ss] [am|pm] mm/dd[/yyyy]'
timestamp'hh:mi[:ss] [am|pm] [yyyy-]mm-dd'

timestamp'mm/dd[/yyyy] hh:mi[:ss] [am|pm]'
timestamp'[yyyy-]mm-dd hh:mi[:ss] [am|pm]'
  • All fields must be entered in integer format.
  • If the year is omitted, the current year is specified by default. If the time value (hour/minute/second) is omitted, 12:00:00 AM is specified.
  • You can store the timestamp value of the system in the TIMESTAMP type by using the SYS_TIMESTAMP(or SYSTIMESTAMP, CURRENT_TIMESTAMP).
  • The TIMESTAMP() or TO_TIMESTAMP() function is used to cast a character string type into a TIMESTAMP type.
  • 0 is not allowed to input in year, month, and day; however, '0000-00-00 00:00:00', which every digit consisting of year, month, day, hour, minute, and second is 0, is allowed as an exception. GMT timestamp'1970-01-01 12:00:00 AM' or KST timestamp'1970-01-01 09:00:00 AM' is translated into timestamp'0000-00-00 00:00:00'.
  • DEFAULT constraint can be specified in a column of this type.
TIMESTAMP'10/31' is outputted as '12:00:00 AM 10/31/2011' (if the value for year/time is omitted, a default value is outputted ).
TIMESTAMP'10/31/2008' is outputted as '12:00:00 AM 10/31/2008' (if the value for time is omitted, a default value is outputted ).
TIMESTAMP'13:15:45 10/31/2008' is outputted as '01:15:45 PM 10/31/2008'.
TIMESTAMP'01:15:45 PM 2008-10-31' is outputted as '01:15:45 PM 10/31/2008'.
TIMESTAMP'13:15:45 2008-10-31' is outputted as '01:15:45 PM 10/31/2008'.
TIMESTAMP'10/31/2008 01:15:45 PM' is outputted as '01:15:45 PM 10/31/2008'.
TIMESTAMP'10/31/2008 13:15:45' is outputted as '01:15:45 PM 10/31/2008'.
TIMESTAMP'2008-10-31 01:15:45 PM' is outputted as '01:15:45 PM 10/31/2008'.
TIMESTAMP'2008-10-31 13:15:45' is outputted as '01:15:45 PM 10/31/2008'.
An error occurs on TIMESTAMP '2099-10-31 01:15:45 PM' (out of range to represent TIMESTAMP).
DATETIME

The DATETIME data type is used to represent a data value in which the data (year, month, date) and time (hour, minute, second) are combined. The range of representable value is between 0001-01-01 00:00:00.000 and 9999-12-31 23:59:59.999 (GMT). The input format of TIMESTAMP is as follows:

datetime'hh:mi[:ss[.msec]] [am|pm] mm/dd[/yyyy]'
datetime'hh:mi[:ss[.msec]] [am|pm] [yyyy-]mm-dd'
datetime'mm/dd[/yyyy] hh:mi[:ss[.ff]] [am|pm]'
datetime'[yyyy-]mm-dd hh:mi[:ss[.ff]] [am|pm]'
  • All fields must be entered as integer.
  • If you year is omitted, the current year is specified by default. If the value (hour, minute/second) is omitted, 12:00:00.000 AM is specified.
  • You can store the timestamp value of the system in the DATETIME type by using the SYS_DATETIME (or SYSDATETIME, CURRENT_DATETIME, CURRENT_DATETIME(), NOW()) function.
  • The TO_DATETIME() function is used to convert a string type into a DATETIME type.
  • 0 is not allowed to input in year, month, and day; however, '0000-00-00 00:00:00', which every digit consisting of year, month, day, hour, minute, and second is 0, is allowed as an exception.
  • DEFAULT constraint can be specified in a column of this type.
DATETIME'10/31' is outputted as '12:00:00.000 AM 10/31/2011' (if the value for year/time is omitted, a default value is outputted).
DATETIME'10/31/2008' is outputted as '12:00:00.000 AM 10/31/2008'.
DATETIME'13:15:45 10/31/2008' is outputted as '01:15:45.000 PM 10/31/2008'.
DATETIME'01:15:45 PM 2008-10-31' is outputted as '01:15:45.000 PM 10/31/2008'.
DATETIME'13:15:45 2008-10-31' is outputted as '01:15:45.000 PM 10/31/2008'.
DATETIME'10/31/2008 01:15:45 PM' is outputted as '01:15:45.000 PM 10/31/2008'.
DATETIME'10/31/2008 13:15:45' is outputted as '01:15:45.000 PM 10/31/2008'.
DATETIME'2008-10-31 01:15:45 PM' is outputted as '01:15:45.000 PM 10/31/2008'.
DATETIME'2008-10-31 13:15:45' is outputted as '01:15:45.000 PM 10/31/2008'.
DATETIME'2099-10-31 01:15:45 PM' is outputted as '01:15:45.000 PM 10/31/2099'.
CASTing a String to Date/Time Type
Available Format for Strings in Date/Time Type

CAST() function allows the below format for date/time strings.

Available DATE String Format

[year sep] month sep day
  • 2011-04-20: April 20th, 2011
  • 04-20: April 20th of this year

If a separator (sep) is a slash (/), strings are recognized in the following order:

month/day[/year]
  • 04/20/2011: April 20th, 2011
  • 04/20: April 20th of this year

If you do not use a separator (sep), strings are recognized in the following format. It is allowed to use 1, 2, and 4 digits for years and 1 and 2 digits for months. For day, you should always enter 2 digits.

YYYYMMDD
YYMMDD
YMMDD
MMDD
MDD
  • 20110420: April 20th, 2011
  • 110420: April 20th, 2011
  • 420: April 20th of this year

Available TIME String Format

[hour]:min[:[sec]][.[msec]] [am|pm]
  • 09:10:15.359 am: 9 hours 10 minutes 15 seconds AM (0.359 seconds will be truncated)
  • 09:10:15: 9 hours 10 minutes 15 seconds AM
  • 09:10: 9 hours 10 minutes AM
  • :10: 12 hours 10 minutes AM
[[[[[[Y]Y]Y]Y]M]MDD]HHMISS[.[msec]] [am|pm]
  • 20110420091015.359 am: 9 hours 10 minutes 15 seconds AM
  • 0420091015: 9 hours 10 minutes 15 seconds AM
[H]HMMSS[.[msec]] [am|pm]
  • 091015.359 am: 9 hours 10 minutes 15 seconds AM
  • 91015: 9 hours 10 minutes 15 seconds AM
[M]MSS[.[msec]] [am|pm]
  • 1015.359 am: 12 hours 10 minutes 15 seconds AM
  • 1015: 12 hours 10 minutes 15 seconds AM
[S]S[.[msec]] [am|pm]
  • 15.359 am: 12 hours 15 seconds AM
  • 15: 12 hours 15 seconds AM

Note

: The [H]H format was allowed in CUBRID 2008 R3.1 and the earlier versions. That is, the string '10' was converted to TIME '10:00:00' in the R3.1 and the earlier versions, and will be converted to TIME '00:00:10' in version R4.0 and later.

Available DATETIME String Format

[year sep] month sep day [sep] [sep] hour [sep min[sep sec[.[msec]]]]
  • 04-20 09: April 20th of this year, 9 hours AM
month/day[/year] [sep] hour [sep min [sep sec[.[msec]]]]
  • 04/20 09: April 20th of this year, 9 hours AM
year sep month sep day sep hour [sep min[sep sec[.[msec]]]]
  • 2011-04-20 09: April 20th, 2011, 9 hours AM
month/day/year sep hour [sep min[sep sec [.[msec]]]]
  • 04/20/2011 09: April 20th, 2011, 9 hours AM
YYMMDDH (It is allowed only when time format is one digit.)
  • 1104209: April 20th, 2011, 9 hours AM
YYMMDDHHMI[SS[.msec]]
  • 1104200910.359: April 20th, 2011, 9 hours 10 minutes AM (0.359 seconds will be truncated)
  • 110420091000.359: April 20th, 2011, 9 hours 10 minutes 0.359 seconds AM
YYYYMMDDHHMISS[.msec]
  • 201104200910.359: November 4th, 2020 8 hours 9 minutes 10.359 seconds PM
  • 20110420091000.359: April 20th, 2011, 9 hours 10 minutes 0.359 seconds AM

Available Time-Date String Format

[hour]:min[:sec[.msec]] [am|pm] [year-]month-day
  • 09:10:15.359 am 2011-04-20: April 20th, 2011, 9 hours 10 minutes 15.359 seconds AM
  • :10 04-20: April 20th of this year, 12 hours 10 minutes AM
[hour]:min[:sec[.msec]] [am|pm] month/day[/[year]]
  • 09:10:15.359 am 04/20/2011: April 20th, 2011, 9 hours 10 minutes 15.359 seconds AM
  • :10 04/20: April 20th of this year, 12 hours 10 minutes AM
hour[:min[:sec[.[msec]]]] [am|pm] [year-]month-day
  • 09:10:15.359 am 04-20: April 20th of this year, 9 hours 10 minutes 15.359 seconds AM
  • 09 04-20: April 20th of this year, 9 hours AM
hour[:min[:sec[.[msec]]]] [am|pm] month/day[/[year]]
  • 09:10:15.359 am 04/20: April 20th of this year, 9 hours 10 minutes, 15.359 seconds AM
  • 09 04/20: April 20th of this year, 9 hours AM

Rules

msec is a series of numbers representing milliseconds. The numbers after the fourth digit will be ignored. The rules for the separator string are as follows:

  • You should always use one colon (:) as a separator for the TIME separator.
  • DATE and DATETIME strings can be represented as a series of numbers without the separator sep), and non-alphanumeric characters can be used as separators. The DATETIME string can be divided into Time and Date with a space.
  • Separators should be identical in the input string.
  • For the Time-Date string, you can only use colon (:) for a Time separator and hyphen (-) or slash (/) for a Date separator. If you use a hyphen when entering date, you should enter like yyyy-mm-dd; in case of a slash, enter like mm/dd/yyyy.

The following rules will be applied in the part of date.

  • You can omit the year as long as the syntax allows it.
  • If you enter the year as two digits, it represents the range from 1970-2069. That is, if YY<70, it is treated as 2000+YY; if YY>=70, it is treated as 1900+YY. If you enter one, three or four digit numbers for the year, the numbers will be represented as they are.
  • A space before and after a string and the string next to the space are ignored. The am/pm identifier for the DATETIME and TIME strings can be recognized as part of TIME value, but are not recognized as the am/pm identifier if non-space characters are added to it.

The TIMESTAMP type of CUBRID consists of DATE type and TIME type, and DATETIME type consists of DATE type and TIME type with milliseconds being added to them. Input strings can include Date (DATE string), Time (TIME string), or both (DATETIME strings). You can convert a string including a specific type of data to another type, and the following rules will be applied for the conversion.

  • If you convert the DATE string to the DATETIME type, the time value will be '00:00:00.'
  • If you convert the TIME string to the DATETIME type, colon (:) is recognized as a date separator, so that the TIME string can be recognized as a date string and the time value will be '00:00:00.'
  • If you convert the DATETIME string to the DATE type, the time part will be ignored from the result but the time input value format should be valid.
  • You can covert the DATETIME string to the TIME type, and you must follow the following rules.
    • The date and time in the string must be divided by at least one blank.
    • The date part of the result value is ignored but the date input value format should be valid.
    • The year in the date part must be over 4 digits (available to start with 0) or the time part must include hours and minutes ([H]H:[M]M) at least. Otherwise the date pate are recognized as the TIME type of the [MM]SS format, and the following string will be ignored.
  • If the one of the units (year, month, date, hour, minute and second) of the DATETIME string is greater than 999999, it is not recognized as a number, so the string including the corresponding unit will be ignored. For example, in '2009-10-21 20:9943:10', an error occurs because the value in minutes is out of the range. However, if '2009-10-21 20:1000123:10' is entered,'2009' is recognized as the TIME type of the MMSS format, so that TIME '00:20:09' will be returned.
  • If you convert the time-date sting to the TIME type, the date part of the string is ignored but the date part format must be valid.
  • All input strings including the time part allow [.msec] on conversion, but only the DATETIME type can be maintained. If you convert this to a type such as DATE, TIMESTAMP or TIME, the msec value is discarded.
  • All conversions in the DATETIME, TIME string allow English locale following after time value or am/pm specifier written in the current locale of a server.
SELECT CAST('420' AS DATE);
   cast('420' as date)
======================
  04/20/2012
SELECT CAST('91015' AS TIME);
   cast('91015' as time)
========================
  09:10:15 AM
SELECT CAST('110420091035.359' AS DATETIME);
   cast('110420091035.359' as datetime)
=======================================
  09:10:35.359 AM 04/20/2011
SELECT CAST('110420091035.359' AS TIMESTAMP);
   cast('110420091035.359' as timestamp)
========================================
  09:10:35 AM 04/20/2011
Date/Time Types with Timezone

Date/Time types with timezone are date/time types which can be input or output by specifying timezone. There are two ways of specifying timezone; specifying the name of local zone and specifying the offset of time.

Timezone information are considered in the Date/Time types if TZ or LTZ is followed after the existing Date/Time types; TZ means timezone, and LTZ means local timezone.

  • TZ type can be represented as <date/time type> WITH TIME ZONE. This stores UTC time and timezone information (decided by a user or session timezone) when this is created. TZ type requires 4 bytes more to store timezone information.
  • LTZ type can be represented as <date/time type> WITH LOCAL TIME ZONE. This stores UTC time internally; when this value is output, this is converted as a value of a local (current session) time zone.

This table describes date/time types to compare date/time types with timezone together.

UTC in the table means Coordinated Universal Time.

Category Type Input Store Output Description
DATE DATE Without timezone Input value Absolute (the same as input) Date
DATETIME DATETIME Without timezone Input value Absolute (the same as input) Date/time including milliseconds
DATETIMETZ With timezone UTC + timezone(region or offset) Absolute (keep input timezone) Date/time + timezone
DATETIMELTZ With timezone UTC Relative (transformed by session timezone) Date/time in the session timezone
TIME TIME Without timezone Input value Absolute (the same as input) Time
TIMESTAMP TIMESTAMP Without timezone UTC Relative (transformed by session timezone) Input value is translated as a session timezone's value.
TIMESTAMPTZ With timezone UTC + timezone(region or offset) Absolute (keep input timezone) UTC + timestamp with timezone
TIMESTAMPLTZ With timezone UTC Relative (transformed by session timezone) Session timezone. Same as TIMESTAMP's value, but timezone specifier is output when this is printed out.

The other features of date/time types with timezone (e.g. maximum/minimum value, range, resolution) are the same with the features of general date/time types.

Note

  • On CUBRID, TIMESTAMP is stored as second unit, after Jan. 1, 1970 UTC (UNIX epoch).
  • Some DBMS's TIMESTAMP is similar to CUBRID's DATETIME as the respect of saving milliseconds.

To see examples of functions using timezone types, see Date/Time Functions and Operators.

The following shows that the output values are different among DATETIME, DATETIMETZ and DATETIMELTZ when session timezone is changed.

--  csql> ;set timezone="+09"

CREATE TABLE tbl (a DATETIME, b DATETIMETZ,  c DATETIMELTZ);
INSERT INTO tbl VALUES (datetime'2015-02-24 12:30', datetimetz'2015-02-24 12:30', datetimeltz'2015-02-24 12:30');

SELECT * FROM tbl;
12:30:00.000 PM 02/24/2015     12:30:00.000 PM 02/24/2015 +09:00                12:30:00.000 PM 02/24/2015 +09:00
-- csql> ;set timezone="+07"

SELECT * FROM tbl;
12:30:00.000 PM 02/24/2015     12:30:00.000 PM 02/24/2015 +09:00                10:30:00.000 AM 02/24/2015 +07:00

The following shows that the output values are different among TIMESTAMP, TIMESTAMPTZ and TIMESTAMPLTZ when session timezone is changed.

-- ;set timezone="+09"

CREATE TABLE tbl (a TIMESTAMP, b TIMESTAMPTZ,  c TIMESTAMPLTZ);
INSERT INTO tbl VALUES (timestamp'2015-02-24 12:30', timestamptz'2015-02-24 12:30', timestampltz'2015-02-24 12:30');

SELECT * FROM tbl;
12:30:00 PM 02/24/2015     12:30:00 PM 02/24/2015 +09:00                12:30:00 PM 02/24/2015 +09:00
-- csql> ;set timezone="+07"

SELECT * FROM tbl;
10:30:00 AM 02/24/2015     12:30:00 PM 02/24/2015 +09:00                10:30:00 AM 02/24/2015 +07:00

Conversion from string to timestamp types

Conversion from string to timestamp/timestampltz/timestamptz are performed in context for creating timestamp objects from literals.

From/to Timestamp Timestampltz Timestamptz
String (without timezone) Interpret the date/time parts in session timezone. Convert to UTC, encode and store the Unix epoch. Interpret the date/time parts in session timezone. Convert to UTC, encode and store the Unix epoch. Interpret the date/time parts in session timezone. Convert to UTC, encode and store the Unix epoch and TZ_ID of session
String (with timezone) Error (timezone part is not supported for timestamp). Convert from value's timezone to UTC. Encode and store the Unix epoch. Convert from value's timezone to UTC. Encode and store the Unix epoch and TZ_ID of value's timezone.

Conversion from string to datetime types

Conversion from string to datetime/datetimeltz/datetimetz are performed in context for creating datetime objects from literals.

From/to Datetime Datetimeltz Datetimetz
String (without timezone) Store the parsed values from string. Interpret the date/time parts in session timezone. Convert to UTC and store the new values. Interpret the date/time parts in session timezone. Convert to UTC and store the new values and TZ_ID of session
String (with timezone) Error (timezone part is not supported for datetime). Convert from value's timezone to UTC. Store the new values in UTC reference. Convert from value's timezone to UTC. Store the new values in UTC reference TZ_ID of string's timezone.

Conversion of datetime and timestamp types to string (printing of values)

From/to String (timezone printing not allowed) String (timezone force print) String (no requirement for timezone - free choice)
TIMESTAMP Decode Unix epoch to session timezone and print Decode Unix epoch to session timezone and print with session timezone. Decode Unix epoch to session timezone and print. Do not print timezone string
TIMESTAMPLTZ Decode Unix epoch to session timezone and print Decode Unix epoch to session timezone and print with session timezone. Decode Unix epoch to session timezone and print. Print session timezone.
TIMESTAMPTZ Decode Unix epoch to timezone from value and print it. Decode Unix epoch to timezone from value and print it; print timezone from value. Decode Unix epoch to timezone from value and print it; print timezone from value.
DATETIME Print the stored values. Print the stored value and session timezone. Print the stored value. Do not print any timezone.
DATETIMELTZ Convert from UTC to session timezone and print the new value. Convert from UTC to session timezone and print it. Print session timezone Convert from UTC to session timezone and print it. Print session timezone.
DATETIMELTZ Convert from UTC to value's timezone and print the new value. Convert from UTC to value's timezone and print it. Print value's timezone Convert from UTC to value's timezone and print it. Print value's timezone.
Timezone Configuration

The below shows the timezone related parameters configured in cubrid.conf. For parameter's configuration, see cubrid.conf Configuration File and Default Parameters.

  • timezone

    Specifies a timezone for a session. The default is a value of server_timezone.

  • server_timezone

    Specifies a timezone for a server. The default is a timezone of OS.

  • tz_leap_second_support

    Sets for support for leap second as yes or no. The default is no.

Timezone Function

The following are timezone related functions. For each function's detail usage, click each function's name.

Functions with a Timezone Type

All functions which use DATETIME, TIMESTAMP or TIME typed value in their input value, can use timezone typed value.

The below is an example of using timezone typed values, it works the same as the case without timezone. Exceptionally, if the type name ends with LTZ, the output value of this type follows the local timezone's setting (timezone parameter).

On the below example, the default unit of a number is millisecond, which is the minimum unit of DATETIME type.

SELECT datetimeltz '09/01/2009 03:30:30 pm' + 1;
03:30:30.001 PM 09/01/2009 Asia/Seoul
SELECT datetimeltz '09/01/2009 03:30:30 pm' - 1;
03:30:29.999 PM 09/01/2009 Asia/Seoul

On the below example, the default unit of a number is second, which is the minimum unit of TIMESTAMP type.

SELECT timestamptz '09/01/2009 03:30:30 pm' + 1;
03:30:31 PM 09/01/2009 Asia/Seoul
SELECT timestamptz '09/01/2009 03:30:30 pm' - 1;
03:30:29 PM 09/01/2009 Asia/Seoul
SELECT EXTRACT (hour from datetimetz'10/15/1986 5:45:15.135 am Europe/Bucharest');

5

A type which the name ends with LTZ follows the setting of local timezone. Therefore, if the value of timezone parameter is set to 'Asia/Seoul', EXTRACT function returns hour value of this timezone.

-- csql> ;set timezone='Asia/Seoul'

SELECT EXTRACT (hour from datetimeltz'10/15/1986 5:45:15.135 am Europe/Bucharest');
12
Conversion Functions for Timezone Types

The following are functions converting a string to a date/time typed value, or date/time typed value to a string; The value can include an information like an offset, a zone and a daylight saving.

For each function's usage, see the each function's explanation by clicking the function name.

SELECT DATE_FORMAT (datetimetz'2012-02-02 10:10:10 Europe/Zurich CET', '%TZR %TZD %TZH %TZM');
SELECT STR_TO_DATE ('2001-10-11 02:03:04 AM Europe/Bucharest EEST', '%Y-%m-%d %h:%i:%s %p %TZR %TZD');
SELECT TO_CHAR (datetimetz'2001-10-11 02:03:04 AM Europe/Bucharest EEST');
SELECT TO_DATETIME_TZ ('2001-10-11 02:03:04 AM Europe/Bucharest EEST');
SELECT TO_TIMESTAMP_TZ ('2001-10-11 02:03:04 AM Europe/Bucharest');

Note

TO_TIMESTAMP_TZ() and TO_DATETIME_TZ() functions do the same behaviours with TO_TIMESTAMP() and TO_DATETIME() functions except that they can have TZR, TZD, TZH and TZM information in their date/time argument.

CUBRID uses the region name of timezone in the IANA(Internet Assigned Numbers Authority) timezone database region; for IANA timezone, see http://www.iana.org/time-zones.

IANA Timezone

In IANA(Internet Assigned Numbers Authority) timezone database, there are lots of codes and data which represent the history of localtime for many representative locations around the globe.

This database is periodically updated to reflect changes made by political bodies to time zone boundaries, UTC offsets, and daylight-saving rules. Its management procedure is described in BCP 175: Procedures for Maintaining the Time Zone Database. For more details, see http://www.iana.org/time-zones.

CUBRID supports IANA timezone, and a user can use the IANA timezone library in the CUBRID installation package as it is. If you want to update as the recent timezone, update timezone first, compile timezone library, and restart the database.

Regarding this, see Compiling Timezone Library.

Bit Strings

A bit string is a sequence of bits (1's and 0's). Images (bitmaps) displayed on the computer screen can be stored as bit strings. CUBRID supports the following two types of bit strings:

  • Fixed-length bit string (BIT)
  • Variable-length bit string (BIT VARYING)

A bit string can be used as a method argument or an attribute type. Bit string literals are represented in a binary or hexadecimal format. For binary format, append the string consisting of 0's and 1's to the letter B or append a value to the 0b as shown example below.

B'1010'
0b1010

For hexadecimal format, append the string consisting of the numbers 0 - 9 and the letters A - F to the uppercase letter X or append a value to the 0x . The following is hexadecimal representation of the same number that was represented above in binary format.

X'a'
0xA

The letters used in hexadecimal numbers are not case-sensitive. That is, X'4f' and X'4F' are considered as the same value.

Length

If a bit string is used in table attributes or method declarations, you must specify the maximum length. The maximum length for a bit string is 1,073,741,823 bits.

Bit String Coercion

Automatic coercion is performed between a fixed-length and a variable-length bit string for comparison. For explicit coercion, use the CAST() operator.
BIT(n)

Fixed-length binary or hexadecimal bit strings are represented as BIT (n), where n is the maximum number of bits. If n is not specified, the length is set to 1. If n is not specified, the length is set to 1. The bit string is filled with 8-bit unit from the left side. For example, the value of B'1' is the same as the value of B'10000000'. Therefore, it is recommended to declare a length by 8-bit unit, and input a value by 8-bit unit.

Note

If you input B'1' to the BIT(4) column, it is printed out X'8' on CSQL, X'80' on CUBRID Manager, Query Browser or application program.

  • n must be a number greater than 0.
  • If the length of the string exceeds n, it is truncated and filled with 0s.
  • If a bit string smaller than n is stored, the remainder of the string is filled with 0s.
  • DEFAULT constraint can be specified in a column of this type.
CREATE TABLE bit_tbl(a1 BIT, a2 BIT(1), a3 BIT(8), a4 BIT VARYING);
INSERT INTO bit_tbl VALUES (B'1', B'1', B'1', B'1');
INSERT INTO bit_tbl VALUES (0b1, 0b1, 0b1, 0b1);
INSERT INTO bit_tbl(a3,a4) VALUES (B'1010', B'1010');
INSERT INTO bit_tbl(a3,a4) VALUES (0xaa, 0xaa);
SELECT * FROM bit_tbl;
  a1                    a2                    a3                    a4

=========================================================================
  X'8'                  X'8'                  X'80'                 X'8'
  X'8'                  X'8'                  X'80'                 X'8'
  NULL                  NULL                  X'a0'                 X'a'
  NULL                  NULL                  X'aa'                 X'aa'
BIT VARYING(n)

A variable-length bit string is represented as BIT VARYING (n), where n is the maximum number of bits. If n is not specified, the length is set to 1,073,741,823 (maximum value). n is the maximum number of bits. If n is not specified, the maximum length is set to 1,073,741,823. The bit string is filled with 8-bit values from the left side. For example, the value of B'1' is the same as the value of B'10000000'. Therefore, it is recommended to declare a length by 8-bit unit, and input a value by 8-bit unit.

Note

If you input B'1' to the BIT VARYING(4) column, it is printed out X'8' on CSQL, X'80' on CUBRID Manager, Query Browser or application program.

  • If the length of the string exceeds n, it is truncated and filled with 0s.
  • The remainder of the string is not filled with 0s even if a bit string smaller than n is stored.
  • n must be a number greater than 0.
  • DEFAULT constraint can be specified in a column of this type.
CREATE TABLE bitvar_tbl(a1 BIT VARYING, a2 BIT VARYING(8));
INSERT INTO bitvar_tbl VALUES (B'1', B'1');
INSERT INTO bitvar_tbl VALUES (0b1010, 0b1010);
INSERT INTO bitvar_tbl VALUES (0xaa, 0xaa);
INSERT INTO bitvar_tbl(a1) VALUES (0xaaa);
SELECT * FROM bitvar_tbl;
  a1                    a2
============================================
  X'8'                  X'8'
  X'a'                  X'a'
  X'aa'                 X'aa'
  X'aaa'                NULL
INSERT INTO bitvar_tbl(a2) VALUES (0xaaa);
ERROR: Data overflow coercing X'aaa' to type bit varying.
Character Strings

CUBRID supports the following two types of character strings:

  • Fixed-length character string: CHAR (n)
  • Variable-length character string: VARCHAR (n)

Note

From CUBRID 9.0 version, NCHAR and NCHAR VARYING is no more supported. Instead, please use CHAR and VARCHAR.

The following are the rules that are applied when using the character string types.

  • In general, single quotations are used to enclose character string. Double quotations may be used as well depending on the value of ansi_quotes, which is a parameter related to SQL statement. If the ansi_quotes value is set to no, character string enclosed by double quotations is handled as character string, not as an identifier. The default value is yes. For details, Statement/Type-Related Parameters.

  • If there are characters that can be considered to be blank (e.g. spaces, tabs, or line breaks) between two character strings, these two character strings are treated as one according to ANSI standard. For example, the following example shows that a line break exists between two character strings.

    'abc'
    'def'
    

    The above two strings and the below string are considered identical.

    'abcdef'
    
  • If you want to include a single quote as part of a character string, enter two single quotes in a row. For example, the character string on the left is stored as the one on the right.

    '''abcde''fghij'       'abcde'fghij
    
  • The maximum size of the token for all the character strings is 16 KB.

  • To enter the language of a specific country, we recommend that you to specify the locale when creating DB, then you can change locale by the introducer CHARSET (or COLLATE modifier). For more information, see An Overview of Globalization.

Length

Specify the number of a character string.

When the length of the character string entered exceeds the length specified, the excess characters are truncated.

For a fixed-length character string type such as CHAR, the length is fixed at the declared length. Therefore, the right part (trailing space) of the character string is filled with space characters when the string is stored. For a variable-length character string type such as VARCHAR, only the entered character string is stored, and the space is not filled with space characters.

The maximum length of a CHAR or VARCHAR type to be specified is 1,073,741,823.

Also, the maximum length that can be input or output in a CSQL statement is 8,192 KB.

Note

In the CUBRID version less than 9.0, the length of CHAR or VARCHAR was not the number of characters, but the byte size.

Character Set, charset

A character set (charset) is a set in which rules are defined that relate to what kind of codes can be used for encoding when specified characters (symbols) are stored in the computer. The character used by CUBRID can be configured as the CUBRID_CHARSET environment variable. For details, see An Overview of Globalization.

Collating Character Sets

A collation is a set of rules used for comparing characters to search or sort values stored in the database when a certain character set is specified. For details, see An Overview of Globalization.

Character String Coercion

Automatic coercion takes place between a fixed-length and a variable-length character string for the comparison of two characters, applicable only to characters that belong to the same character set.

For example, when you extract a column value from a CHAR (5) data type and insert it into a column with a CHAR (10) data type, the data type is automatically coerced to CHAR (10). If you want to coerce a character string explicitly, use the CAST operator (See CAST()).

CHAR(n)

A fixed-length character string is represented as CHAR (n), in which n represents the number of characters. If n is not specified, the value is specified as 1, default value.

When the length of a character string exceeds n, they are truncated. When character string which is shorter than n is stored, whitespace characters are used to fill up the trailing space.

CHAR (n) and CHARACTER (n) are used interchangeably.

Note

In the earlier versions of CUBRID 9.0, n represents bite length, not the number of characters.

  • n is an integer between 1 and 1,073,741,823 (1G).
  • Empty quotes (' ') are used to represent a blank string. In this case, the return value of the LENGTH function is not 0, but is the fixed length defined in CHAR (n). That is, if you enter a blank string into a column with CHAR (10), the LENGTH is 10; if you enter a blank value into a CHAR with no length specified, the LENGTH is the default value 1.
  • Space characters used as filling characters are considered to be smaller than any other characters, including special characters.
If you specify 'pacesetter' as CHAR(12), 'pacesetter ' is stored (a 10-character string plus two whitespace characters).
If you specify 'pacesetter ' as CHAR(10), 'pacesetter' is stored (a 10-character string; two whitespace characters are truncated).
If you specify 'pacesetter' as CHAR(4), 'pace' is stored (truncated as the length of the character string is greater than 4).
If you specify 'p ' as CHAR, 'p' is stored (if n is not specified, the length is set to the default value 1).
  • DEFAULT constraint can be specified in a column of this type.
VARCHAR(n)/CHAR VARYING(n)

Variable-length character strings are represented as VARCHAR (n), where n represents the number of characters. If n is not specified, the value is specified as 1,073,741,823, the maximum length.

When the length of a character string exceeds n, they are truncated. When character string which is shorter than n is stored, whitespace characters are used to fill up the trailing space for VARCHAR (n), the length of string used are stored.

VARCHAR (n), CHARACTER, VARYING (n), and CHAR VARYING (n) are used interchangeably.

Note

In the earlier versions of CUBRID 9.0, n represents bite length, not the number of characters.

  • STRING is the same as the VARCHAR (maximum length).
  • n is an integer between 1 and 1,073,741,823 (1G).
  • Empty quotes (' ') are used to represent a blank string. In this case, the return value of the LENGTH function is not 0.
If you specify 'pacesetter' as CHAR(4), 'pace' is stored (truncated as the length of the character string is greater than 4).
If you specify 'pacesetter' as VARCHAR(12), 'pacesetter' is stored (a 10-character string).
If you specify 'pacesetter ' as VARCHAR(12), 'pacesetter ' is stored (a 10-character string plus two whitespace characters).
If you specify 'pacesetter ' as VARCHAR(10), 'pacesetter' is stored (a 10-character string; two whitespace characters are truncated).
If you specify 'p ' as VARCHAR, 'p' is stored (if n is not specified, the default value 1,073,741,823 is used, and the trailing space is not filled with whitespace characters).
  • DEFAULT constraint can be specified in a column of this type.
STRING

STRING is a variable-length character string data type. STRING is the same as the VARCHAR with the length specified as the maximum value. That is, STRING and VARCHAR (1,073,741,823) have the same value.

Escape Special Characters

CUBRID supports two kinds of methods to escape special characters. One is using quotes and the other is using backslash (\).

  • Escape with Quotes

    If you set no for the system parameter ansi_quotes in the cubrid.conf file, you can use both double quotes (") and singe quotes (') to wrap strings. The default value for the ansi_quotes parameter is yes, and you can use only single quotes to wrap the string.

    • You should use two single quotes ('') for the single quotes included in the strings wrapped in single quotes.
    • You should use two double quotes ("") for the double quotes included in the strings wrapped in double quotes. (when ansi_quotes = no)
    • You don't need to escape the single quotes included in the string wrapped in double quotes. (when ansi_quotes = no)
    • You don't need to escape the double quotes included in the string wrapped in single quotes.
  • Escape with Backslash

    You can use escape using backslash (\) only if you set no for the system parameter no_backslash_escapes in the cubrid.conf file. The default value for the no_backslash_escapes parameter is yes. If the value of no_backslash_escapes is no, the following are the special characters.

    • \' : Single quotes (')
    • \" : Double quotes (")
    • \n : Newline, linefeed character
    • \r : Carriage return character
    • \t : Tab character
    • \\ : Backslash
    • \% : Percent sign (%). For details, see the following description.
    • \_ : Underbar (_). For details, see the following description.

    For all other escapes, the backslash will be ignored. For example, "x" is the same as entering only "x".

    \% and \_ are used in the pattern matching syntax such as LIKE to search percent signs and underbars and are used as a wildcard character if there is no backslash. Outside of the pattern matching syntax, "\%"and "\_" are recognized as normal strings not wildcard characters. For details, see LIKE.

The following is the result of executing Escape if a value for the system parameter ansi_quotes in the cubrid.conf file is yes(default), and a value for no_backslash_escapes is no.

-- ansi_quotes=yes, no_backslash_escapes=no
SELECT STRCMP('single quotes test('')', 'single quotes test(\')');

If you run the above query, backslash is regarded as an escape character. Therefore, above two strings are the same.

   strcmp('single quotes test('')', 'single quotes test('')')
=============================================================
                                                            0
SELECT STRCMP('\a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z', 'a\bcdefghijklm\nopq\rs\tuvwxyz');

If you run the above query, backslash is regarded as an escape character. Therefore, above two strings are the same.

   strcmp('abcdefghijklm
s       uvwxyz', 'abcdefghijklm
s       uvwxyz')
=====================================================================
                                                                    0
SELECT LENGTH('\\');

If you run the above query, backslash is regarded as an escape character. Therefore, the length of above string is 1.

   char_length('\')
===================
                  1

The following is the result of executing Escape if a value for the system parameter ansi_quotes in the cubrid.conf file is yes(default), and a value for no_backslash_escapes is yes(default). Backslash character is regarded as a general character.

-- ansi_quotes=yes, no_backslash_escapes=yes

SELECT STRCMP('single quotes test('')', 'single quotes test(\')');

If you run the above query, the quotation mark is regarded as opened, so the below error occurs. If you input this query on the CSQL interpreter's console, it waits the next quotation mark's input.

ERROR: syntax error, unexpected UNTERMINATED_STRING, expecting SELECT or VALUE or VALUES or '('
SELECT STRCMP('\a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z', 'a\bcdefghijklm\nopq\rs\tuvwxyz');

If you run the above query, backslash is regarded as a general character. Therefore, the result of the comparison between the above two strings shows different.

   strcmp('\a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z', 'a\bcdefghijklm\nopq\rs\tuvwxyz')
===================================================================================================
                                                                                                 -1
SELECT LENGTH('\\');

If you run the above query, backslash is regarded as a general character. Therefore, the length of above string is 2.

   char_length('\\')
====================
                   2

The following shows the result of executing Escape about the LIKE clause when ansi_quotes is yes and no_backslash_escapes is no.

-- ansi_quotes=yes, no_backslash_escapes=no

CREATE TABLE t1 (a VARCHAR(200));
INSERT INTO t1 VALUES ('aaabbb'), ('aaa%');

SELECT a FROM t1 WHERE a LIKE 'aaa\%' ESCAPE '\\';
  a
======================
  'aaa%'

If you run above query, it returns only one row because '%' character is regarded as a general character.

In the string of LIKE clause, backslash is always regarded as a general character. Therefore, if you want to make the '%' character as a general character, not as an pattern matching character, you should specify that '%' is an escape character by using ESCAPE clause. In the ESCAPE clause, backslash is regarded as an escape character. Therefore, we used two backslashes.

If you want use other character than a backslash as an escape character, you can write the query as follows.

SELECT a FROM t1 WHERE a LIKE 'aaa#%' ESCAPE '#';
ENUM Data Type

The ENUM type is a data type consisting of an ordered set of distinct constant char literals called enum values. The syntax for creating an enum column is:

<enum_type>
    : ENUM '(' <char_string_literal_list> ')'

<char_string_literal_list>
    : <char_string_literal_list> ',' CHAR_STRING
    | CHAR_STRING

The following example shows the definition of an ENUM column.

CREATE TABLE tbl (
    color ENUM ('red', 'yellow', 'blue', 'green')
);
  • DEFAULT constraint can be specified in a column of this type.

An index is associated to each element of the enum set, according to the order in which elements are defined in the enum type. For example, the color column can have one of the following values (assuming that the column allows NULL values) :

Value Index Number
NULL NULL
'red' 1
'yellow' 2
'blue' 3
'green' 4

The set of values of an ENUM type must not exceed 512 elements and each element of the set must be unique. CUBRID allocates two bytes of storage for each ENUM type value because it only stores the index of each value. This reduces the storage space needed which may improve performance.

Either the enum value or the value index can be used when working with ENUM types. For example, to insert values into an ENUM type column, users can use either the value or the index of the ENUM type:

-- insert enum element 'yellow' with index 2
INSERT INTO tbl (color) VALUES ('yellow');
-- insert enum element 'red' with index 1
INSERT INTO tbl (color) VALUES (1);

When used in expressions, the ENUM type behaves either as a CHAR type or as a number, depending on the context in which it is used:

-- the first result column has ENUM type, the second has INTEGER type and the third has VARCHAR type
SELECT color, color + 0, CONCAT(color, '') FROM tbl;
  color                     color+0   concat(color, '')
=========================================================
  'yellow'                        2  'yellow'
  'red'                           1  'red'

When used in type contexts other than CHAR or numbers, the enum is coerced to that type using either the index or the enum value. The table below shows which part of an ENUM type is used in the coercion:

Type Enum type (Index/Value)
SHORT Index
INTEGER Index
BIGINT Index
FLOAT Index
DOUBLE Index
NUMERIC Index
TIME Value
DATE Value
DATETIME Value
TIMESTAMP Value
CHAR Value
VARCHAR Value
BIT Value
VARBIT Value
ENUM Type Comparisons

When used in = or IN predicates of the form (<enum_column> <operator> <constant>), CUBRID tries to convert the constant to the ENUM type. If the coercion fails, CUBRID does not return an error but considers the comparison to be false. This is implemented like this in order to allow index scan plans to be generated on these two operators.

For all other comparison operators, the ENUM type is converted to the type of the other operand. If a comparison is performed on two ENUM types, both arguments are converted to CHAR type and the comparison follows CHAR type rules. Except for = and IN, predicates on ENUM columns cannot be used in index scan plans.

To understand these rules, consider the following table:

CREATE TABLE tbl (
    color ENUM ('red', 'yellow', 'blue', 'green')
);

INSERT INTO tbl (color) VALUES (1), (2), (3), (4);

The following query will convert the constant 'red' to the enum value 'red' with index 1

SELECT color FROM tbl WHERE color = 'red';
  color
======================
  'red'
SELECT color FROM tbl WHERE color = 1;
  color
======================
  'red'

The following queries will not return a conversion error but will not return any results:

SELECT color FROM tbl WHERE color = date'2010-01-01';
SELECT color FROM tbl WHERE color = 15;
SELECT color FROM tbl WHERE color = 'asdf';

In the following queries the ENUM type will be converted to the type of the other operand:

-- CHAR comparison using the enum value
SELECT color FROM tbl WHERE color < 'pink';
  color
======================
  'blue'
  'green'
-- INTEGER comparison using the enum index
SELECT color FROM tbl WHERE color > 3;
  color
======================
  'green'
-- Conversion error
SELECT color FROM tbl WHERE color > date'2012-01-01';
ERROR: Cannot coerce value of domain "enum" to domain "date".
ENUM Type Ordering

Values of the ENUM type are ordered by value index, not by enum value. When defining a column with ENUM type, users also define the ordering of the enum values.

SELECT color FROM tbl ORDER BY color ASC;
  color
======================
  'red'
  'yellow'
  'blue'
  'green'

To order the values stored in an ENUM type column as CHAR values, users can cast the enum value to the CHAR type:

SELECT color FROM tbl ORDER BY CAST (color AS VARCHAR) ASC;
  color
======================
  'blue'
  'green'
  'red'
  'yellow'
Notes

The ENUM type is not a reusable type. If several columns require the same set of values, an ENUM type must be defined for each one. When comparing two columns of ENUM type, the comparison is performed as if the columns were coerced to CHAR type even if the two ENUM types define the same set of values.

Using the ALTER ... CHANGE statement to modify the set of values of an ENUM type is only allowed if the value of the system parameter alter_table_change_type_strict is set to yes. In this case, CUBRID uses enum value (the char-literal) to convert values to the new domain. If a value is outside of the new ENUM type values set, it is automatically mapped to the empty string('').

CREATE TABLE tbl(color ENUM ('red', 'green', 'blue'));
INSERT INTO tbl VALUES('red'), ('green'), ('blue');

The following statement will extend the ENUM type with the value 'yellow':

ALTER TABLE tbl CHANGE color color ENUM ('red', 'green', 'blue', 'yellow');
INSERT into tbl VALUES(4);
SELECT color FROM tbl;
  color
======================
  'red'
  'green'
  'blue'
  'yellow'

The following statement will change all tuples with value 'green' to value 'red' because the value 'green' cannot be converted the new ENUM type:

ALTER TABLE tbl CHANGE color color enum ('red', 'yellow', 'blue');
SELECT color FROM tbl;
  color
======================
  'red'
  ''
  'blue'
  'yellow'

The ENUM type is mapped to char-string types in CUBRID drivers. The following example shows how to use the ENUM type in a JDBC application:

Statement stmt = connection.createStatement("SELECT color FROM tbl");
ResultSet rs = stmt.executeQuery();

while(rs.next()) {
   System.out.println(rs.getString());
}

The following example shows how to use the ENUM type in a CCI application.

req_id = cci_prepare (conn, "SELECT color FROM tbl", 0, &err);
error = cci_execute (req_id, 0, 0, &err);
if (error < CCI_ER_NO_ERROR)
{
    /* handle error */
}

error = cci_cursor (req_id, 1, CCI_CURSOR_CURRENT, &err);
if (error < CCI_ER_NO_ERROR)
{
    /* handle error */
}

error = cci_fetch (req_id, &err);
if (error < CCI_ER_NO_ERROR)
{
    /* handle error */
}

cci_get_data (req, idx, CCI_A_TYPE_STR, &data, 1);
BLOB/CLOB Data Types

An External LOB type is data to process Large Object, such as text or images. When LOB-type data is created and inserted, it will be stored in a file to an external storage, and the location information of the relevant file (LOB Locator) will be stored in the CUBRID database. If the LOB Locator is deleted from the database, the relevant file that was stored in the external storage will be deleted as well. CUBRID supports the following two types of LOB :

  • Binary Large Object (BLOB)
  • Character Large Object (CLOB)

Note

Terminologies

  • LOB (Large Object): Large-sized objects such as binaries or text.
  • FBO (File Based Object): An object that stores data of the database in an external file.
  • External LOB: An object better known as FBO, which stores LOB data in a file into an external DB. It is supported by CUBRID. Internal LOB is an object that stores LOB data inside the DB.
  • External Storage: An external storage to store LOB (example : POSIX file system).
  • LOB Locator: The path name of a file stored in external storage.
  • LOB Data: Details of a file in a specific location of LOB Locator.

When storing LOB data in external storage, the following naming convention will be applied:

{table_name}_{unique_name}
  • table_name : It is inserted as a prefix and able to store the LOB data of many tables in one external storage.
  • unique_name : The random name created by the DB server.

LOB data is stored in the local file system of the DB server. LOB data is stored in the path specified in the -lob-base-path option value of cubrid createdb; if this value is omitted, the data will be stored in the [db-vol path]/lob path where the database volume will be created. For more details, see createdb and To create and manage LOB storage.

If a user change any LOB file without using CUBRID API or CUBRID tools, data consistency is not guaranteed.

If a LOB data file path that was registered to the database directory file(databases.txt) is deleted, please note that database server (cub_server) and standalone utilities will not correctly work.

BLOB

A type that stores binary data outside the database. The maximum length of BLOB data is the maximum file size creatable in an external storage. In SQL statements, the BLOB type expresses the input and output value in a bit string. That is, it is compatible with the BIT (n) and BIT VARYING (n) types, and only an explicit type change is allowed. If data lengths differ from one another, the maximum length is truncated to fit the smaller one. When converting the BLOB type value to a binary value, the length of the converted data cannot exceed 1GB. When converting binary data to the BLOB type, the size of the converted data cannot exceed the maximum file size provided by the BLOB storage.

CLOB

A type that stores character string data outside the database. The maximum length of CLOB data is the maximum file size creatable in an external storage. In SQL statements, the CLOB type expresses the input and output value in a character string. That is, it is compatible with the CHAR (n), VARCHAR (n) types. However, only an explicit type change is allowed, and if data lengths are different from one another, the maximum length is truncated to fit to the smaller one. When converting the CLOB type value to a character string, the length of the converted data cannot exceed 1 GB. When converting a character string to the CLOB type, the size of the converted data cannot exceed the maximum file size provided by the CLOB storage.

To Create and alter LOB

BLOB / CLOB type columns can be created/added/deleted by using a CREATE TABLE statement or an ALTER TABLE statement.

  • You cannot create the index file for a LOB type column.
  • You cannot define the PRIMARY KEY, FOREIGN KEY, UNIQUE, NOT NULL constraints for a LOB type column. However, SHARED property cannot be defined and DEFAULT property can only be defined by the NULL value.
  • LOB type column/data cannot be the element of collection type.
  • If you are deleting a record containing a LOB type column, all files located inside a LOB column value (Locator) and the external storage will be deleted. When a record containing a LOB type column is deleted in a basic key table, and a record of a foreign key table that refers to the foregoing details is deleted at once, all LOB files located in a LOB column value (Locator) and the external storage will be deleted. However, if the relevant table is deleted by using a DROP TABLE statement, or a LOB column is deleted by using an ALTER TABLE...DROP statement, only a LOB column value (LOB Locator) is deleted, and the LOB files inside the external storage which a LOB column refers to will not be deleted.
-- creating a table and CLOB column
CREATE TABLE doc_t (doc_id VARCHAR(64) PRIMARY KEY, content CLOB);

-- an error occurs when UNIQUE constraint is defined on CLOB column
ALTER TABLE doc_t ADD CONSTRAINT content_unique UNIQUE(content);

-- an error occurs when creating an index on CLOB column
CREATE INDEX i_doc_t_content ON doc_t (content);

-- creating a table and BLOB column
CREATE TABLE image_t (image_id VARCHAR(36) PRIMARY KEY, doc_id VARCHAR(64) NOT NULL, image BLOB);

-- an error occurs when adding a BOLB column with NOT NULL constraint
ALTER TABLE image_t ADD COLUMN thumbnail BLOB NOT NULL;

-- an error occurs when adding a BLOB column with DEFAULT attribute
ALTER TABLE image_t ADD COLUMN thumbnail2 BLOB DEFAULT BIT_TO_BLOB(X'010101');
To store and update LOB

In a BLOB / CLOB type column, each BLOB / CLOB type value is stored, and if binary or character string data is input, you must explicitly change the types by using each BIT_TO_BLOB() and CHAR_TO_CLOB() function.

If a value is input in a LOB column by using an INSERT statement, a file is created in an external storage internally and the relevant data is stored; the relevant file path (Locator) is stored in an actual column value.

If a record containing a LOB column uses a DELETE statement, a file to which the relevant LOB column refers will be deleted simultaneously.

If a LOB column value is changed using an UPDATE statement, the column value will be changed following the operation below, according to whether a new value is NULL or not.

  • If a LOB type column value is changed to a value that is not NULL : If a Locator that refers to an external file is already available in a LOB column, the relevant file will be deleted. A new file is created afterwards. After storing a value that is not NULL, a Locator for a new file will be stored in a LOB column value.
  • If changing a LOB type column value to NULL : If a Locator that refers to an external file is already available in a LOB column, the relevant file will be deleted. And then NULL is stored in a LOB column value.
-- inserting data after explicit type conversion into CLOB type column
INSERT INTO doc_t (doc_id, content) VALUES ('doc-1', CHAR_TO_CLOB('This is a Dog'));
INSERT INTO doc_t (doc_id, content) VALUES ('doc-2', CHAR_TO_CLOB('This is a Cat'));

-- inserting data after explicit type conversion into BLOB type column
INSERT INTO image_t VALUES ('image-0', 'doc-0', BIT_TO_BLOB(X'000001'));
INSERT INTO image_t VALUES ('image-1', 'doc-1', BIT_TO_BLOB(X'000010'));
INSERT INTO image_t VALUES ('image-2', 'doc-2', BIT_TO_BLOB(X'000100'));

-- inserting data from a sub-query result
INSERT INTO image_t SELECT 'image-1010', 'doc-1010', image FROM image_t WHERE image_id = 'image-0';

-- updating CLOB column value to NULL
UPDATE doc_t SET content = NULL WHERE doc_id = 'doc-1';

-- updating CLOB column value
UPDATE doc_t SET content = CHAR_TO_CLOB('This is a Dog') WHERE doc_id = 'doc-1';

-- updating BLOB column value
UPDATE image_t SET image = (SELECT image FROM image_t WHERE image_id = 'image-0') WHERE image_id = 'image-1';

-- deleting BLOB column value and its referencing files
DELETE FROM image_t WHERE image_id = 'image-1010';
To access LOB

When you get a LOB type column, the data stored in a file to which the column refers will be displayed. You can execute an explicit type change by using CAST() operator, CLOB_TO_CHAR() and BLOB_TO_BIT() function.

  • If the query is executed in CSQL, a column value (Locator) will be displayed, instead of the data stored in a file. To display the data to which a BLOB / CLOB column refers, it must be changed to strings by CLOB_TO_CHAR() function.
  • To use the string process function, the strings need to be converted by CLOB_TO_CHAR() function.
  • You cannot specify a LOB column in ** GROUP BY** clause and ORDER BY clause.
  • Comparison operators, relational operators, IN, NOT IN operators cannot be used to compare LOB columns. However, IS NULL expression can be used to compare whether it is a LOB column value (Locator) or NULL. This means that TRUE will be returned when a column value is NULL, and if a column value is NULL, there is no file to store LOB data.
  • When a LOB column is created, and the file is deleted after data input, a LOB column value (Locator) will become a state that is referring to an invalid file. As such, using CLOB_TO_CHAR(), BLOB_TO_BIT(), CLOB_LENGTH() and BLOB_LENGTH() functions on the columns that have mismatching LOB Locator and a LOB data file enables them to display NULL.
-- displaying locator value when selecting CLOB and BLOB column in CSQL interpreter
SELECT doc_t.doc_id, content, image FROM doc_t, image_t WHERE doc_t.doc_id = image_t.doc_id;
  doc_id                content               image
==================================================================
  'doc-1'               file:/home1/data1/ces_658/doc_t.00001282208855807171_7329  file:/home1/data1/ces_318/image_t.00001282208855809474_7474
  'doc-2'               file:/home1/data1/ces_180/doc_t.00001282208854194135_5598  file:/home1/data1/ces_519/image_t.00001282208854205773_1215

2 rows selected.
-- using string functions after coercing its type by CLOB_TO_CHAR( )
SELECT CLOB_TO_CHAR(content), SUBSTRING(CLOB_TO_CHAR(content), 10) FROM doc_t;
   clob_to_char(content)  substring( clob_to_char(content) from 10)
============================================
  'This is a Dog'       ' Dog'
  'This is a Cat'       ' Cat'

2 rows selected.
SELECT CLOB_TO_CHAR(content) FROM doc_t WHERE CLOB_TO_CHAR(content) LIKE '%Dog%';
   clob_to_char(content)
======================
  'This is a Dog'
SELECT CLOB_TO_CHAR(content) FROM doc_t ORDER BY CLOB_TO_CHAR(content);
   clob_to_char(content)
======================
  'This is a Cat'
  'This is a Dog'
SELECT * FROM doc_t WHERE content LIKE 'This%';
  doc_id                content
============================================
  'doc-1'               file:/home1/data1/ces_004/doc_t.00001366272829040346_0773
  'doc-2'               file:/home1/data1/ces_256/doc_t.00001366272815153996_1229
-- an error occurs when LOB column specified in ORDER BY/GROUP BY clauses
SELECT * FROM doc_t ORDER BY content;
ERROR: doc_t.content can not be an ORDER BY column
Functions and Operators for LOB

You can explicitly cast bit/string type to BLOB/CLOB type and BLOB/CLOB type to bit/string type with CAST() operator. For more details, see CAST() operator.

CAST (<bit_type_column_or_value> AS { BLOB | CLOB })
CAST (<char_type_column_or_value> AS { BLOB | CLOB })

These are the functions for BLOB/CLOB types. For more details, refer LOB Functions.

Note

" <blob_or_clob_column IS NULL ": using IS NULL condition, it compares the value of LOB column(Locator) if it's NULL or not. If it's NULL, this condition returns TRUE.

To create and manage LOB storage

By default, the LOB data file is stored in the <db-volume-path>/lob directory where database volume is created. However, if the lob base path is specified with createdb -B option when creating the database, LOB data files will be stored in the directory designated. However, if the specified directory does not exist, CUBRID tries to create the directory and display an error message when it fails to create it. For more details, see createdb -B option.

# image_db volume is created in the current work directory, and a LOB data file will be stored.
% cubrid createdb image_db en_US

# LOB data file is stored in the "/home1/data1" path within a local file system.
% cubrid createdb --lob-base-path="file:/home1/data1" image_db en_US

You can identify a directory where a LOB file will be stored by executing the cubrid spacedb utility.

% cubrid spacedb image_db

Space description for database 'image_db' with pagesize 16.0K. (log pagesize: 16.0K)

Volid  Purpose  total_size  free_size  Vol Name

    0  GENERIC      512.0M     510.1M  /home1/data1/image_db

Space description for temporary volumes for database 'image_db' with pagesize 16.0K.

Volid  Purpose  total_size  free_size  Vol Name

LOB space description file:/home1/data1

To expand or change the lob-base-path of the database, change its lob-base-path of databases.txt file. Restart the database server to apply the changes made to databases.txt. However, even if you change the lob-base-path of databases.txt, access to the LOB data stored in a previous storage is possible.

# You can change to a new directory from the lob-base-path of databases.txt file.
% cat $CUBRID_DATABASES/databases.txt

#db-name     vol-path           db-host       log-path              lob-base-path
image_db     /home1/data1       localhost     /home1/data1          file:/home1/data2

Backup/recovery for data files of LOB type columns are not supported, while those for meta data(Locator) are supported.

If you are copying a database by using copydb utility, you must configure the databases.txt additionally, as the LOB file directory path will not be copied if the related option is not specified. For more details, see the copydb -B and copydb --copy-lob-path options.

Transaction and Recovery

Commit/Rollback for LOB data changes are supported. That is, it ensures the validation of mapping between LOB Locator and actual LOB data within transactions, and it supports recovery during DB errors. This means that an error will be displayed in case of mapping errors between LOB Locator and LOB data due to the rollback of the relevant transactions, as the database is terminated during transactions. See the example below.

-- csql> ;AUTOCOMMIT OFF

CREATE TABLE doc_t (doc_id VARCHAR(64) PRIMARY KEY, content CLOB);
INSERT INTO doc_t VALUES ('doc-10', CHAR_TO_CLOB('This is content'));
COMMIT;
UPDATE doc_t SET content = CHAR_TO_CLOB('This is content 2') WHERE doc_id = 'doc-10';
ROLLBACK;
SELECT doc_id, CLOB_TO_CHAR(content) FROM doc_t WHERE doc_id = 'doc-10';
  doc_id   content
=========================================================
  'doc-10'  'This is content'
-- csql> ;AUTOCOMMIT OFF

INSERT INTO doc_t VALUES ('doc-11', CHAR_TO_CLOB ('This is content'));
COMMIT;
UPDATE doc_t SET content = CHAR_TO_CLOB('This is content 3') WHERE doc_id = 'doc-11';

-- system crash occurred and then restart server
SELECT doc_id, CLOB_TO_CHAR(content) FROM doc_t WHERE doc_id = 'doc-11';
-- Error : LOB Locator references to the previous LOB data because only LOB Locator is rollbacked.

Note

  • When selecting LOB data in an application through a driver such as JDBC, the driver can get ResultSet from DB server and fetch the record while changing the cursor location on Resultset. That is, only Locator, the meta data of a LOB column, is stored at the time when ResultSet is imported, and LOB data that is referred by a File Locator will be fetched from the file Locator at the time when a record is fetched. Therefore, if LOB data is updated between two different points of time, there could be an error, as the mapping of LOB Locator and actual LOB data will be invalid.
  • Since backup/recovery is supported only for meta data (Locator) of the LOB type columns, an error is likely to occur, as the mapping of LOB Locator and LOB data is invalid if recovery is performed based on a specific point of time.
  • TO execute INSERT the LOB data into other device, LOB data referred by the meta data (Locator) of a LOB column must be read.
  • In a CUBRID HA environment, the meta data (Locator) of a LOB column is replicated and data of a LOB type is not replicated. Therefore, if storage of a LOB type is located on the local machine, no tasks on the columns in a slave node or a master node after failover are allowed.

Warning

Up to CUBRID 2008 R3.0, Large Objects are processed by using glo (Generalized Large Object) classes. However, the glo classes has been deprecated since the CUBRID 2008 R3.1. Instead of it, LOB / CLOB data type is supported. Therefore, both DB schema and application must be modified when upgrading CUBRID in an environment using the previous version of glo classes.

Collection Types

Allowing multiple data values to be stored in a single attribute is an extended feature of relational database. Each element of a collection is possible to have different data type each other except View. Rest types except BLOB and CLOB can be an element of collection types.

Type Description Definition Input Data Stored Data
SET A union which does not allow duplicates col_name SET VARCHAR(20) or col_name SET (VARCHAR(20)) {'c','c','c','b','b','a'} {'a','b','c'}
MULTISET A union which allows duplicates col_name MULTISET VARCHAR(20) or col_name MULTISET (VARCHAR(20)) {'c','c','c','b','b','a'} {'a','b','b','c','c','c'}
LIST or SEQUENCE A union which allows duplicates and stores data in the order of input col_name LIST VARCHAR(20) or col_name LIST (VARCHAR(20)) {'c','c','c','b','b','a'} {'c','c','c','b','b','a'}

As you see the table above, the value specified as a collection type can be inputted with curly braces ('{', '}') each value is separated with a comma (,).

If the specified collection types are identical, the collection types can be cast explicitly by using the CAST operator. The following table shows the collection types that allow explicit coercions.

FROM \ TO SET MULTISET LIST
SET - Yes Yes
MULTISET Yes - No
LIST Yes Yes -

Collection Types do not support collations. Therefore, Below query returns error.

CREATE TABLE tbl (str SET (string) COLLATE utf8_en_ci);
Syntax error: unexpected 'COLLATE', expecting ',' or ')'
SET

SET is a collection type in which each element has different values. Elements of a SET are allowed to have only one data type. It can have records of other tables.

CREATE TABLE set_tbl (col_1 SET (CHAR(1)));
INSERT INTO set_tbl VALUES ({'c','c','c','b','b','a'});
INSERT INTO set_tbl VALUES ({NULL});
INSERT INTO set_tbl VALUES ({''});
SELECT * FROM set_tbl;
  col_1
======================
{'a', 'b', 'c'}
{NULL}
{' '}
SELECT CAST (col_1 AS MULTISET), CAST (col_1 AS LIST) FROM set_tbl;
   cast(col_1 as multiset)   cast(col_1 as sequence)
============================================
  {'a', 'b', 'c'}  {'a', 'b', 'c'}
  {NULL}  {NULL}
  {' '}  {' '}
INSERT INTO set_tbl VALUES ('');
ERROR: Casting '' to type set is not supported.
MULTISET

MULTISET is a collection type in which duplicated elements are allowed. Elements of a MULTISET are allowed to have only one data type. It can have records of other tables.

CREATE TABLE multiset_tbl (col_1 MULTISET (CHAR(1)));
INSERT INTO multiset_tbl VALUES ({'c','c','c','b','b', 'a'});
SELECT * FROM multiset_tbl;
  col_1
======================
  {'a', 'b', 'b', 'c', 'c', 'c'}
SELECT CAST(col_1 AS SET), CAST(col_1 AS LIST) FROM multiset_tbl;
   cast(col_1 as set)   cast(col_1 as sequence)
============================================
  {'a', 'b', 'c'}  {'c', 'c', 'c', 'b', 'b', 'a'}
LIST/SEQUENCE

LIST (= SEQUENCE) is a collection type in which the input order of elements is preserved, and duplications are allowed. Elements of a LIST are allowed to have only one data type. It can have records of other tables.

CREATE TABLE list_tbl (col_1 LIST (CHAR(1)));
INSERT INTO list_tbl VALUES ({'c','c','c','b','b', 'a'});
SELECT * FROM list_tbl;
  col_1
======================
  {'c', 'c', 'c', 'b', 'b', 'a'}
SELECT CAST(col_1 AS SET), CAST(col_1 AS MULTISET) FROM list_tbl;
   cast(col_1 as set)  cast(col_1 as multiset)
============================================
  {'a', 'b', 'c'}  {'a', 'b', 'b', 'c', 'c', 'c'}
Implicit Type Conversion

An implicit type conversion represents an automatic conversion of a type of expression to a corresponding type.

SET, MULTISET, LIST and SEQUENCE should be converted explicitly.

If you convert the DATETIME and the TIMESTAMP types to the DATE type or the TIME type, data loss may occur. If you convert the DATE type to the DATETIME type or the TIMESTAMP type, the time will be set to '12:00:00 AM.'

If you convert a string type or an exact numeric type to a floating-point numeric type, the value may not be accurate. Because a string type and an exact type use a decimal precision to represent the value, but a floating-point numeric type uses a binary precision.

The implicit type conversion executed by CUBRID is as follows:

Implicit Type Conversion Table 1

From \ To DATETIME DATE TIME TIMESTAMP DOUBLE FLOAT NUMERIC BIGINT
DATETIME - O O O        
DATE O -   O        
TIME     -          
TIMESTAMP O O O -        
DOUBLE     O O - O O O
FLOAT     O O O - O O
NUMERIC       O O O - O
BIGINT     O O O O O -
INT     O O O O O O
SHORT     O O O O O O
BIT                
VARBIT                
CHAR O O O O O O O O
VARCHAR O O O O O O O O

Limitations when numeric value is changed as TIME or TIMESTAMP

  • All numeric types except for NUMERIC type can be converted into TIME type; at this time, it represents a value of the remainder which is calcuated by dividing the input number into 86,400 seconds(1 day), and the remainder is calculated as seconds.
  • All numeric types including NUMERIC can be converted into TIMESTAMP type; at this time, the input number cannot exceed 2,147,483,647 as the maximum.

Implicit Type Conversion Table 2

From \ To INT SHORT BIT VARBIT CHAR VARCHAR
DATETIME         O O
DATE         O O
TIME         O O
TIMESTAMP         O O
DOUBLE O O     O O
FLOAT O O     O O
NUMERIC O O     O O
BIGINT O O     O O
INT - O     O O
SHORT O -     O O
BIT     - O O O
VARBIT     O - O O
CHAR O O O O - O
VARCHAR O O O O O -
Conversion Rules
INSERT and UPDATE

The type will be converted to the type of the column affected.

CREATE TABLE t(i INT);
INSERT INTO t VALUES('123');

SELECT * FROM t;
            i
=============
          123
Function

If the parameter value entered in the function can be converted to the specified type, the parameter type will be converted. The strings are converted to numbers because the input parameter expected in the following function is a number.

SELECT MOD('123','2');
           mod('123', '2')
==========================
     1.000000000000000e+00

You can enter multiple type values in the function. If the type value not specified in the function is delivered, the type will be converted depending on the following priority order.

  • Date/Time Type ( DATETIME > TIMESTAMP > DATE > TIME )
  • Approximate Numeric Type ( DOUBLE > FLOAT )
  • Exact Numeric Type ( NUMERIC > BIGINT > INT > SHORT )
  • String Type ( CHAR > VARCHAR )
Comparison Operation

The following are the conversion rules according to an operand type of the comparison operator.

operand1 Type operand2 Type Conversion Comparison
Numeric Type Numeric Type None NUMERIC
String Type Converts operand2 to DOUBLE NUMERIC
Date/Time Type Converts operand1 to Date/Time TIME/TIMESTAMP
String Type Numeric Type Converts operand1 to DOUBLE NUMERIC
String Type None String
Date/Time Type Converts operand1 to date/time type Date/Time
Date/Time Type Numeric Type Converts operand2 to Date/Time TIME/TIMESTAMP
String Type Converts operand2 to date/time type Date/Time
Date/Time Type Converts it to the type with higher priority Date/Time

When Date/Time type and numeric type are compared, see Limitations when numeric value is changed as TIME or TIMESTAMP of the above table.

There are exceptions when operand1 is string type and operand2 is a value.

operand1 Type operand2 Type Conversion Comparison
String type Numeric type Converts operand2 to the string type String
Date/Time type Converts operand2 to the string type String

If operand2 is a set operator( IS IN, IS NOT IN, = ALL, = ANY, < ALL, < ANY, <= ALL, <= ANY, >= ALL, >= ANY ), the exception above is not applied.

The following is examples of implicit type conversion in comparison operations.

  • Numeric Type & String Type Operands

    The string type operand will be converted to DOUBLE.

    CREATE TABLE t1(i INT, s STRING);
    INSERT INTO t1 VALUES(1,'1'),(2,'2'),(3,'3'),(4,'4'), (12,'12');
    
    SELECT i FROM t1 WHERE i < '11.3';
    
                i
    =============
                1
                2
                3
                4
    
    SELECT ('2' <= 11);
    
         ('2'<11)
    =============
                1
    
  • String Type & Date/Time Type Operands

    The string type operand will be converted to the date/time type.

    SELECT ('2010-01-01' < date'2010-02-02');
    
       ('2010-01-01'<date '2010-02-02')
    ==================================
                                    1
    
    SELECT (date'2010-02-02' >= '2010-01-01');
    
      (date '2010-02-02'>='2010-01-01')
    ===================================
                                    1
    
  • String Type & Numeric Type Host Variable Operands

    The numeric type host variable will be converted to the string type.

    PREPARE s FROM 'SELECT s FROM t1 WHERE s < ?';
    EXECUTE s USING 11;
    
           s
    ===================
         '1'
    
  • String Type & Numeric Type value Operands

    The numeric type value will be converted to the string type.

    SELECT s FROM t1 WHERE s > 11;
    
           s
    ==================
         '2'
         '3'
         '4'
         '12'
    
    SELECT s FROM t1 WHERE s BETWEEN 11 AND 33;
    
            s
    ======================
          '2'
          '3'
          '12'
    
  • String Type Column & Date/Time Type Value Operands

    The date/time type value will be converted to the string type.

    CREATE TABLE t2 (s STRING);
    INSERT INTO t2 VALUES ('01/01/1998'), ('01/01/1999'), ('01/01/2000');
    SELECT s FROM t2;
    
               s
    ======================
        '01/01/1998'
        '01/01/1999'
        '01/01/2000'
    
    SELECT s FROM t2 WHERE s <= date'02/02/1998';
    

    In the above query, comparison operation is performed by converting date'02/02/1998' into string '02/02/1998'.

                s
    ======================
        '01/01/1998'
        '01/01/1999'
        '01/01/2000'
    
Range Operation
  • Numeric Type and String Type Operands

    The string type operand will be converted to DOUBLE.

    CREATE TABLE t3 (i INT);
    INSERT INTO t3 VALUES (1), (2), (3), (4);
    SELECT i FROM t3 WHERE i <= ALL {'11','12'};
    
                i
    =============
                1
                2
                3
                4
    
  • String Type and Date/Time Type Operands

    The string type operand will be converted to the date/time type.

    SELECT s FROM t2;
    
      s
    =================
      '01/01/1998'
      '01/01/1999'
      '01/01/2000'
    
    SELECT s FROM t2 WHERE s <= ALL {date'02/02/1998',date'01/01/2000'};
    
      s
    ================
     '01/01/1998'
    

    An error will be returned if it cannot be converted to the corresponding type.

Arithmetic Operation
  • Date/Time Type Operand

    If the date/time type operands are given to '-' operator and the types are different from each other, it will be converted to the type with a higher priority. The following example shows that the operand data type on the left is converted from DATE to DATETIME so that the result of '-' operation of DATETIME can be outputted in milliseconds.

    SELECT date'2002-01-01' - datetime'2001-02-02 12:00:00 am';
    
       date '2002-01-01'- datetime '2001-02-02 12:00:00 am'
    =====================================================
                                              28771200000
    
  • Numeric Type Operand

    If the numeric type operands are given and the types are different from each other, it will be converted to the type with the higher priority.

  • Date/Time Type & Numeric Type Operands

    If the date/time type and the numeric type operands are given to '+' or '-' operator, the numeric type operand is converted to either BIGINT, INT or SHORT.

  • Date/Time Type & String Type Operands

    If a date/time type and a string type are operands, only '+' and '-' operators are allowed. If the '+' operator is used, it will be applied according to the following rules.

    • The string type will be converted to BIGINT with an interval value. The interval is the smallest unit for operands in the Date/Time type, and the interval for each type is as follows:
      • DATE : Days
      • TIME, TIMESTAMP : Seconds
      • DATETIME : Milliseconds
    • Floating-point numbers are rounded.
    • The result type is the type of an date/time operand.
    SELECT date'2002-01-01' + '10';
    
      date '2002-01-01'+'10'
    ======================
      01/11/2002
    

    If the date/time type and a string type are operands and the '-' operator is used, they will be applied according to the following rules.

    • If the date/time type operands are DATE, DATETIME and TIMESTAMP, the string will be converted to DATETIME; if the date/time operand is TIME, the string is converted to TIME.
    • The result type is always BIGINT.
    SELECT date'2002-01-01'-'2001-01-01';
    
      date '2002-01-01'-'2001-01-01'
    ================================
                        31536000000
    
    -- this causes an error
    
    SELECT date'2002-01-01'-'10';
    
    ERROR: Cannot coerce '10' to type datetime.
    
  • Numeric Type & String Type Operands

    If a numeric type and a string type are operands, they will be applied according to the following rules.

    • Strings will be converted to DOUBLE when possible.
    • The result type is DOUBLE and depends on the type of the numeric operand.
    SELECT 4 + '5.2';
    
                    4+'5.2'
    ==========================
      9.199999999999999e+00
    

    Unlike CUBRID 2008 R3.1 and the earlier versions, the string in the date/time format, that is, the string such as '2010-09-15' is not converted to the date/time type. You can use a literal (DATE'2010-09-15') with the date/time type for addition and subtraction operations.

    SELECT '2002-01-01'+1;
    
    ERROR: Cannot coerce '2002-01-01' to type double.
    
    SELECT DATE'2002-01-01'+1;
    
      date '2002-01-01'+1
    =====================
      01/02/2002
    
  • String Type Operand

    If you multiply, divide or subtract both strings, the result returns a DOUBLE type value.

    SELECT '3'*'2';
    
                         '3'*'2'
    ============================
           6.000000000000000e+00
    

    The '+' operator action depends on how to set the system parameter plus_as_concat in the cubrid.conf file. For details, see Statement/Type-Related Parameters.

    • If a value for plus_as_concat is yes (default value), the concatenation of two strings will be returned.

      SELECT '1'+'1';
      
                     '1'+'1'
      ======================
                        '11'
      
    • If a value for plus_as_concat is no and two strings can be converted to numbers, the DOUBLE type value will be returned by adding the two numbers.

      SELECT '1'+'1';
      
                         '1'+'1'
      ==========================
           2.000000000000000e+00
      

    An error will be returned if it cannot be converted to the corresponding type.

Data Definition Statements

CREATE TABLE
Table Definition

To create a table, use the CREATE TABLE statement.

CREATE {TABLE | CLASS} [IF NOT EXISTS] table_name
[<subclass_definition>]
[(<column_definition>, ... [, <table_constraint>, ...])]
[AUTO_INCREMENT = initial_value]
[CLASS ATTRIBUTE (<column_definition>, ...)]
[INHERIT <resolution>, ...]
[<table_options>]

    <subclass_definition> ::= {UNDER | AS SUBCLASS OF} table_name, ...

    <column_definition> ::=
        column_name <data_type> [{<default_or_shared_or_ai> | <column_constraint>}] [COMMENT 'column_comment_string']

        <data_type> ::= <column_type> [<charset_modifier_clause>] [<collation_modifier_clause>]

            <charset_modifier_clause> ::= {CHARACTER_SET|CHARSET} {<char_string_literal>|<identifier>}

            <collation_modifier_clause> ::= COLLATE {<char_string_literal>|<identifier>}

        <default_or_shared_or_ai> ::=
            SHARED <value_specification> |
            DEFAULT <value_specification>  |
            AUTO_INCREMENT [(seed, increment)]

        <column_constraint> ::= [CONSTRAINT constraint_name] { NOT NULL | UNIQUE | PRIMARY KEY | FOREIGN KEY <referential_definition> }

            <referential_definition> ::=
                REFERENCES [referenced_table_name] (column_name, ...) [<referential_triggered_action> ...]

                <referential_triggered_action> ::=
                    ON UPDATE <referential_action> |
                    ON DELETE <referential_action>

                    <referential_action> ::= CASCADE | RESTRICT | NO ACTION | SET NULL

    <table_constraint> ::=
        [CONSTRAINT [constraint_name]]
        {
            UNIQUE [KEY|INDEX](column_name, ...) |
            {KEY|INDEX} [constraint_name](column_name, ...) |
            PRIMARY KEY (column_name, ...) |
            <referential_constraint>
        } COMMENT 'index_comment_string'

        <referential_constraint> ::= FOREIGN KEY [<foreign_key_name>](column_name, ...) <referential_definition>

            <referential_definition> ::=
                REFERENCES [referenced_table_name] (column_name, ...) [<referential_triggered_action> ...]

                <referential_triggered_action> ::=
                    ON UPDATE <referential_action> |
                    ON DELETE <referential_action>

                    <referential_action> ::= CASCADE | RESTRICT | NO ACTION | SET NULL

    <resolution> ::= [CLASS] {column_name} OF superclass_name [AS alias]
    <table_options> ::= <table_option> [[,] <table_option> ...]
        <table_option> ::= REUSE_OID |
                           COMMENT [=] 'table_comment_string' |
                           [CHARSET charset_name] [COLLATE collation_name]
  • IF NOT EXISTS: If an identically named table already exists, a new table will not be created without an error.
  • table_name: specifies the name of the table to be created (maximum: 254 bytes).
  • column_name: specifies the name of the column to be created (maximum: 254 bytes).
  • column_type: specifies the data type of the column.
  • [SHARED value | DEFAULT value]: specifies the initial value of the column.
  • <column_constraint>: specifies the constraint of the column. Available constraints are NOT NULL, UNIQUE, PRIMARY KEY and FOREIGN KEY. For details, see Constraint Definition.
  • <default_or_shared_or_ai>: only one of DEFAULT, SHARED, AUTO_INCREMENT can be used. When AUTO_INCREMENT is specified, "(seed, increment)" and "AUTO_INCREMENT = initial_value" cannot be defined at the same time.
  • table_comment_string: specifies a table's comment
  • column_comment_string: specifies a column's comment.
  • index_comment_string: specifies an index's comment.
CREATE TABLE olympic2 (
    host_year        INT    NOT NULL PRIMARY KEY,
    host_nation      VARCHAR(40) NOT NULL,
    host_city        VARCHAR(20) NOT NULL,
    opening_date     DATE        NOT NULL,
    closing_date     DATE        NOT NULL,
    mascot           VARCHAR(20),
    slogan           VARCHAR(40),
    introduction     VARCHAR(1500)
);

The below adds a comment of a table with ALTER statement.

ALTER TABLE olympic2 COMMENT = 'this is new comment for olympic2';

The below includes an index comment when you create a table.

CREATE TABLE tbl (a INT, index i_t_a (a) COMMENT 'index comment');

Note

A CHECK constraint in the table schema

A CHECK constraint defined in the table schema is parsed, but ignored. The reason of being parsed is to support the compatibility when DB migration from other DBMS is done.

CREATE TABLE tbl (
    id INT PRIMARY KEY,
    CHECK (id > 0)
)
Column Definition

A column is a set of data values of a particular simple type, one for each row of the table.

<column_definition> ::=
    column_name <data_type> [[<default_or_shared_or_ai>] | [<column_constraint>]] ... [COMMENT 'comment_string']

    <data_type> ::= <column_type> [<charset_modifier_clause>] [<collation_modifier_clause>]

        <charset_modifier_clause> ::= {CHARACTER_SET|CHARSET} {<char_string_literal>|<identifier>}

        <collation_modifier_clause> ::= COLLATE {<char_string_literal>|<identifier>}

    <default_or_shared_or_ai> ::=
        SHARED <value_specification> |
        DEFAULT <value_specification>  |
        AUTO_INCREMENT [(seed, increment)]

    <column_constraint> ::= [CONSTRAINT constraint_name] {NOT NULL | UNIQUE | PRIMARY KEY | FOREIGN KEY <referential_definition>}
Column Name

How to create a column name, see Identifier. You can alter created column name by using the RENAME COLUMN Clause of the ALTER TABLE statement.

The following example shows how to create the manager2 table that has the following two columns: full_name and age.

CREATE TABLE manager2 (full_name VARCHAR(40), age INT );

Note

  • The first character of a column name must be an alphabet.
  • The column name must be unique in the table.
Setting the Column Initial Value (SHARED, DEFAULT)

An attribute in a table can be created with an initial SHARED or DEFAULT value. You can change the value of SHARED and DEFAULT in the ALTER TABLE statement.

  • SHARED : Column values are identical in all rows. If a value different from the initial value is INSERTed, the column value is updated to a new one in every row.
  • DEFAULT : The initial value set when the DEFAULT attribute was defined is stored even if the column value is not specified when a new row is inserted.

The pseudocolumn allows for the DEFAULT value as follows.

DEFAULT Value Data Type
SYS_TIMESTAMP TIMESTAMP
SYS_DATETIME DATETIME
SYS_DATE DATE
SYS_TIME TIME
USER, USER() STRING

Note

In version lower than CUBRID 9.0, the value at the time of CREATE TABLE has been saved when the DATE value of the DATE, DATETIME, TIME, TIMESTAMP column has been specified as SYS_DATE, SYS_DATETIME, SYS_TIME, SYS_TIMESTAMP while creating a table. Therefore, to enter the value at the time of data INSERT in version lower than CUBRID 9.0, the function should be entered to the VALUES clause of the INSERT syntax.

CREATE TABLE colval_tbl
(id INT, name VARCHAR SHARED 'AAA', phone VARCHAR DEFAULT '000-0000');
INSERT INTO colval_tbl (id) VALUES (1), (2);
SELECT * FROM colval_tbl;
           id  name                  phone
=========================================================
            1  'AAA'                 '000-0000'
            2  'AAA'                 '000-0000'
--updating column values on every row
INSERT INTO colval_tbl(id, name) VALUES (3,'BBB');
INSERT INTO colval_tbl(id) VALUES (4),(5);
SELECT * FROM colval_tbl;
           id  name                  phone
=========================================================
            1  'BBB'                 '000-0000'
            2  'BBB'                 '000-0000'
            3  'BBB'                 '000-0000'
            4  'BBB'                 '000-0000'
            5  'BBB'                 '000-0000'
--changing DEFAULT value in the ALTER TABLE statement
ALTER TABLE colval_tbl MODIFY phone VARCHAR DEFAULT '111-1111';
INSERT INTO colval_tbl (id) VALUES (6);
SELECT * FROM colval_tbl;
           id  name                  phone
=========================================================
            1  'BBB'                 '000-0000'
            2  'BBB'                 '000-0000'
            3  'BBB'                 '000-0000'
            4  'BBB'                 '000-0000'
            5  'BBB'                 '000-0000'
            6  'BBB'                 '111-1111'

The DEFAULT value of the pseudocolumn can be specified as one or more columns.

CREATE TABLE tbl (date1 DATE DEFAULT SYSDATE, date2 DATE DEFAULT SYSDATE);
CREATE TABLE tbl (date1 DATE DEFAULT SYSDATE,
                  ts1   TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
AUTO INCREMENT

You can define the AUTO_INCREMENT attribute for the column to automatically give serial numbers to column values. This can be defined only for SMALLINT, INTEGER, BIGINT and NUMERIC(p, 0) types.

DEFAULT, SHARED and AUTO_INCREMENT cannot be defined for the same column. Make sure the value entered directly by the user and the value entered by the auto increment attribute do not conflict with each other.

You can change the initial value of AUTO_INCREMENT by using the ALTER TABLE statement. For details, see AUTO_INCREMENT Clause of ALTER TABLE.

CREATE TABLE table_name (id INT AUTO_INCREMENT[(seed, increment)]);

CREATE TABLE table_name (id INT AUTO_INCREMENT) AUTO_INCREMENT = seed ;
  • seed : The initial value from which the number starts. All integers (positive, negative, and zero) are allowed. The default value is 1.
  • increment : The increment value of each row. Only positive integers are allowed. The default value is 1.

When you use the CREATE TABLE table_name (id INT AUTO_INCREMENT) AUTO_INCREMENT = seed; statement, the constraints are as follows:

  • You should define only one column with the AUTO_INCREMENT attribute.
  • Don't use (seed, increment) and AUTO_INCREMENT = seed together.
CREATE TABLE auto_tbl (id INT AUTO_INCREMENT, name VARCHAR);
INSERT INTO auto_tbl VALUES (NULL, 'AAA'), (NULL, 'BBB'), (NULL, 'CCC');
INSERT INTO auto_tbl (name) VALUES ('DDD'), ('EEE');
SELECT * FROM auto_tbl;
           id  name
===================================
            1  'AAA'
            2  'BBB'
            3  'CCC'
            4  'DDD'
            5  'EEE'
CREATE TABLE tbl (id INT AUTO_INCREMENT, val string) AUTO_INCREMENT = 3;
INSERT INTO tbl VALUES (NULL, 'cubrid');

SELECT * FROM tbl;
           id  val
===================================
            3  'cubrid'
CREATE TABLE t (id INT AUTO_INCREMENT, id2 int AUTO_INCREMENT) AUTO_INCREMENT = 5;
ERROR: To avoid ambiguity, the AUTO_INCREMENT table option requires the table to  have exactly one AUTO_INCREMENT column and no seed/increment specification.
CREATE TABLE t (i INT AUTO_INCREMENT(100, 2)) AUTO_INCREMENT = 3;
ERROR: To avoid ambiguity, the AUTO_INCREMENT table option requires the table to  have exactly one AUTO_INCREMENT column and no seed/increment specification.

Note

  • Even if a column has auto increment, the UNIQUE constraint is not satisfied.

  • If NULL is specified in the column where auto increment is defined, the value of auto increment is stored.

  • Even if a value is directly specified in the column where auto increment is defined, AUTO_INCREMENT value is not changed.

  • SHARED or DEFAULT attribute cannot be specified in the column in which AUTO_INCREMENT is defined.

  • The initial value and the final value obtained by auto increment cannot exceed the minimum and maximum values allowed in the given type.

  • Because auto increment has no cycle, an error occurs when the maximum value of the type exceeds, and no rollback is executed. Therefore, you must delete and recreate the column in such cases.

    For example, if a table is created as below, the maximum value of A is 32767. Because an error occurs if the value exceeds 32767, you must make sure that the maximum value of the column A does not exceed the maximum value of the type when creating the initial table.

    CREATE TABLE tb1(A SMALLINT AUTO_INCREMENT, B CHAR(5));
    
Constraint Definition

You can define NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY as the constraints. You can also create an index by using INDEX or KEY.

<column_constraint> ::= [CONSTRAINT constraint_name] { NOT NULL | UNIQUE | PRIMARY KEY | FOREIGN KEY <referential_definition> }

<table_constraint> ::=
    [CONSTRAINT [constraint_name]]
    {
        UNIQUE [KEY|INDEX](column_name, ...) |
        {KEY|INDEX} [constraint_name](column_name, ...) |
        PRIMARY KEY (column_name, ...) |
        <referential_constraint>
    }

    <referential_constraint> ::= FOREIGN KEY [<foreign_key_name>](column_name, ...) <referential_definition>

        <referential_definition> ::=
            REFERENCES [referenced_table_name] (column_name, ...) [<referential_triggered_action> ...]

            <referential_triggered_action> ::=
                ON UPDATE <referential_action> |
                ON DELETE <referential_action>

                <referential_action> ::= CASCADE | RESTRICT | NO ACTION | SET NULL
NOT NULL Constraint

A column for which the NOT NULL constraint has been defined must have a certain value that is not NULL. The NOT NULL constraint can be defined for all columns. An error occurs if you try to insert a NULL value into a column with the NOT NULL constraint by using the INSERT or UPDATE statement.

In the following example, if you input NULL value on the id column, it occurs an error because id column cannot have NULL value.

CREATE TABLE const_tbl1(id INT NOT NULL, INDEX i_index(id ASC), phone VARCHAR);

CREATE TABLE const_tbl2(id INT NOT NULL PRIMARY KEY, phone VARCHAR);
INSERT INTO const_tbl2 VALUES (NULL,'000-0000');
Putting value 'null' into attribute 'id' returned: Attribute "id" cannot be made NULL.
UNIQUE Constraint

The UNIQUE constraint enforces a column to have a unique value. An error occurs if a new record that has the same value as the existing one is added by this constraint.

You can place a UNIQUE constraint on either a column or a set of columns. If the UNIQUE constraint is defined for multiple columns, the uniqueness is ensured not for each column, but the combination of multiple columns.

In the following example, the second INSERT statement fails because the value of id column is the same as 1 with the value of id column in the first INSERT statement.

-- UNIQUE constraint is defined on a single column only
CREATE TABLE const_tbl5(id INT UNIQUE, phone VARCHAR);
INSERT INTO const_tbl5(id) VALUES (NULL), (NULL);
INSERT INTO const_tbl5 VALUES (1, '000-0000');
SELECT * FROM const_tbl5;
   id  phone
=================
 NULL  NULL
 NULL  NULL
    1  '000-0000'
INSERT INTO const_tbl5 VALUES (1, '111-1111');
ERROR: Operation would have caused one or more unique constraint violations.

In the following example, if a UNIQUE constraint is defined on several columns, this ensures the uniqueness of the values in all the columns.

-- UNIQUE constraint is defined on several columns
CREATE TABLE const_tbl6(id INT, phone VARCHAR, CONSTRAINT UNIQUE (id, phone));
INSERT INTO const_tbl6 VALUES (1, NULL), (2, NULL), (1, '000-0000'), (1, '111-1111');
SELECT * FROM const_tbl6;
   id  phone
====================
    1  NULL
    2  NULL
    1  '000-0000'
    1  '111-1111'
PRIMARY KEY Constraint

A key in a table is a set of column(s) that uniquely identifies each row. A candidate key is a set of columns that uniquely identifies each row of the table. You can define one of such candidate keys a primary key. That is, the column defined as a primary key is uniquely identified in each row.

By default, the index created by defining the primary key is created in ascending order, and you can define the order by specifying ASC or DESC keyword next to the column.

CREATE TABLE pk_tbl (a INT, b INT, PRIMARY KEY (a, b DESC));

CREATE TABLE const_tbl7 (
    id INT NOT NULL,
    phone VARCHAR,
    CONSTRAINT pk_id PRIMARY KEY (id)
);

-- CONSTRAINT keyword
CREATE TABLE const_tbl8 (
    id INT NOT NULL PRIMARY KEY,
    phone VARCHAR
);

-- primary key is defined on multiple columns
CREATE TABLE const_tbl8 (
    host_year    INT NOT NULL,
    event_code   INT NOT NULL,
    athlete_code INT NOT NULL,
    medal        CHAR (1)  NOT NULL,
    score        VARCHAR (20),
    unit         VARCHAR (5),
    PRIMARY KEY (host_year, event_code, athlete_code, medal)
);
FOREIGN KEY Constraint

A foreign key is a column or a set of columns that references the primary key in other tables in order to maintain reference relationship. The foreign key and the referenced primary key must have the same data type. Consistency between two tables is maintained by the foreign key referencing the primary key, which is called referential integrity.

[CONSTRAINT constraint_name] FOREIGN KEY [foreign_key_name] (<column_name_comma_list1>) REFERENCES [referenced_table_name] (<column_name_comma_list2>) [<referential_triggered_action> ...]

    <referential_triggered_action> ::=
        ON UPDATE <referential_action> |
        ON DELETE <referential_action>

        <referential_action> ::= CASCADE | RESTRICT | NO ACTION  | SET NULL
  • constraint_name: Specifies the name of the table to be created.
  • foreign_key_name: Specifies a name of the FOREIGN KEY constraint. You can skip the name specification. However, if you specify this value, constraint_name will be ignored, and the specified value will be used.
  • <column_name_comma_list1>: Specifies the name of the column to be defined as a foreign key after the FOREIGN KEY keyword. The column number of foreign keys defined and primary keys must be same.
  • referenced_table_name: Specifies the name of the table to be referenced.
  • <column_name_comma_list2>: Specifies the name of the referred primary key column after the FOREIGN KEY keyword.
  • <referential_triggered_action>: Specifies the trigger action that responds to a certain operation in order to maintain referential integrity. ON UPDATE or ON DELETE can be specified. Each action can be defined multiple times, and the definition order is not significant.
    • ON UPDATE: Defines the action to be performed when attempting to update the primary key referenced by the foreign key. You can use either NO ACTION, RESTRICT, or SET NULL option. The default is RESTRICT.
    • ON DELETE: Defines the action to be performed when attempting to delete the primary key referenced by the foreign key. You can use NO ACTION, RESTRICT, CASCADE, or SET NULL option. The default is RESTRICT.
  • <referential_action>: You can define an option that determines whether to maintain the value of the foreign key when the primary key value is deleted or updated.
    • CASCADE: If the primary key is deleted, the foreign key is deleted as well. This option is supported only for the ON DELETE operation.
    • RESTRICT: Prevents the value of the primary key from being deleted or updated, and rolls back any transaction that has been attempted.
    • SET NULL: When a specific record is being deleted or updated, the column value of the foreign key is updated to NULL.
    • NO ACTION: Its behavior is the same as that of the RESTRICT option.
-- creating two tables where one is referring to the other
CREATE TABLE a_tbl (
    id INT NOT NULL DEFAULT 0 PRIMARY KEY,
    phone VARCHAR(10)
);

CREATE TABLE b_tbl (
    ID INT NOT NULL,
    name VARCHAR (10) NOT NULL,
    CONSTRAINT pk_id PRIMARY KEY (id),
    CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES a_tbl (id)
    ON DELETE CASCADE ON UPDATE RESTRICT
);

INSERT INTO a_tbl VALUES (1,'111-1111'), (2,'222-2222'), (3, '333-3333');
INSERT INTO b_tbl VALUES (1,'George'),(2,'Laura'), (3,'Max');
SELECT a.id, b.id, a.phone, b.name FROM a_tbl a, b_tbl b WHERE a.id = b.id;
   id           id                   phone                 name
======================================================================
    1            1                   '111-1111'            'George'
    2            2                   '222-2222'            'Laura'
    3            3                   '333-3333'            'Max'
-- when deleting primary key value, it cascades foreign key value
DELETE FROM a_tbl WHERE id=3;
1 row affected.
SELECT a.id, b.id, a.phone, b.name FROM a_tbl a, b_tbl b WHERE a.id = b.id;
   id           id                   phone                 name
======================================================================
    1            1                   '111-1111'            'George'
    2            2                   '222-2222'            'Laura'
-- when attempting to update primary key value, it restricts the operation
UPDATE  a_tbl SET id = 10 WHERE phone = '111-1111';
ERROR: Update/Delete operations are restricted by the foreign key 'fk_id'.

Note

  • In a referential constraint, the name of the primary key table to be referenced and the corresponding column names are defined. If the list of column names are is not specified, the primary key of the primary key table is specified in the defined order.
  • The number of primary keys in a referential constraint must be identical to that of foreign keys. The same column name cannot be used multiple times for the primary key in the referential constraint.
  • The actions cascaded by reference constraints do not activate the trigger action.
  • It is not recommended to use referential_triggered_action in the CUBRID HA environment. In the CUBRID HA environment, the trigger action is not supported. Therefore, if you use referential_triggered_action, the data between the master database and the slave database can be inconsistent. For details, see CUBRID HA.
KEY or INDEX

KEY and INDEX are used interchangeably. They create an index that uses the corresponding column as a key.

CREATE TABLE const_tbl4(id INT, phone VARCHAR, KEY i_key(id DESC, phone ASC));

Note

In versions lower than CUBRID 9.0, index name can be omitted; however, in version of CUBRID 9.0 or higher, it is no longer allowed.

Column Option

You can specify options such as ASC or DESC after the column name when defining UNIQUE or INDEX for a specific column. This keyword is specified as store the index value in ascending or descending order.

column_name [ASC | DESC]
CREATE TABLE const_tbl(
    id VARCHAR,
    name VARCHAR,
    CONSTRAINT UNIQUE INDEX(id DESC, name ASC)
);

INSERT INTO const_tbl VALUES('1000', 'john'), ('1000','johnny'), ('1000', 'jone');
INSERT INTO const_tbl VALUES('1001', 'johnny'), ('1001','john'), ('1001', 'jone');

SELECT * FROM const_tbl WHERE id > '100';
  id    name
=================
  1001     john
  1001     johnny
  1001     jone
  1000     john
  1000     johnny
  1000     jone
Table Option
REUSE_OID

You can specify the REUSE_OID option when creating a table, so that OIDs that have been deleted due to the deletion of records (DELETE) can be reused when a new record is inserted (INSERT). Such a table is called an OID reusable or a non-referable table.

OID (Object Identifier) is an object identifier represented by physical location information such as the volume number, page number and slot number. By using such OIDs, CUBRID manages the reference relationships of objects and searches, stores or deletes them. When an OID is used, accessibility is improved because the object in the heap file can be directly accessed without referring to the table. However, the problem of decreased reusability of the storage occurs when there are many DELETE/ INSERT operations because the object's OID is kept to maintain the reference relationship with the object even if it is deleted.

If you specify the REUSE_OID option when creating a table, the OID is also deleted when data in the table is deleted, so that another INSERTed data can use it. OID reusable tables cannot be referred to by other tables, and OID values of the objects in the OID reusable tables cannot be viewed.

-- creating table with REUSE_OID option specified
CREATE TABLE reuse_tbl (a INT PRIMARY KEY) REUSE_OID, COMMENT = 'reuse oid table';
INSERT INTO reuse_tbl VALUES (1);
INSERT INTO reuse_tbl VALUES (2);
INSERT INTO reuse_tbl VALUES (3);

-- an error occurs when column type is a OID reusable table itself
CREATE TABLE tbl_1 (a reuse_tbl);
ERROR: The class 'reuse_tbl' is marked as REUSE_OID and is non-referable. Non-referable classes can't be the domain of an attribute and their instances' OIDs cannot be returned.

If you specify REUSE_OID together with the collation of table, it can be placed on before or after COLLATE syntax.

CREATE TABLE t3(a VARCHAR(20)) REUSE_OID, COMMENT = 'reuse oid table', COLLATE euckr_bin;
CREATE TABLE t4(a VARCHAR(20)) COLLATE euckr_bin REUSE_OID;

Note

  • OID reusable tables cannot be referred to by other tables.
  • Updatable views cannot be created for OID reusable tables.
  • OID reusable tables cannot be specified as table column type.
  • OID values of the objects in the OID reusable tables cannot be read.
  • Instance methods cannot be called from OID reusable tables. Also, instance methods cannot be called if a sub class inherited from the class where the method is defined is defined as an OID reusable table.
  • OID reusable tables are supported only by CUBRID 2008 R2.2 or above, and backward compatibility is not ensured. That is, the database in which the OID reusable table is located cannot be accessed from a lower version database.
  • OID reusable tables can be managed as partitioned tables and can be replicated.
Charset and Collation

The charset and collation of the table can be designated in CREATE TABLE statement. Please see Charset and Collation of String Literals for details.

Table's COMMENT

You can write a table's comment as following.

CREATE TABLE tbl (a INT, b INT) COMMENT = 'this is comment for table tbl';

To see the table's comment, run the below syntax.

SHOW CREATE TABLE table_name;
SELECT class_name, comment from db_class;
SELECT class_name, comment from _db_class;

Or you can see the table's comment with ;sc command in the CSQL interpreter.

$ csql -u dba demodb

csql> ;sc tbl
CREATE TABLE LIKE

You can create a table that has the same schema as an existing table by using the CREATE TABLE ... LIKE statement. Column attribute, table constraint, and index are replicated from the existing table. An index name created from the existing table changes according to a new table name, but an index name defined by a user is replicated as it is. Therefore, you should be careful at a query statement that is supposed to use a specific index created by using the index hint syntax(see Index Hint).

You cannot create the column definition because the CREATE TABLE ... LIKE statement replicates the schema only.

CREATE {TABLE | CLASS} <new_table_name> LIKE <source_table_name>;
  • new_table_name: A table name to be created

  • source_table_name: The name of the original table that already exists in the database. The following tables cannot be specified as original tables in the CREATE TABLE ... LIKE statement.

    • Partition table
    • Table that contains an AUTO_INCREMENT column
    • Table that uses inheritance or methods
CREATE TABLE a_tbl (
  id INT NOT NULL DEFAULT 0 PRIMARY KEY,
  phone VARCHAR(10)
);
INSERT INTO a_tbl VALUES (1,'111-1111'), (2,'222-2222'), (3, '333-3333');

-- creating an empty table with the same schema as a_tbl
CREATE TABLE new_tbl LIKE a_tbl;
SELECT * FROM new_tbl;
There are no results.

csql> ;schema a_tbl

=== <Help: Schema of a Class> ===


 <Class Name>

     a_tbl

 <Attributes>

     id                   INTEGER DEFAULT 0 NOT NULL
     phone                CHARACTER VARYING(10)

 <Constraints>

     PRIMARY KEY pk_a_tbl_id ON a_tbl (id)

csql> ;schema new_tbl

=== <Help: Schema of a Class> ===


 <Class Name>

     new_tbl

 <Attributes>

     id                   INTEGER DEFAULT 0 NOT NULL
     phone                CHARACTER VARYING(10)

 <Constraints>

     PRIMARY KEY pk_new_tbl_id ON new_tbl (id)
CREATE TABLE AS SELECT

You can create a new table that contains the result records of the SELECT statement by using the CREATE TABLE...AS SELECT statement. You can define column and table constraints for the new table. The following rules are applied to reflect the result records of the SELECT statement.

  • If col_1 is defined in the new table and the same column col_1 is specified in select_statement, the result record of the SELECT statement is stored as col_1 value in the new table. Type casting is attempted if the column names are identical but the columns types are different.
  • If col_1 and col_2 are defined in the new table, col_1, col_2 and col_3 are specified in the column list of the select_statement and there is a containment relationship between all of them, col_1, col_2 and col_3 are created in the new table and the result data of the SELECT statement is stored as values for all columns. Type casting is attempted if the column names are identical but the columns types are different.
  • If columns col_1 and col_2 are defined in the new table and col_1 and col_3 are defined in the column list of select_statement without any containment relationship between them, col_1, col_2 and col_3 are created in the new table, the result data of the SELECT statement is stored only for col_1 and col_3 which are specified in select_statement, and NULL is stored as the value of col_2.
  • Column aliases can be included in the column list of select_statement. In this case, new column alias is used as a new table column name. It is recommended to use an alias because invalid column name is created, if an alias does not exist when a function calling or an expression is used.
  • The REPLACE option is valid only when the UNIQUE constraint is defined in a new table column (col_1). When duplicate values exist in the result record of select_statement, a UNIQUE value is stored for col_1 if the REPLACE option has been defined, or an error message is displayed if the REPLACE option is omitted due to the violation of the UNIQUE constraint.
CREATE {TABLE | CLASS} table_name [(<column_definition> [,<table_constraint>], ...)] [REPLACE] AS <select_statement>;
  • table_name: a name of the table to be created.
  • <column_definition>: defines a column. If this is omitted, the column schema of SELECT statement is replicated; however, the constraint or the AUTO_INCREMENT attribute is not replicated.
  • <table_constraint>: defines table constraint.
  • <select_statement>: a SELECT statement targeting a source table that already exists in the database.
CREATE TABLE a_tbl (
  id INT NOT NULL DEFAULT 0 PRIMARY KEY,
  phone VARCHAR(10)
);
INSERT INTO a_tbl VALUES (1,'111-1111'), (2,'222-2222'), (3, '333-3333');

-- creating a table without column definition
CREATE TABLE new_tbl1 AS SELECT * FROM a_tbl;
SELECT * FROM new_tbl1;
   id  phone
===================================
    1  '111-1111'
    2  '222-2222'
    3  '333-3333'
-- all of column values are replicated from a_tbl
CREATE TABLE new_tbl2 (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  phone VARCHAR
) AS SELECT * FROM a_tbl;

SELECT * FROM new_tbl2;
   id  phone
===================================
    1  '111-1111'
    2  '222-2222'
    3  '333-3333'
-- some of column values are replicated from a_tbl and the rest is NULL
CREATE TABLE new_tbl3 (
  id INT,
  name VARCHAR
) AS SELECT id, phone FROM a_tbl;

SELECT * FROM new_tbl3
  name                           id  phone
=========================================================
  NULL                            1  '111-1111'
  NULL                            2  '222-2222'
  NULL                            3  '333-3333'
-- column alias in the select statement should be used in the column definition
CREATE TABLE new_tbl4 (
  id1 INT,
  id2 INT
) AS SELECT t1.id id1, t2.id id2 FROM new_tbl1 t1, new_tbl2 t2;

SELECT * FROM new_tbl4;
  id1          id2
==========================
    1            1
    1            2
    1            3
    2            1
    2            2
    2            3
    3            1
    3            2
    3            3
-- REPLACE is used on the UNIQUE column
CREATE TABLE new_tbl5 (id1 int UNIQUE) REPLACE AS SELECT * FROM new_tbl4;

SELECT * FROM new_tbl5;
  id1          id2
==========================
    1            3
    2            3
    3            3
ALTER TABLE

You can modify the structure of a table by using the ALTER statement. You can perform operations on the target table such as adding/deleting columns, creating/deleting indexes, and type casting existing columns as well as changing table names, column names and constraints. You can also change the initial value of AUTO_INCREMENT. TABLE and CLASS are used interchangeably VIEW and VCLASS, and COLUMN and ATTRIBUTE as well.

ALTER [TABLE | CLASS] table_name <alter_clause> [, <alter_clause>] ... ;

    <alter_clause> ::=
        ADD <alter_add> [INHERIT <resolution>, ...]  |
        ADD {KEY | INDEX} <index_name> (<index_col_name>, ... ) [COMMENT 'index_comment_string'] |
        ALTER [COLUMN] column_name SET DEFAULT <value_specification> |
        DROP <alter_drop> [ INHERIT <resolution>, ... ] |
        DROP {KEY | INDEX} index_name |
        DROP FOREIGN KEY constraint_name |
        DROP PRIMARY KEY |
        RENAME <alter_rename> [ INHERIT <resolution>, ... ] |
        CHANGE <alter_change> |
        MODIFY <alter_modify> |
        INHERIT <resolution>, ... |
        AUTO_INCREMENT = <initial_value> |
        COMMENT [=] 'table_comment_string'

        <alter_add> ::=
            [ATTRIBUTE|COLUMN] [(]<class_element>, ...[)] [FIRST|AFTER old_column_name] |
            CLASS ATTRIBUTE <column_definition>, ... |
            CONSTRAINT <constraint_name> <column_constraint> (column_name) |
            QUERY <select_statement> |
            SUPERCLASS <class_name>, ...

            <class_element> ::= <column_definition> | <table_constraint>

            <column_constraint> ::= UNIQUE [KEY] | PRIMARY KEY | FOREIGN KEY

        <alter_drop> ::=
            [ATTRIBUTE | COLUMN]
            {
                column_name, ... |
                QUERY [<unsigned_integer_literal>] |
                SUPERCLASS class_name, ... |
                CONSTRAINT constraint_name
            }

        <alter_rename> ::=
            [ATTRIBUTE | COLUMN]
            {
                old_column_name AS new_column_name |
                FUNCTION OF column_name AS function_name
            }

        <alter_change> ::=
            [COLUMN | CLASS ATTRIBUTE] old_col_name new_col_name <column_definition>
                [FIRST | AFTER col_name]

        <alter_modify> ::=
            [COLUMN | CLASS ATTRIBUTE] col_name <column_definition>
                [FIRST | AFTER col_name2]

        <table_option> ::=
            CHANGE [COLUMN | CLASS ATTRIBUTE] old_col_name new_col_name <column_definition>
                [FIRST | AFTER col_name2]
          | MODIFY [COLUMN | CLASS ATTRIBUTE] col_name <column_definition>
                [FIRST | AFTER col_name2]

        <resolution> ::= column_name OF superclass_name [AS alias]

        <index_col_name> ::= column_name [(length)] [ASC | DESC]

Note

A column's comment is specified in <column_definition>. For <column_definition>, see the above CREATE TABLE syntax.

Warning

The table's name can be changed only by the table owner, DBA and DBA members. The other users must be granted to change the name by the owner or DBA (see GRANT For details on authorization).

ADD COLUMN Clause

You can add a new column by using the ADD COLUMN clause. You can specify the location of the column to be added by using the FIRST or AFTER keyword.

ALTER [TABLE | CLASS] table_name
ADD [COLUMN | ATTRIBUTE] [(] <column_definition> [FIRST | AFTER old_column_name] [)];

    <column_definition> ::=
        column_name <data_type> [[<default_or_shared_or_ai>] | [<column_constraint>]] [COMMENT 'comment_string']

        <data_type> ::= <column_type> [<charset_modifier_clause>] [<collation_modifier_clause>]

            <charset_modifier_clause> ::= {CHARACTER_SET|CHARSET} {<char_string_literal>|<identifier>}

            <collation_modifier_clause> ::= COLLATE {<char_string_literal>|<identifier>}

        <default_or_shared_or_ai> ::=
            SHARED <value_specification> |
            DEFAULT <value_specification>  |
            AUTO_INCREMENT [(seed, increment)]

        <column_constraint> ::= [CONSTRAINT constraint_name] {NOT NULL | UNIQUE | PRIMARY KEY | FOREIGN KEY <referential_definition>}

            <referential_definition> ::=
                REFERENCES [referenced_table_name] (column_name, ...) [<referential_triggered_action> ...]

                <referential_triggered_action> ::=
                    ON UPDATE <referential_action> |
                    ON DELETE <referential_action>

                    <referential_action> ::= CASCADE | RESTRICT | NO ACTION | SET NULL
  • table_name: specifies the name of a table that has a column to be added.
  • <column_definition>: specifies the name(max 254 bytes), data type, and constraints of a column to be added.
  • AFTER oid_column_name: specifies the name of an existing column before the column to be added.
  • comment_string: specifies a column's comment.
CREATE TABLE a_tbl;
ALTER TABLE a_tbl ADD COLUMN age INT DEFAULT 0 NOT NULL COMMENT 'age comment';
ALTER TABLE a_tbl ADD COLUMN name VARCHAR FIRST;
ALTER TABLE a_tbl ADD COLUMN id INT NOT NULL AUTO_INCREMENT UNIQUE FIRST;
INSERT INTO a_tbl(age) VALUES(20),(30),(40);

ALTER TABLE a_tbl ADD COLUMN phone VARCHAR(13) DEFAULT '000-0000-0000' AFTER name;

SELECT * FROM a_tbl;
   id  name                  phone                         age
==============================================================
    1  NULL                  '000-0000-0000'                20
    2  NULL                  '000-0000-0000'                30
    3  NULL                  '000-0000-0000'                40

--adding multiple columns
ALTER TABLE a_tbl ADD COLUMN (age1 int, age2 int, age3 int);

The result when you add a new column depends on what constraints are added.

  • If there is a DEFAULT constraint on the newly added column, DEFAULT value is inserted.
  • If there is no DEFAULT constraint and there is a NOT NULL constraint, hard default value is inserted when a value of system parameter add_column_update_hard_default is yes; however, it returns an error when a value of add_column_update_hard_default is no.

The default of add_column_update_hard_default is no.

Depending on DEFAULT constraint and add_column_update_hard_default's value, if they do not violate their constraints, it is possible to add PRIMARY KEY constraint or UNIQUE constraint.

  • If the newly added column when there is no data on the table, or the newly added column with NOT NULL and UNIQUE data can have PRIMARY KEY constraint.

  • If you try to add a new column with PRIMARY KEY constraint when there is data on the table, it returns an error.

    CREATE TABLE tbl (a INT);
    INSERT INTO tbl VALUES (1), (2);
    ALTER TABLE tbl ADD COLUMN (b int PRIMARY KEY);
    
    ERROR: NOT NULL constraints do not allow NULL value.
    
  • If there is data and UNIQUE constraint is specified on the newly added data, NULL is inserted when there is no DEFAULT constraint.

    ALTER TABLE tbl ADD COLUMN (b int UNIQUE);
    SELECT * FROM tbl;
    
        a            b
    ==================
        1         NULL
        2         NULL
    
  • If there is data on the table and UNIQUE constraint is specified on the newly added column, unique violation error is returned when there is DEFAULT constraint.

    ALTER TABLE tbl ADD COLUMN (c int UNIQUE DEFAULT 10);
    
    ERROR: Operation would have caused one or more unique constraint violations.
    
  • If there is data on the table and UNIQUE constraint is specified on the newly added column, unique violation error is returned when there is NOT NULL constraint and the value of system parameter add_column_update_hard_default is yes.

    SET SYSTEM PARAMETERS 'add_column_update_hard_default=yes';
    ALTER TABLE tbl ADD COLUMN (c int UNIQUE NOT NULL);
    
    ERROR: Operation would have caused one or more unique constraint violations.
    

For add_column_update_hard_default and the hard default, see CHANGE/MODIFY Clauses.

ADD CONSTRAINT Clause

You can add a new constraint by using the ADD CONSTRAINT clause.

By default, the index created when you add PRIMARY KEY constraints is created in ascending order, and you can define the key sorting order by specifying the ASC or DESC keyword next to the column name.

ALTER [ TABLE | CLASS | VCLASS | VIEW ] table_name
ADD <table_constraint> ;

    <table_constraint> ::=
        [CONSTRAINT [constraint_name]]
        {
            UNIQUE [KEY|INDEX](column_name, ...) |
            {KEY|INDEX} [constraint_name](column_name, ...) |
            PRIMARY KEY (column_name, ...) |
            <referential_constraint>
        }

        <referential_constraint> ::= FOREIGN KEY [foreign_key_name](column_name, ...) <referential_definition>

            <referential_definition> ::=
                REFERENCES [referenced_table_name] (column_name, ...) [<referential_triggered_action> ...]

                <referential_triggered_action> ::=
                    ON UPDATE <referential_action> |
                    ON DELETE <referential_action>

                    <referential_action> ::= CASCADE | RESTRICT | NO ACTION | SET NULL
  • table_name: Specifies the name of a table that has a constraint to be added.
  • constraint_name: Specifies the name of a constraint to be added, or it can be omitted. If omitted, a name is automatically assigned(maximum: 254 bytes).
  • foreign_key_name: Specifies a name of the FOREIGN KEY constraint. You can skip the name specification. However, if you specify this value, constraint_name will be ignored, and the specified value will be used.
  • <table_constraint>: Defines a constraint for the specified table. For details, see Constraint Definition.
ALTER TABLE a_tbl ADD CONSTRAINT pk_a_tbl_id PRIMARY KEY(id);
ALTER TABLE a_tbl DROP CONSTRAINT pk_a_tbl_id;
ALTER TABLE a_tbl ADD CONSTRAINT pk_a_tbl_id PRIMARY KEY(id, name DESC);
ALTER TABLE a_tbl ADD CONSTRAINT u_key1 UNIQUE (id);
ADD INDEX Clause

You can define the index attributes for a specific column by using the ADD INDEX clause.

ALTER [TABLE | CLASS] table_name ADD {KEY | INDEX} index_name (<index_col_name>) ;

    <index_col_name> ::= column_name [(length)] [ ASC | DESC ]
  • table_name : Specifies the name of a table to be modified.
  • index_name : Specifies the name of an index(maximum: 254 bytes). If omitted, a name is automatically assigned.
  • index_col_name : Specifies the column that has an index to be defined. ASC or DESC can be specified for a column option.
ALTER TABLE a_tbl ADD INDEX i1(age ASC), ADD INDEX i2(phone DESC);
csql> ;schema a_tbl

=== <Help: Schema of a Class> ===

 <Class Name>

     a_tbl

<Attributes>

     name                 CHARACTER VARYING(1073741823) DEFAULT ''
     phone                CHARACTER VARYING(13) DEFAULT '111-1111'
     age                  INTEGER
     id                   INTEGER AUTO_INCREMENT  NOT NULL

 <Constraints>

     UNIQUE u_a_tbl_id ON a_tbl (id)
     INDEX i1 ON a_tbl (age)
     INDEX i2 ON a_tbl (phone DESC)

The below is an example to include an index's comment when you add an index with ALTER statement.

ALTER TABLE tbl ADD index i_t_c (c) COMMENT 'index comment c';
ALTER COLUMN ... SET DEFAULT Clause

You can specify a new default value for a column that has no default value or modify the existing default value by using the ALTER COLUMN ... SET DEFAULT. You can use the CHANGE clause to change the default value of multiple columns with a single statement. For details, see the CHANGE/MODIFY Clauses.

ALTER [TABLE | CLASS] table_name ALTER [COLUMN] column_name SET DEFAULT value ;
  • table_name : Specifies the name of a table that has a column whose default value is to be modified.
  • column_name : Specifies the name of a column whose default value is to be modified.
  • value : Specifies a new default value.
csql> ;schema a_tbl

=== <Help: Schema of a Class> ===


 <Class Name>

     a_tbl

 <Attributes>

     name                 CHARACTER VARYING(1073741823)
     phone                CHARACTER VARYING(13) DEFAULT '000-0000-0000'
     age                  INTEGER
     id                   INTEGER AUTO_INCREMENT  NOT NULL

 <Constraints>

     UNIQUE u_a_tbl_id ON a_tbl (id)
ALTER TABLE a_tbl ALTER COLUMN name SET DEFAULT '';
ALTER TABLE a_tbl ALTER COLUMN phone SET DEFAULT '111-1111';
csql> ;schema a_tbl

=== <Help: Schema of a Class> ===


 <Class Name>

     a_tbl

 <Attributes>

     name                 CHARACTER VARYING(1073741823) DEFAULT ''
     phone                CHARACTER VARYING(13) DEFAULT '111-1111'
     age                  INTEGER
     id                   INTEGER AUTO_INCREMENT  NOT NULL

 <Constraints>

     UNIQUE u_a_tbl_id ON a_tbl (id)
AUTO_INCREMENT Clause

The AUTO_INCREMENT clause can change the initial value of the increment value that is currently defined. However, there should be only one AUTO_INCREMENT column defined.

ALTER TABLE table_name AUTO_INCREMENT = initial_value ;
  • table_name : Table name
  • initial_value : Initial value to alter
CREATE TABLE t (i int AUTO_INCREMENT);
ALTER TABLE t AUTO_INCREMENT = 5;

CREATE TABLE t (i int AUTO_INCREMENT, j int AUTO_INCREMENT);

-- when 2 AUTO_INCREMENT constraints are defined on one table, below query returns an error.
ALTER TABLE t AUTO_INCREMENT = 5;
ERROR: To avoid ambiguity, the AUTO_INCREMENT table option requires the table to have exactly one AUTO_INCREMENT column and no seed/increment specification.

Warning

You must be careful not to violate constraints (such as a PRIMARY KEY or UNIQUE) due to changing the initial value of AUTO_INCREMENT.

Note

If you change the type of AUTO_INCREMENT column, the maximum value is changed, too. For example, if you change INT to BIGINT, the maximum value of AUTO_INCREMENT is changed from the maximum INT into the maximum BIGINT.

CHANGE/MODIFY Clauses

The CHANGE clause changes column name, type, size, and attribute. If the existing column name and a new column name are the same, types, size, and attribute will be changed.

The MODIFY clause can modify type, size, and attribute of a column but cannot change its name.

If you set the type, size, and attribute to apply to a new column with the CHANGE clause or the MODIFY clause, the attribute that is currently defined will not be passed to the attribute of the new column.

When you change data types using the CHANGE clause or the MODIFY clause, the data can be modified. For example, if you shorten the length of a column, the character string may be truncated.

Warning

  • ALTER TABLE table_name CHANGE column_name DEFAULT default_value syntax supported in CUBRID 2008 R3.1 or earlier version is no longer supported.
  • When converting a number type to character type, if alter_table_change_type_strict=no and the length of the string is shorter than that of the number, the string is truncated and saved according to the length of the converted character type. If alter_table_change_type_strict=yes, it returns an error.
  • If the column attributes like a type, a collation, etc. are changed, the changed attributes are not applied into the view created with the table before the change. Therefore, if you change the attributes of a table, it is recommended to recreate the related views.
ALTER [/*+ SKIP_UPDATE_NULL */] TABLE tbl_name <table_options> ;

    <table_options> ::=
        <table_option>[, <table_option>, ...]

        <table_option> ::=
            CHANGE [COLUMN | CLASS ATTRIBUTE] old_col_name new_col_name <column_definition>
                     [FIRST | AFTER col_name]
          | MODIFY [COLUMN | CLASS ATTRIBUTE] col_name <column_definition>
                     [FIRST | AFTER col_name]
  • tbl_name: specifies the name of the table including the column to change.
  • old_col_name: specifies the existing column name.
  • new_col_name: specifies the column name to change
  • <column_definition>: specifies the type, the size, the attribute, and the comment of the column to be changed.
  • col_name: specifies the location where the column to change exists.
  • SKIP_UPDATE_NULL: If this hint is added, CUBRID does not check the previous NULLs even if NOT NULL constraint is added. See SKIP_UPDATE_NULL.
CREATE TABLE t1 (a INTEGER);

-- changing column a's name into a1
ALTER TABLE t1 CHANGE a a1 INTEGER;

-- changing column a1's constraint
ALTER TABLE t1 CHANGE a1 a1 INTEGER NOT NULL;
---- or
ALTER TABLE t1 MODIFY a1 INTEGER NOT NULL;

-- changing column col1's type - "DEFAULT 1" constraint is removed.
CREATE TABLE t1 (col1 INT DEFAULT 1);
ALTER TABLE t1 MODIFY col1 BIGINT;

-- changing column col1's type - "DEFAULT 1" constraint is kept.
CREATE TABLE t1 (col1 INT DEFAULT 1, b VARCHAR(10));
ALTER TABLE t1 MODIFY col1 BIGINT DEFAULT 1;

-- changing column b's size
ALTER TABLE t1 MODIFY b VARCHAR(20);

-- changing the name and position of a column
CREATE TABLE t1 (i1 INT, i2 INT);
INSERT INTO t1 VALUES (1,11), (2,22), (3,33);

SELECT * FROM t1 ORDER BY 1;
            i1           i2
==========================
             1           11
             2           22
             3           33
ALTER TABLE t1 CHANGE i2 i0 INTEGER FIRST;
SELECT * FROM t1 ORDER BY 1;
            i0           i1
==========================
            11            1
            22            2
            33            3
-- adding NOT NULL constraint (strict)
SET SYSTEM PARAMETERS 'alter_table_change_type_strict=yes';

CREATE TABLE t1 (i INT);
INSERT INTO t1 VALUES (11), (NULL), (22);

ALTER TABLE t1 CHANGE i i1 INTEGER NOT NULL;
ERROR: Cannot add NOT NULL constraint for attribute "i1": there are existing NULL values for this attribute.
-- adding NOT NULL constraint
SET SYSTEM PARAMETERS 'alter_table_change_type_strict=no';

CREATE TABLE t1 (i INT);
INSERT INTO t1 VALUES (11), (NULL), (22);

ALTER TABLE t1 CHANGE i i1 INTEGER NOT NULL;

SELECT * FROM t1;
           i1
=============
           22
            0
           11
-- change the column's data type (no errors)

CREATE TABLE t1 (i1 INT);
INSERT INTO t1 VALUES (1), (-2147483648), (2147483647);

ALTER TABLE t1 CHANGE i1 s1 CHAR(11);
SELECT * FROM t1;
  s1
======================
  '2147483647 '
  '-2147483648'
  '1          '
-- change the column's data type (errors), strict mode
SET SYSTEM PARAMETERS 'alter_table_change_type_strict=yes';

CREATE TABLE t1 (i1 INT);
INSERT INTO t1 VALUES (1), (-2147483648), (2147483647);

ALTER TABLE t1 CHANGE i1 s1 CHAR(4);
ERROR: ALTER TABLE .. CHANGE : changing to new domain : cast failed, current configuration doesn't allow truncation or overflow.
-- change the column's data type (errors)
SET SYSTEM PARAMETERS 'alter_table_change_type_strict=no';

CREATE TABLE t1 (i1 INT);
INSERT INTO t1 VALUES (1), (-2147483648), (2147483647);

ALTER TABLE t1 CHANGE i1 s1 CHAR(4);
SELECT * FROM t1;
-- hard default values have been placed instead of signaling overflow

  s1
======================
  '1   '
  '-214'
  '2147'

Note

When you change NULL constraint into NOT NULL, it takes a long time by the time updating values into hard default; to resolve this problem, CUBRID can skip updating values which already exists by using SKIP_UPDATE_NULL. However, you should consider that NULL values which do not match with the NOT NULL constraints, can exists.

ALTER /*+ SKIP_UPDATE_NULL */ TABLE foo MODIFY col INT NOT NULL;
Changes of Table Attributes based on Changes of Column Type
  • Type Change : If the value of the system parameter alter_table_change_type_strict is set to no, then changing values to other types is allowed, but if it is set to yes then changing is not allowed. The default value of the parameter is no. You can change values to all types allowed by the CAST operator. Changing object types is allowed only by the upper classes (tables) of the objects.
  • NOT NULL
    • If the NOT NULL constraint is not specified, it will be removed from a new table even though it is present in the existing table.
    • If the NOT NULL constraint is specified in the column to change, the result varies depending on the configuration of the system parameter, alter_table_change_type_strict.
      • If alter_table_change_type_strict is set to yes, the column values will be checked. If NULL exists, an error will occur, and the change will not be executed.
      • If the alter_table_change_type_strict is set to no, every existing NULL value will be changed to a hard default value of the type to change.
  • DEFAULT : If the DEFAULT attribute is not specified in the column to change, it will be removed from a new table even though the attribute is present in the existing table.
  • AUTO_INCREMENT : If the AUTO_INCREMENT attribute is not specified in the column to change, it will be removed from a new table even though the attribute is present in the existing table.
  • FOREIGN KEY : You cannot change the column with the foreign key constraint that is referred to or refers to.
  • Single Column PRIMARY KEY
    • If the PRIMARY KEY constraint is specified in the column to change, a PRIMARY KEY is re-created only in which a PRIMARY KEY constraint exists in the existing column and the type is upgraded.
    • If the PRIMARY KEY constraint is specified in the column to change but doesn't exist in the existing column, a PRIMARY KEY will be created.
    • If a PRIMARY KEY constraint exists but is not specified in the column to change, the PRIMARY KEY will be maintained.
  • Multicolumn PRIMARY KEY: If the PRIMARY KEY constraint is specified and the type is upgraded, a PRIMARY KEY will be re-created.
  • Single Column UNIQUE KEY
    • If the type is upgraded, a UNIQUE KEY will be re-created.
    • If a UNIQUE KEY exists in the existing column and it is not specified in the column to change, it will be maintained.
    • If a UNIQUE KEY exists in the existing column to change, it will be created.
  • Multicolumn UNIQUE KEY: If the column type is changed, an index will be re-created.
  • Column with a Non-unique Index : If the column type is changed, an index will be re-created.
  • Partition Column: If a table is partitioned by a column, the column cannot be changed. Partitions cannot be added.
  • Column with a Class Hierarchy : You can only change the tables that do not have a lower class. You cannot change the lower class that inherits from an upper class. You cannot change the inherited attributes.
  • Trigger and View : You must redefine triggers and views directly because they are not changed according to the definition of the column to change.
  • Column Sequence : You can change the sequence of columns.
  • Name Change : You can change names as long as they do not conflict.
Changes of Values based on Changes of Column Type

The alter_table_change_type_strict parameter determines whether the value conversion is allowed according to the type change. If the value is no, it can be changed when you change a column type or add a NOT NULL constraint. The default value is no.

When the value of the parameter, alter_table_change_type_strict is no, it will operate depending on the conditions as follows:

  • Overflow occurred while converting numbers or character strings to Numbers: It is determined based on symbol of the result type. If it is negative value, it is specified as a minimum value or positive value, specified as the maximum value and a warning message for records where overflow occurred is recorded in the log. For strings, it will follow the rules stated above after it is converted to DOUBLE type.
  • Character strings to convert to shorter ones: The record will be updated to the hard default value of the type that is defined and the warning message will be recorded in a log.
  • Conversion failure due to other reasons: The record will be updated to the hard default value of the type that is defined and the warning message will be recorded in a log.

If the value of the alter_table_change_type_strict parameter is yes, an error message will be displayed and the changes will be rolled back.

The ALTER CHANGE statement checks the possibility of type conversion before updating a record but the type conversion of specific values may fail. For example, if the value format is not correct when you convert VARCHAR to DATE, the conversion may fail. In this case, the hard default value of the DATE type will be assigned.

The hard default value is a value that will be used when you add columns with the ALTER TABLE ... ADD COLUMN statement, add or change by converting types with the ALTER TABLE ... CHANGE/MODIFY statement. The operation will vary depending on the system parameter, add_column_update_hard_default in the ADD COLUMN statement.

Hard Default Value by Type

Type Existence of Hard Default Value Hard Default Value
INTEGER Yes 0
FLOAT Yes 0
DOUBLE Yes 0
SMALLINT Yes 0
DATE Yes date'01/01/0001'
TIME Yes time'00:00'
DATETIME Yes datetime'01/01/0001 00:00'
TIMESTAMP Yes timestamp'00:00:01 AM 01/01/1970' (GMT)
NUMERIC Yes 0
CHAR Yes ''
VARCHAR Yes ''
SET Yes {}
MULTISET Yes {}
SEQUENCE Yes {}
BIGINT Yes 0
BIT NO  
VARBIT No  
OBJECT No  
BLOB No  
CLOB No  
Column's COMMENT

A column's comment is specified in <column_definition>, which is located at the end of ADD/MODIFY/CHANGE syntax. To see the meaning of <column_definition>, refer to CREATE TABLE syntax on the above.

The below is a syntax to show a column's comment.

SHOW CREATE TABLE table_name;

SELECT attr_name, class_name, comment
FROM db_attribute WHERE class_name ='classname';

SHOW FULL COLUMNS FROM table_name;

You can see this comment with the ";sc table_name" command in the CSQL interpreter.

$ csql -u dba demodb

csql> ;sc table_name
RENAME COLUMN Clause

You can change the name of the column by using the RENAME COLUMN clause.

ALTER [ TABLE | CLASS | VCLASS | VIEW ] table_name
RENAME [ COLUMN | ATTRIBUTE ] old_column_name { AS | TO } new_column_name ;
  • table_name : Specifies the name of a table that has a column to be renamed.
  • old_column_name : Specifies the name of a column.
  • new_column_name : Specifies a new column name after the AS keyword(maximum: 254 bytes).
CREATE TABLE a_tbl (id INT, name VARCHAR(50));
ALTER TABLE a_tbl RENAME COLUMN name AS name1;
DROP COLUMN Clause

You can delete a column in a table by using the DROP COLUMN clause. You can specify multiple columns to delete simultaneously by separating them with commas (,).

ALTER [TABLE | CLASS | VCLASS | VIEW] table_name
DROP [COLUMN | ATTRIBUTE] column_name, ... ;
  • table_name : Specifies the name of a table that has a column to be deleted.
  • column_ name : Specifies the name of a column to be deleted. Multiple columns can be specified by separating them with commas (,).
ALTER TABLE a_tbl DROP COLUMN age1,age2,age3;
DROP CONSTRAINT Clause

You can drop the constraints pre-defined for the table, such as UNIQUE, PRIMARY KEY and FOREIGN KEY by using the DROP CONSTRAINT clause. In this case, you must specify a constraint name. You can check these names by using the CSQL command (;schema table_name).

ALTER [TABLE | CLASS] table_name
DROP CONSTRAINT constraint_name ;
  • table_name : Specifies the name of a table that has a constraint to be dropped.
  • constraint_name : Specifies the name of a constraint to be dropped.
CREATE TABLE a_tbl (
  id INT NOT NULL DEFAULT 0 PRIMARY KEY,
  phone VARCHAR(10)
);

CREATE TABLE b_tbl (
  ID INT NOT NULL,
  name VARCHAR (10) NOT NULL,
  CONSTRAINT u_name UNIQUE (name),
  CONSTRAINT pk_id PRIMARY KEY (id),
  CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES a_tbl (id)
  ON DELETE CASCADE ON UPDATE RESTRICT
);

ALTER TABLE b_tbl DROP CONSTRAINT pk_id;
ALTER TABLE b_tbl DROP CONSTRAINT fk_id;
ALTER TABLE b_tbl DROP CONSTRAINT u_name;
DROP INDEX Clause

You can delete an index defined for a column by using the DROP INDEX clause. A unique index can be dropped with a DROP CONSTRAINT clause.

ALTER [TABLE | CLASS] table_name DROP INDEX index_name ;
  • table_name : Specifies the name of a table of which constraints will be deleted.
  • index_name : Specifies the name of an index to be deleted.
ALTER TABLE a_tbl DROP INDEX i_a_tbl_age;
DROP PRIMARY KEY Clause

You can delete a primary key constraint defined for a table by using the DROP PRIMARY KEY clause. You do have to specify the name of the primary key constraint because only one primary key can be defined by table.

ALTER [TABLE | CLASS] table_name DROP PRIMARY KEY ;
  • table_name : Specifies the name of a table that has a primary key constraint to be deleted.
ALTER TABLE a_tbl DROP PRIMARY KEY;
DROP FOREIGN KEY Clause

You can drop a foreign key constraint defined for a table using the DROP FOREIGN KEY clause.

ALTER [TABLE | CLASS] table_name DROP FOREIGN KEY constraint_name ;
  • table_name : Specifies the name of a table whose constraint is to be deleted.
  • constraint_name : Specifies the name of foreign key constraint to be deleted.
ALTER TABLE b_tbl ADD CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES a_tbl (id);
ALTER TABLE b_tbl DROP FOREIGN KEY fk_id;
DROP TABLE

You can drop an existing table by the DROP statement. Multiple tables can be dropped with a single DROP statement. All rows of table are also dropped. If you also specify IF EXISTS clause, no error will be happened even if a target table does not exist.

DROP [TABLE | CLASS] [IF EXISTS] <table_specification_comma_list> [CASCADE CONSTRAINTS] ;

    <table_specification_comma_list> ::=
        <single_table_spec> | (<table_specification_comma_list>)

        <single_table_spec> ::=
            |[ONLY] table_name
            | ALL table_name [( EXCEPT table_name, ... )]
  • table_name : Specifies the name of the table to be dropped. You can delete multiple tables simultaneously by separating them with commas.
  • If a super class name is specified after the ONLY keyword, only the super class, not the sub classes inheriting from it, is deleted. If a super class name is specified after the ALL keyword, the super classes as well as the sub classes inheriting from it are all deleted. You can specify the list of sub classes not to be deleted after the EXCEPT keyword.
  • If sub classes that inherit from the super class specified after the ALL keyword are specified after the EXCEPT keyword, they are not deleted.
  • Specifies the list of subclasses which are not to be deleted after the EXCEPT keyword.
  • CASCADE CONSTRAINTS: The table is dropped and also forein keys of other tables which refer this table are dropped.
CREATE TABLE b_tbl (i INT);
CREATE TABLE a_tbl (i INT);

-- DROP TABLE IF EXISTS
DROP TABLE IF EXISTS b_tbl, a_tbl;

SELECT * FROM a_tbl;
ERROR: Unknown class "a_tbl".
  • If CASCADE CONSTRAINTS is specified, the specified table is dropped even if some tables refer the dropping table's primary key; foreign keys of other tables which refer this table are also dropped. However, the data of tables which are referred are not deleted.

The below shows to drop a_parent table which b_child table refers. A foreign key of b_child table also dropped, and the data of b_child table are kept.

CREATE TABLE a_parent (
    id INTEGER PRIMARY KEY,
    name VARCHAR(10)
);
CREATE TABLE b_child (
    id INTEGER PRIMARY KEY,
    parent_id INTEGER,
    CONSTRAINT fk_parent_id FOREIGN KEY(parent_id) REFERENCES a_parent(id) ON DELETE CASCADE ON UPDATE RESTRICT
);

DROP TABLE a_parent CASCADE CONSTRAINTS;
RENAME TABLE

You can change the name of a table by using the RENAME TABLE statement and specify a list of the table name to change the names of multiple tables.

RENAME  [TABLE | CLASS] old_table_name {AS | TO} new_table_name [, old_table_name {AS | TO} new_table_name, ...] ;
  • old_table_name : Specifies the old table name to be renamed.
  • new_table_name : Specifies a new table name(maximum: 254 bytes).
RENAME TABLE a_tbl AS aa_tbl;
RENAME TABLE aa_tbl TO a1_tbl, b_tbl TO b1_tbl;

Note

The table name can be changed only by the table owner, DBA and DBA members. The other users must be granted to change the name by the owner or DBA (see GRANT for details about authorization).

CREATE INDEX

Creates an index to a specified table by using the CREATE INDEX statement. Regarding writing index name, see Identifier.

For how to use indexes on the SELECT statement like Using SQL Hint, Descending Index, Covering Index, Index Skip Scan, ORDER BY Optimization and GROUP BY Optimization, and how to create Filtered Index and Function-based Index, see Updating Statistics.

CREATE [UNIQUE] INDEX index_name ON table_name <index_col_desc> ;

    <index_col_desc> ::=
        { ( column_name [ASC | DESC] [ {, column_name [ASC | DESC]} ...] ) [ WHERE <filter_predicate> ] |
        (function_name (argument_list) ) }
            [COMMENT 'index_comment_string']
  • UNIQUE: creates an index with unique values.
  • index_name: specifies the name of the index to be created. The index name must be unique in the table.
  • table_name: specifies the name of the table where the index is to be created.
  • column_name: specifies the name of the column where the index is to be applied. To create a composite index, specify two or more column names.
  • ASC | DESC: specifies the sorting order of columns.
  • <filter_predicate>: defines the conditions to create filtered indexes. When there are several comparison conditions between a column and a constant, filtering is available only when the conditions are connected by using AND. Regarding this, definitely watch Filtered Index.
  • function_name (argument_list): Defines the conditions to create function-based indexes. Regarding this, definitely watch Function-based Index.
  • index_comment_string: specifies a comment of an index.

Note

  • From CUBRID 9.0, the index name should not be omitted.
  • Prefix index feature is deprecated, so it is not recommended anymore.
  • The session and server timezone (Timezone Parameter) should not be changed if database contains indexes or function index on columns of type TIMESTAMP, TIMESTAMP WITH LOCAL TIME ZONE or DATETIME WITH LOCAL TIME ZONE.
  • The leap second support parameter (Timezone Parameter) should not be changed if database contains indexes or function index on columns of type TIMESTAMP or TIMESTAMP WITH LOCAL TIME ZONE.

The following example shows how to create a descending index.

CREATE INDEX gold_index ON participant(gold DESC);

The following example shows how to create a multiple column index.

CREATE INDEX name_nation_idx ON athlete(name, nation_code) COMMENT 'index comment';
COMMENT of Index

You can write a comment of an index as following.

CREATE TABLE tbl (a int default 0, b int, c int);

CREATE INDEX i_tbl_b on tbl (b) COMMENT 'index comment for i_tbl_b';

CREATE TABLE tbl2 (a INT, index i_tbl_a (a) COMMENT 'index comment', b INT);

ALTER TABLE tbl2 ADD INDEX i_tbl2_b (b) COMMENT 'index comment b';

A specified comment of an indexe can be shown by running these statements.

SHOW CREATE TABLE table_name;
SELECT index_name, class_name, comment from db_index where class_name ='classname';
SHOW INDEX FROM table_name;

Or you can see the index comments with ;sc command in the CSQL interpreter.

$ csql -u dba demodb

csql> ;sc tbl
ALTER INDEX

The ALTER INDEX statement rebuilds an index or adds/changes the comment of an index. Rebuilding an index is a job which drops and recreates an index.

The following is a syntax of rebuilding an index.

ALTER INDEX index_name ON table_name REBUILD;
  • index_name: specifies the name of the index to be recreated. The index name must be unique in the table.
  • table_name: specifies the name of the table where the index is recreated.
  • REBUILD: recreate an index with the same structure as the one already created.
  • index_comment_string: specifies a comment of an index.

Note

  • From CUBRID 9.0, the index name should not be omitted.
  • From CUBRID 10.0, table name should not be omitted.
  • From CUBRID 10.0, even if you add column names at the end of a table name, these will be ignored and recreated with the same columns with the previous index.
  • Prefix index feature is deprecated, so it is not recommended anymore.

The following is an example of recreating index.

CREATE INDEX i_game_medal ON game(medal);
ALTER INDEX i_game_medal ON game COMMENT 'rebuild index comment' REBUILD ;

If you want to add or change a comment of the index without rebuilding an index, add a COMMENT syntax and remove a REBUILD keyword as following.

ALTER INDEX index_name ON table_name COMMENT 'index_comment_string' ;

The below is a syntax to only add or change a comment without rebuilding an index.

ALTER INDEX i_game_medal ON game COMMENT 'change index comment' ;

The following is a syntax of renaming an index.

ALTER INDEX old_index_name ON table_name RENAME TO new_index_name [COMMENT 'index_comment_string'] ;
DROP INDEX

Use the DROP INDEX statement to drop an index. An index also can be dropped with DROP CONSTRAINT clause.

DROP INDEX index_name ON table_name ;
  • index_name: specifies the name of the index to be dropped.
  • table_name: specifies the name of the table whose index is dropped.

Warning

From the CUBRID 10.0 version, table name cannot be omitted.

The following is an example of dropping an index:

DROP INDEX i_game_medal ON game;
CREATE VIEW

A view is a virtual table that does not exist physically. You can create a view by using an existing table or a query. VIEW and VCLASS are used interchangeably.

Use CREATE VIEW statement to create a view. Regarding writing view name, see Identifier.

CREATE [OR REPLACE] {VIEW | VCLASS} view_name
[<subclass_definition>]
[(view_column_name [COMMENT 'column_comment_string'], ...)]
[INHERIT <resolution>, ...]
[AS <select_statement>]
[WITH CHECK OPTION]
[COMMENT [=] 'view_comment_string'];

    <subclass_definition> ::= {UNDER | AS SUBCLASS OF} table_name, ...
    <resolution> ::= [CLASS | TABLE] {column_name} OF superclass_name [AS alias]
  • OR REPLACE: If the keyword OR REPLACE is specified after CREATE, the existing view is replaced by a new one without displaying any error message, even when the view_name overlaps with the existing view name.
  • view_name: specifies the name of a view to be created. It must be unique in a database.
  • view_column_name: defines the column of a view.
  • AS <select_statement>: A valid SELECT statement must be specified. A view is created based on this.
  • WITH CHECK OPTION: If this option is specified, the update or insert operation is possible only when the condition specified in the WHERE clause of the <select_statement> is satisfied. Therefore, this option is used to disallow the update of a virtual table that violates the condition.
  • view_comment_string: specifies a view's comment.
  • column_comment_string: specofies a column's comment.
CREATE TABLE a_tbl (
    id INT NOT NULL,
    phone VARCHAR(10)
);
INSERT INTO a_tbl VALUES(1,'111-1111'), (2,'222-2222'), (3, '333-3333'), (4, NULL), (5, NULL);

--creating a new view based on AS select_statement from a_tbl
CREATE VIEW b_view AS SELECT * FROM a_tbl WHERE phone IS NOT NULL WITH CHECK OPTION;
SELECT * FROM b_view;
           id  phone
===================================
            1  '111-1111'
            2  '222-2222'
            3  '333-3333'
--WITH CHECK OPTION doesn't allow updating column value which violates WHERE clause
UPDATE b_view SET phone=NULL;
ERROR: Check option exception on view b_view.

The below updates the old view's definition, In addition, this adds a view's comment.

--creating view which name is as same as existing view name
CREATE OR REPLACE VIEW b_view AS SELECT * FROM a_tbl ORDER BY id DESC COMMENT 'changed view';

--the existing view has been replaced as a new view by OR REPLACE keyword
SELECT * FROM b_view;
           id  phone
===================================
            5  NULL
            4  NULL
            3  '333-3333'
            2  '222-2222'
            1  '111-1111'

The below adds a comment to a view's columns.

CREATE OR REPLACE VIEW b_view(a COMMENT 'column id', b COMMENT 'column phone') AS SELECT * FROM a_tbl ORDER BY id DESC;
Condition for Creating Updatable VIEW

A virtual table is updatable if it satisfies the following conditions:

  • The FROM clause must include the updatable table or view only.

    In versions lower than CUBRID 9.0, only one updatable table can be included to the FROM clause it requires. However, two tables in parentheses like FROM (class_x, class_y) can be updated since the two were expressed as one table. In version of CUBRID 9.0 or higher, more than one updatable table is allowed. The FROM clause must include only one table or updatable view. However, two tables included in parentheses as in FROM (class_x, class_y) can be updated because they represent one table.

  • A JOIN syntax can be included.

    Note

    In versions lower than CUBRID 10.0, you cannot update a view which is created with a JOIN syntax.

  • The DISTINCT or UNIQUE statement should not be included.

  • The GROUP BY... HAVING statement should not be included.

  • Aggregate functions such as SUM or AVG should not be included.

  • The entire query must consist of queries that can be updated by UNION ALL, not by UNION. However, the table should exist only in one of the queries that constitute UNION ALL.

  • If a record is inserted into a view created by using the UNION ALL statement, the system determines into which table the record will be inserted. This cannot be done by the user. To control this, the user must manually insert the row or create a separate view for insertion.

Even when all rules above are satisfied, columns that contains following contents cannot be updated.

  • Path expressions (example: tbl_name.col_name)
  • Numeric type column that includes an arithmetic operator

Even though the column defined in the view is updatable, a view can be updated only when an appropriate update authorization is granted on the table included in the FROM clause. Also there must be an access authorization to a view. The way to grant an access authorization to a view is the same to grant an access authorization to a table. For details on granting authorization, see GRANT.

View's COMMENT

You can specify a view's comment as follows.

CREATE OR REPLACE VIEW b_view AS SELECT * FROM a_tbl ORDER BY id DESC COMMENT 'changed view';

You can see the specified comment of a view by running this syntax.

SHOW CREATE VIEW view_name;
SELECT vclass_name, comment from db_vclass;

Or you can see the view's comment with ;sc command which displays the schema in the CSQL interpreter.

$ csql -u dba demodb

csql> ;sc b_view

Also, you can add a comment for each column of the view.

CREATE OR REPLACE VIEW b_view (a COMMENT 'a comment', b COMMENT 'b comment')
AS SELECT * FROM a_tbl ORDER BY id DESC COMMENT 'view comment';

To see how to change a comment of a view, refer to ALTER VIEW syntax on the below.

ALTER VIEW
ADD QUERY Clause

You can add a new query to a query specification by using the ADD QUERY clause of the ALTER VIEW statement. 1 is assigned to the query defined when a virtual table was created, and 2 is assigned to the query added by the ADD QUERY clause.

ALTER [VIEW | VCLASS] view_name
ADD QUERY <select_statement>
[INHERIT <resolution> , ...] ;

    <resolution> ::= {column_name} OF superclass_name [AS alias]
  • view_name: specifies the name of a view where the query to be added.
  • <select_statement>: specifies the query to be added.
SELECT * FROM b_view;
           id  phone
===================================
            1  '111-1111'
            2  '222-2222'
            3  '333-3333'
            4  NULL
            5  NULL
ALTER VIEW b_view ADD QUERY SELECT * FROM a_tbl WHERE id IN (1,2);
SELECT * FROM b_view;
           id  phone
===================================
            1  '111-1111'
            2  '222-2222'
            3  '333-3333'
            4  NULL
            5  NULL
            1  '111-1111'
            2  '222-2222'
AS SELECT Clause

You can change the SELECT query defined in the virtual table by using the AS SELECT clause in the ALTER VIEW statement. This function is working like the CREATE OR REPLACE statement. You can also change the query by specifying the query number 1 in the CHANGE QUERY clause of the ALTER VIEW statement.

ALTER [VIEW | VCLASS] view_name AS <select_statement> ;
  • view_name: specifies the name of a view to be modified.
  • <select_statement>: specifies the new query statement to replace the SELECT statement defined when a view is created.
ALTER VIEW b_view AS SELECT * FROM a_tbl WHERE phone IS NOT NULL;
SELECT * FROM b_view;
           id  phone
===================================
            1  '111-1111'
            2  '222-2222'
            3  '333-3333'
CHANGE QUERY Clause

You can change the query defined in the query specification by using the CHANGE QUERY clause reserved word of the ALTER VIEW statement.

ALTER [VIEW | VCLASS] view_name
CHANGE QUERY [integer] <select_statement> ;
  • view_name: specifies the name of a view to be modified.
  • integer: specifies the number value of the query to be modified. The default value is 1.
  • <select_statement>: specifies the new query statement to replace the query whose query number is integer.
--adding select_statement which query number is 2 and 3 for each
ALTER VIEW b_view ADD QUERY SELECT * FROM a_tbl WHERE id IN (1,2);
ALTER VIEW b_view ADD QUERY SELECT * FROM a_tbl WHERE id = 3;
SELECT * FROM b_view;
           id  phone
===================================
            1  '111-1111'
            2  '222-2222'
            3  '333-3333'
            4  NULL
            5  NULL
            1  '111-1111'
            2  '222-2222'
            3  '333-3333'
--altering view changing query number 2
ALTER VIEW b_view CHANGE QUERY 2 SELECT * FROM a_tbl WHERE phone IS NULL;
SELECT * FROM b_view;
           id  phone
===================================
            1  '111-1111'
            2  '222-2222'
            3  '333-3333'
            4  NULL
            5  NULL
            4  NULL
            5  NULL
            3  '333-3333'
DROP QUERY Clause

You can drop a query defined in the query specification by using the DROP QUERY of the ALTER VIEW statement.

ALTER VIEW b_view DROP QUERY 2,3;
SELECT * FROM b_view;
           id  phone
===================================
            1  '111-1111'
            2  '222-2222'
            3  '333-3333'
            4  NULL
            5  NULL
COMMENT Clause

You can change a view's comment with COMMENT clause of ALTER VIEW syntax.

ALTER [VIEW | VCLASS] view_name COMMENT [=] 'view_comment';
ALTER VIEW b_view COMMENT = 'changed view comment';
DROP VIEW

You can drop a view by using the DROP VIEW clause. The way to drop a view is the same as to drop a regular table. If you also specify IF EXISTS clause, no error will be happened even if a target view does not exist.

DROP [VIEW | VCLASS] [IF EXISTS] view_name [{ ,view_name , ... }] ;
  • view_name: specifies the name of a view to be dropped.
DROP VIEW b_view;
RENAME VIEW

You can change the view name by using the RENAME VIEW statement.

RENAME [VIEW | VCLASS] old_view_name {AS | TO} new_view_name[, old_view_name {AS | TO} new_view_name, ...] ;
  • old_view_name: specifies the name of a view to be modified.
  • new_view_name: specifies the new name of a view.

The following example shows how to rename a view name to game_2004.

RENAME VIEW game_2004 AS info_2004;
CREATE SERIAL

Serial is an object that creates a unique sequence number, and has the following characteristics.

  • The serial is useful in creating a unique sequence number in multi-user environment.
  • Generated serial numbers are not related with table so, you can use the same serial in multiple tables.
  • All users including PUBLIC can create a serial object. Once it is created, all users can get the number by using CURRENT_VALUE and NEXT_VALUE.
  • Only owner of a created serial object and DBA can update or delete a serial object. If an owner is PUBLIC, all users can update or delete it.

You can create a serial object in the database by using the CREATE SERIAL statement. Regarding writing serial name, Identifier.

CREATE SERIAL serial_name
[START WITH initial]
[INCREMENT BY interval]
[MINVALUE min | NOMINVALUE]
[MAXVALUE max | NOMAXVALUE]
[CACHE cached_num | NOCACHE]
[COMMENT 'comment_string'];
  • serial_identifier: specifies the name of the serial to be generated(maximum: 254 bytes).
  • START WITH initial: Specifies the initial value of serial. The range of this value is between -1,000,000,000,000,000,000,000,000,000,000,000,000(-10^36) and 9,999,999,999,999,999,999,999,999,999,999,999,999(10^37-1). The default value of ascending serial is 1 and that of descending serial is -1.
  • INCREMENT BY interval: Specifies the increment of the serial. You can specify any integer between -9,999,999,999,999,999,999,999,999,999,999,999,999(-10^37+1) and 9,999,999,999,999,999,999,999,999,999,999,999,999(10^37-1) except zero at interval. The absolute value of the interval must be smaller than the difference between MAXVALUE and MINVALUE. If a negative number is specified, the serial is in descending order otherwise, it is in ascending order. The default value is 1.
  • MINVALUE: Specifies the minimum value of the serial. The range of this value is between -1,000,000,000,000,000,000,000,000,000,000,000,000(-10^36) and 9,999,999,999,999,999,999,999,999,999,999,999,999(10^37-1). MINVALUE must be smaller than or equal to the initial value and smaller than the maximum value.
  • NOMINVALUE: 1 is set automatically as a minimum value for the ascending serial, -1,000,000,000,000,000,000,000,000,000,000,000,000(-10^36) for the descending serial.
  • MAXVALUE: Specifies the maximum number of the serial. The range of this value is between -999,999,999,999,999,999,999,999,999,999,999,999(-10^36+1) and 10,000,000,000,000,000,000,000,000,000,000,000,000(10^37). MAXVALUE must be greater than or equal to the initial value and greater than the minimum value.
  • NOMAXVALUE: 10,000,000,000,000,000,000,000,000,000,000,000,000(10^37) is set automatically as a maximum value for the ascending serial, -1 for the descending serial.
  • CYCLE: Specifies that the serial will be generated continuously after reaching the maximum or minimum value. When a serial in ascending order reaches the maximum value, the minimum value is created as the next value; when a serial in descending order reaches the minimum value, the maximum value is created as the next value.
  • NOCYCLE: Specifies that the serial will not be generated anymore after reaching the maximum or minimum value. The default value is NOCYCLE.
  • CACHE: Stores as many serials as the number specified by "cached_num" in the cache to improve the performance of the serials and fetches a serial value when one is requested. If all cached values are used up, as many serials as "cached_num" are fetched again from the disk to the memory. If the database server stops accidently, all cached serial values are deleted. For this reason, the serial values before and after the restart of the database server may be discontinuous. Because the transaction rollback does not affect the cached serial values, the request for the next serial will return the next value of the value used (or fetched) lastly when the transaction is rolled back. The "cached_num" after the CACHE keyword cannot be omitted. If the "cached_num" is equal to or smaller than 1, the serial cache is not applied.
  • NOCACHE: Specifies that the serial cache is not used, and serial value is updated for each time.
  • comment_string: specifies a comment of a serial.
--creating serial with default values
CREATE SERIAL order_no;

--creating serial within a specific range
CREATE SERIAL order_no START WITH 10000 INCREMENT BY 2 MAXVALUE 20000;

--creating serial with specifying the number of cached serial values
CREATE SERIAL order_no START WITH 10000 INCREMENT BY 2 MAXVALUE 20000 CACHE 3;

--selecting serial information from the db_serial class
SELECT * FROM db_serial;
  name            current_val      increment_val         max_val         min_val         cyclic      started       cached_num        att_name
====================================================================================================================================================
'order_no'      10006            2                     20000           10000                0            1                3            NULL

The following example shows how to create the athlete_idx table to store athlete codes and names and then create an instance by using the order_no. NEXT_VALUE increases the serial number and returns its value.

CREATE TABLE athlete_idx( code INT, name VARCHAR(40) );
CREATE SERIAL order_no START WITH 10000 INCREMENT BY 2 MAXVALUE 20000;
INSERT INTO athlete_idx VALUES (order_no.NEXT_VALUE, 'Park');
INSERT INTO athlete_idx VALUES (order_no.NEXT_VALUE, 'Kim');
INSERT INTO athlete_idx VALUES (order_no.NEXT_VALUE, 'Choo');
INSERT INTO athlete_idx VALUES (order_no.CURRENT_VALUE, 'Lee');

SELECT * FROM athlete_idx;
         code  name
===================================
        10000  'Park'
        10002  'Kim'
        10004  'Choo'
        10004  'Lee'
COMMENT of Serial

The below adds a comment when you create a serial.

CREATE SERIAL order_no
START WITH 100 INCREMENT BY 2 MAXVALUE 200
COMMENT 'from 100 to 200 by 2';

To see a comment of the serial, run the below syntax.

SELECT name, comment FROM db_serial;

To change a comment of a serial, see ALTER SERIAL syntax.

ALTER SERIAL

With the ALTER SERIAL statement, you can update the increment of the serial value, set or delete its initial or minimum/maximum values, and set its cycle attribute.

ALTER SERIAL serial_identifier
[INCREMENT BY interval]
[START WITH initial_value]
[MINVALUE min | NOMINVALUE]
[MAXVALUE max | NOMAXVALUE]
[CACHE cached_num | NOCACHE]
[COMMENT 'comment_string'];
  • serial_identifier: specifies the name of the serial to be created(maximum: 254 bytes).
  • INCREMENT BY interval: specifies the increment of the serial. For the interval, you can specify any integer with 38 digits or less except zero. The absolute value of the interval must be smaller than the difference between MAXVALUE and MINVALUE. If a negative number is specified, the serial is in descending order; otherwise, it is in ascending order. The default value is 1.
  • START WITH initial_value: changes the initial value of Serial.
  • MINVALUE: specifies the minimum value of the serial with 38 digits or less. MINVALUE must be smaller than or equal to the initial value and smaller than the maximum value.
  • NOMINVALUE: 1 is set automatically as a minimum value for the ascending serial; -(10) 36 for the descending serial.
  • MAXVALUE: specifies the maximum number of the serial with 38 digits or less. MAXVALUE must be larger than or equal to the initial value and greater than the minimum value.
  • NOMAXVALUE: (10) 37 is set automatically as a maximum value for the ascending serial; -1 for the descending serial.
  • CYCLE: specifies that the serial will be generated continuously after reaching the maximum or minimum value. If the ascending serial reaches the maximum value, the minimum value is generated as the next value. If the descending serial reaches the minimum value, the maximum value is generated as the next value.
  • NOCYCLE: specifies that the serial will not be generated anymore after reaching the maximum or minimum value. The default is NOCYCLE.
  • CACHE: stores as many serials as the number specified by integer in the cache to improve the performance of the serials and fetches a serial value when one is requested. The integer after the CACHE keyword cannot be omitted. If a number equal to or smaller than 1 is specified, the serial cache is not applied.
  • NOCACHE: It does not use the serial cache feature. The serial value is updated every time and a new serial value is fetched from the disk upon each request.
  • comment_string: specifies a comment of a serial.
--altering serial by changing start and incremental values
ALTER SERIAL order_no START WITH 100 MINVALUE 100 INCREMENT BY 2;

--altering serial to operate in cache mode
ALTER SERIAL order_no CACHE 5;

--altering serial to operate in common mode
ALTER SERIAL order_no NOCACHE;

Warning

In CUBRID 2008 R1.x version, the serial value can be modified by updating the db_serial table, a system catalog. However, in CUBRID 2008 R2.0 version or above, the modification of the db_serial table is not allowed but use of the ALTER SERIAL statement is allowed. Therefore, if an ALTER SERIAL statement is included in the data exported (unloaddb) from CUBRID 2008 R2.0 or above, it is not allowed to import (loaddb) the data in CUBRID 2008 R1.x or below.

Warning

When you get the value of NEXT_VALUE after running ALTER SERIAL, in the version lower than CUBRID 9.0, the next value of the initial value was returned. From CUBRID 9.0, the setting value of ALTER_SERIAL is returned.

CREATE SERIAL s1;
SELECT s1.NEXTVAL;

ALTER SERIAL s1 START WITH 10;

SELECT s1.NEXTVAL;
-- From 9.0, above query returns 10
-- In the version less than 9.0, above query returns 11

The below changes the comment of the serial.

ALTER SERIAL order_no COMMENT 'new comment';
DROP SERIAL

With the DROP SERIAL statement, you can drop a serial object from the database. If you also specify IF EXISTS clause, no error will be happened even if a target serial does not exist.

DROP SERIAL [ IF EXISTS ] serial_identifier ;
  • serial_identifier: Specifies the name of the serial to be dropped.

The following example shows how to drop the order_no serial.

DROP SERIAL order_no;
DROP SERIAL IF EXISTS order_no;
Accessing Serial
Pseudocolumns

You can access and update a serial by serial name and a pseudocolumn pair.

serial_identifier.CURRENT_VALUE
serial_identifier.NEXT_VALUE
  • serial_identifier.CURRENT_VALUE: Returns the current serial value.
  • serial_identifier.NEXT_VALUE: Increments the serial value and returns the result.

The following example shows how to create a table athlete_idx where athlete numbers and names are stored and how to create the instances by using a serial order_no.

CREATE TABLE athlete_idx (code INT, name VARCHAR (40));
CREATE SERIAL order_no START WITH 10000 INCREMENT BY 2 MAXVALUE 20000;
INSERT INTO athlete_idx VALUES (order_no.NEXT_VALUE, 'Park');
INSERT INTO athlete_idx VALUES (order_no.NEXT_VALUE, 'Kim');
INSERT INTO athlete_idx VALUES (order_no.NEXT_VALUE, 'Choo');
INSERT INTO athlete_idx VALUES (order_no.NEXT_VALUE, 'Lee');
SELECT * FROM athlete_idx;
         code  name
===================================
        10000  'Park'
        10002  'Kim'
        10004  'Choo'
        10006  'Lee'

Note

When you use a serial for the first time after creating it, NEXT_VALUE returns the initial value. Subsequently, the sum of the current value and the increment are returned.

Functions
SERIAL_CURRENT_VALUE(serial_name)
SERIAL_NEXT_VALUE(serial_name, number)

The Serial function consists of the SERIAL_CURRENT_VALUE and SERIAL_NEXT_VALUE functions.

Parameters:
  • serial_name -- Serial name
  • number -- The number of serials to be obtained
Return type:

NUMERIC(38,0)

The SERIAL_CURRENT_VALUE function returns the current serial value, which is the same value as serial_name .current_value.

This function returns as much added value as interval specified. The serial interval is determined by the value of a CREATE SERIAL ... INCREMENT BY statement. SERIAL_NEXT_VALUE (serial_name, 1) returns the same value as serial_name .next_value.

To get a large amount of serials at once, specify the desired number as an argument to call the SERIAL_NEXT_VALUE function only once; which has an advantage over calling repeatedly serial_name .next_value in terms of performance.

Assume that an application process is trying to get the number of n serials at once. To perform it, call SERIAL_NEXT_VALUE (serial_name, N) one time to store a return value and calculate a serial value between (a serial start value) and (the return value). (Serial value at the point of function call) is equal to the value of (return value) - (desired number of serials) * (serial interval).

For example, if you create a serial starting 101 and increasing by 1 and call SERIAL_NEXT_VALUE (serial_name, 10), it returns 110. The start value at the point is 110-(10-1)*1 = 101. Therefore, 10 serial values such as 101, 102, 103, ... 110 can be used by an application process. If SERIAL_NEXT_VALUE (serial_name, 10) is called in succession, 120 is returned; the start value at this point is 120-(10-1)*1 = 111.

CREATE SERIAL order_no START WITH 101 INCREMENT BY 1 MAXVALUE 20000;
SELECT SERIAL_CURRENT_VALUE(order_no);
101
-- At first, the first serial value starts with the initial serial value, 10000. So the l0'th serial value will be 10009.
SELECT SERIAL_NEXT_VALUE(order_no, 10);
110
SELECT SERIAL_NEXT_VALUE(order_no, 10);
120

Note

If you create a serial and calls the SERIAL_NEXT_VALUE function for the first time, a value of (serial interval) * (desired number of serials - 1) added to the current value is returned. If you call the SERIAL_NEXT_VALUE function in succession, a value of (serial interval) * (desired number of serials) added to the current is returned (see the example above).

Operators and Functions

Logical Operators

For logical operators, boolean expressions or expressions that evaluates to an INTEGER value are specified as operands; TRUE, FALSE or NULL is returned as a result. If the INTEGER value is used, 0 is evaluated to FALSE and the other values are evaluated to TRUE. If a boolean value is used, 1 is evaluated to TRUE and 0 is evaluated to FALSE.

The following table shows the logical operators.

Logical Operators

Logical Operator Description Condition
AND, && If all operands are TRUE, it returns TRUE. a AND b
OR, || If none of operands is NULL and one or more operands are TRUE, it returns TRUE. If pipes_as_concat is no that is a parameter related to SQL statements, a double pipe symbol can be used as OR operator. a OR b
XOR If none of operand is NULL and each of operand has a different value, it returns TRUE. a XOR b
NOT, ! A unary operator. If a operand is FALSE , it returns TRUE. If it is TRUE , returns FALSE. NOT a

Truth Table of Logical Operators

a b a AND b a OR b NOT a a XOR b
TRUE TRUE TRUE TRUE FALSE FALSE
TRUE FALSE FALSE TRUE FALSE TRUE
TRUE NULL NULL TRUE FALSE NULL
FALSE TRUE FALSE TRUE TRUE TRUE
FALSE FALSE FALSE FALSE TRUE FALSE
FALSE NULL FALSE NULL TRUE NULL
Comparison Operators

The comparison operators compare the operand on the left and on the right, and they return 1 or 0. The operands of comparison operations must have the same data type. Therefore, implicit type casting by the system or implicit type casting by the user is required.

Syntax 1

<expression> <comparison_operator> <expression>

    <expression> ::=
        bit_string |
        character_string |
        numeric_value |
        date-time_value |
        collection_value |
        NULL

    <comparison_operator> ::=
        = |
        <=> |
        <> |
        != |
        > |
        < |
        >= |
        <=

Syntax 2

<expression> IS [NOT] <boolean_value>

    <expression> ::=
        bit_string |
        character_string |
        numeric_value |
        date-time_value |
        collection_value |
        NULL

<boolean_value> ::=
    { UNKNOWN | NULL } |
    TRUE |
    FALSE
  • <expression>: Declares an expression to be compared.
    • bit_string: A Boolean operation can be performed on bit strings, and all comparison operators can be used for comparison between bit strings. If you compare two expressions with different lengths, 0s are padded at the end of the shorter one.
    • character_string: When compared by a comparison operator, two character strings must have the same character sets. The comparison is determined by the collation sequence of the character code set. If you compare two character strings with different lengths, blanks are padded at the end of the shorter one before comparison so that they have the same length.
    • numeric_value: The Boolean operator can be performed for all numeric values and any types of comparison operator can be used. When two different numeric types are compared, the system implicitly performs type casting. For example, when an INTEGER value is compared with a DECIMAL value, the system first casts INTEGER to DECIMAL before it performs comparison. When you compare a FLOAT value, you must specify the range instead of an exact value because the processing of FLOAT is dependent on the system.
    • date-time_value: If two date-time values with the same type are compared, the order is determined in time order. That is, when comparing two date-time values, the earlier date is considered to be smaller than the later date. You cannot compare date-time values with different type by using a comparison operator; therefore, you must explicitly convert it. However, comparison operation can be performed between DATE, TIMESTAMP, and DATETIME because they are implicitly converted.
    • collection_value: When comparing two LISTs (SEQUENCE), comparison is performed between the two elements by user-specified order when LIST was created. Comparison including SET and MULTISET is overloaded to an appropriate operator. You can perform comparison operations on SET, MULTISET, LIST, or SEQUENCE by using a containment operator explained later in this chapter. For details, see Containment Operators.
    • NULL: The NULL value is not included in the value range of any data type. Therefore, comparison between NULL values is only allowed to determine if the given value is NULL or not. An implicit type cast does not take place when a NULL value is assigned to a different data type. For example, when an attribute of INTEGER type has a NULL and is compared with a floating point type, the NULL value is not coerced to FLOAT before comparison is made. A comparison operation on the NULL value does not return a result.

The following table shows the comparison operators supported by CUBRID and their return values.

Comparison Operators

Comparison Operator Description Predicate Return Value
= A general equal sign. It compares whether the values of the left and right operands are the same. Returns NULL if one or more operands are NULL. 1=2 1=NULL 0 NULL
<=> A NULL-safe equal sign. It compares whether the values of the left and right operands are the same including NULL. Returns 1 if both operands are NULL. 1<=>2 1<=> NULL 0 0
<>, != The value of left operand is not equal to that of right operand. If any operand value is NULL, NULL is returned. 1<>2 1
> The value of left operand is greater than that of right operand. If any operand value is NULL, NULL is returned. 1>2 0
< The value of left operand is less than that of right operand. If any operand value is NULL, NULL is returned. 1<2 1
>= The value of left operand is greater than or equal to that of right operand. If any operand value is NULL, NULL is returned. 1>=2 0
<= The value of left operand is less than or equal to that of right operand. If any operand value is NULL, NULL is returned. 1<=2 1
IS boolean_value Compares whether the value of the left operand is the same as boolean value of the right. The boolean value may be TRUE, FALSE (or NULL). 1 IS FALSE 0
IS NOT boolean_value Compares whether the value of the left operand is the same as boolean value of the right. The boolean value may be TRUE, FALSE (or NULL). 1 IS NOT FALSE 1

The following are the examples which use comparison operators.

SELECT (1 <> 0); -- 1 is displayed because it is TRUE.
SELECT (1 != 0); -- 1 is displayed because it is TRUE.
SELECT (0.01 = '0.01'); -- An error occurs because a numeric data type is compared with a character string type.
SELECT (1 = NULL); -- NULL is displayed.
SELECT (1 <=> NULL); -- 0 is displayed because it is FALSE.
SELECT (1.000 = 1); -- 1 is displayed because it is TRUE.
SELECT ('cubrid' = 'CUBRID'); -- 0 is displayed because it is case sensitive.
SELECT ('cubrid' = 'cubrid'); -- 1 is displayed because it is TRUE.
SELECT (SYSTIMESTAMP = CAST(SYSDATETIME AS TIMESTAMP)); -- 1 is displayed after casting the type explicitly and then performing comparison operator.
SELECT (SYSTIMESTAMP = SYSDATETIME); --0 is displayed after casting the type implicitly and then performing comparison operator.
SELECT (SYSTIMESTAMP <> NULL); -- NULL is returned without performing comparison operator.
SELECT (SYSTIMESTAMP IS NOT NULL); -- 1 is returned because it is not NULL.
Arithmetic Operators

For arithmetic operators, there are binary operators for addition, subtraction, multiplication, or division, and unary operators to represent whether the number is positive or negative. The unary operators to represent the numbers' positive/negative status have higher priority over the binary operators.

<expression>  <mathematical_operator>  <expression>

    <expression> ::=
        bit_string |
        character_string |
        numeric_value |
        date-time_value |
        collection_value |
        NULL

    <mathematical_operator> ::=
        <set_arithmetic_operator> |
        <arithmetic_operator>

            <arithmetic_operator> ::=
                + |
                - |
                * |
                { / | DIV } |
                { % | MOD }

            <set_arithmetic_operator> ::=
                UNION |
                DIFFERENCE |
                { INTERSECT | INTERSECTION }
  • <expression>: Declares the mathematical operation to be calculated.
  • <mathematical_operator>: A operator that performs an operation the arithmetic and the set operators are applicable.
    • <set_arithmetic_operator>: A set arithmetic operator that performs operations such as union, difference and intersection on collection type operands.
    • <arithmetic_operator>: An operator to perform the four fundamental arithmetic operations.

The following table shows the arithmetic operators supported by CUBRID and their return values.

Arithmetic Operators

Arithmetic Operator | Description Operator Return Value
+ | Addition 1+2 3
- Subtraction 1-2 -1
* Multiplication 1*2 2
/ Division. Returns quotient. 1/2.0 0.500000000
DIV Division. Returns quotient. 1 DIV 2 0
% , MOD Division. Returns quotient. An operator must be an integer type, and it always returns integer. If an operand is real number, the MOD function can be used. 1 % 2 1 MOD 2 1
Arithmetic Operations and Type Casting of Numeric Data Types

All numeric data types can be used for arithmetic operations. The result type of the operation differs depending on the data types of the operands and the type of the operation. The following table shows the result data types of addition/subtraction/multiplication for each operand type.

Result Data Type by Operand Type

  INT NUMERIC FLOAT DOUBLE
INT INT or BIGINT NUMERIC FLOAT DOUBLE
NUMERIC NUMERIC NUMERIC (p and s are also converted) DOUBLE DOUBLE
FLOAT FLOAT DOUBLE FLOAT DOUBLE
DOUBLE DOUBLE DOUBLE DOUBLE DOUBLE

Note that the result type of the operation does not change if all operands are of the same data type but type casting occurs exceptionally in division operations. An error occurs when a denominator, i.e. a divisor, is 0.

The following table shows the total number of digits (p) and the number of digits after the decimal point (s) of the operation results when all operands are of the NUMERIC type.

Result of NUMERIC Type Operation

Operation Maximum Precision Maximum Scale
N(p1, s1) + N(p2, s2) max(p1-s1, p2-s2)+max(s1, s2) +1 max(s1, s2)
N(p1, s1) - N(p2, s2) max(p1-s1, p2-s2)+max(s1, s2) max(s1, s2)
N(p1, s1) * N(p2, s2) p1+p2+1 s1+s2
N(p1, s1) / N(p2, s2) Let Pt = p1+max(s1, s2) + s2 - s1 when s2 > 0 and Pt = p1 in other cases; St = s1 when s1 > s2 and s2 in other cases; | the number of decimal places is min(9-St, 38-Pt) + St when St < 9 and St in other cases. |

Example

--int * int
SELECT 123*123;
      123*123
=============
        15129
-- int * int returns overflow error
SELECT (1234567890123*1234567890123);
ERROR: Data overflow on data type bigint.
-- int * numeric returns numeric type
SELECT (1234567890123*CAST(1234567890123 AS NUMERIC(15,2)));
 (1234567890123* cast(1234567890123 as numeric(15,2)))
======================
  1524157875322755800955129.00
-- int * float returns float type
SELECT (1234567890123*CAST(1234567890123 AS FLOAT));
 (1234567890123* cast(1234567890123 as float))
===============================================
                                  1.524158e+024
-- int * double returns double type
SELECT (1234567890123*CAST(1234567890123 AS DOUBLE));
 (1234567890123* cast(1234567890123 as double))
================================================
                          1.524157875322756e+024
-- numeric * numeric returns numeric type
SELECT (CAST(1234567890123 AS NUMERIC(15,2))*CAST(1234567890123 AS NUMERIC(15,2)));
 ( cast(1234567890123 as numeric(15,2))* cast(1234567890123 as numeric(15,2)))
======================
  1524157875322755800955129.0000
-- numeric * float returns double type
SELECT (CAST(1234567890123 AS NUMERIC(15,2))*CAST(1234567890123 AS FLOAT));
 ( cast(1234567890123 as numeric(15,2))* cast(1234567890123 as float))
=======================================================================
                                                 1.524157954716582e+024
-- numeric * double returns double type
SELECT (CAST(1234567890123 AS NUMERIC(15,2))*CAST(1234567890123 AS DOUBLE));
 ( cast(1234567890123 as numeric(15,2))* cast(1234567890123 as double))
========================================================================
                                                  1.524157875322756e+024
-- float * float returns float type
SELECT (CAST(1234567890123 AS FLOAT)*CAST(1234567890123 AS FLOAT));
 ( cast(1234567890123 as float)* cast(1234567890123 as float))
===============================================================
                                                  1.524158e+024
-- float * double returns float type
SELECT (CAST(1234567890123 AS FLOAT)*CAST(1234567890123 AS DOUBLE));
 ( cast(1234567890123 as float)* cast(1234567890123 as double))
================================================================
                                          1.524157954716582e+024
-- double * double returns float type
SELECT (CAST(1234567890123 AS DOUBLE)*CAST(1234567890123 AS DOUBLE));
 ( cast(1234567890123 as double)* cast(1234567890123 as double))
=================================================================
                                           1.524157875322756e+024
-- int / int returns int type without type conversion or rounding
SELECT 100100/100000;
  100100/100000
===============
              1
-- int / int returns int type without type conversion or rounding
SELECT 100100/200200;
  100100/200200
===============
              0
-- int / zero returns error
SELECT 100100/(100100-100100);
ERROR: Attempt to divide by zero.
Arithmetic Operations and Type Casting of DATE/TIME Data Types

If all operands are date/time type, only a subtraction operation is allowed and its return value is BIGINT . Note that the unit of the operation differs depending on the types of the operands. Both addition and subtraction operations are allowed in case of date/time and integer types In this case, operation units and return values are date/time data type.

The following table shows operations allowed for each operand type, and their result types.

Allowable Operation and Result Data Type by Operand Type

  TIME (in seconds) DATE (in day) TIMESTAMP (in seconds) DATETIME (in milliseconds) INT
TIME A subtraction is allowed. BIGINT X X X An addition and a subtraction are allowed. TIME
DATE X A subtraction is allowed. BIGINT A subtraction is allowed. BIGINT A subtraction is allowed. BIGINT An addition and a subtraction are allowed. DATE
TIMESTAMP X A subtraction is allowed. BIGINT A subtraction is allowed. BIGINT A subtraction is allowed. BIGINT An addition and a subtraction are allowed. TIMESTAMP
DATETIME X A subtraction is allowed. BIGINT A subtraction is allowed. BIGINT A subtraction is allowed. BIGINT An addition and a subtraction are allowed. DATETIME
INT An addition and a subtraction are allowed. TIME An addition and a subtraction are allowed. DATE An addition and a subtraction are allowed. TIMESTAMP An addition and a subtraction are allowed. DATETIME All operations are allowed.

Note

If any of the date/time arguments contains NULL, NULL is returned.

Example

-- initial systimestamp value
SELECT SYSDATETIME;
  SYSDATETIME
===============================
  07:09:52.115 PM 01/14/2010
-- time type + 10(seconds) returns time type
SELECT (CAST (SYSDATETIME AS TIME) + 10);
 ( cast( SYS_DATETIME  as time)+10)
====================================
  07:10:02 PM
-- date type + 10 (days) returns date type
SELECT (CAST (SYSDATETIME AS DATE) + 10);
 ( cast( SYS_DATETIME  as date)+10)
====================================
  01/24/2010
-- timestamp type + 10(seconds) returns timestamp type
SELECT (CAST (SYSDATETIME AS TIMESTAMP) + 10);
 ( cast( SYS_DATETIME  as timestamp)+10)
=========================================
  07:10:02 PM 01/14/2010
-- systimestamp type + 10(milliseconds) returns systimestamp type
SELECT (SYSDATETIME  + 10);
 ( SYS_DATETIME +10)
===============================
  07:09:52.125 PM 01/14/2010
SELECT DATETIME '09/01/2009 03:30:30.001 pm'- TIMESTAMP '08/31/2009 03:30:30 pm';
 datetime '09/01/2009 03:30:30.001 pm'-timestamp '08/31/2009 03:30:30 pm'
=======================================
  86400001
SELECT TIMESTAMP '09/01/2009 03:30:30 pm'- TIMESTAMP '08/31/2009 03:30:30 pm';
 timestamp '09/01/2009 03:30:30 pm'-timestamp '08/31/2009 03:30:30 pm'
=======================================
  86400
Set Arithmetic Operators
SET, MULTISET, LIST

To compute union, difference or intersection of collections types (SET, MULTISET, and LIST (SEQUENCE)), you can use +, -, or * operators, respectively.

<value_expression>  <set_arithmetic_operator> <value_expression>

    <value_expression> ::=
        collection_value |
        NULL

    <set_arithmetic_operator> ::=
        + (union) |
        - (difference) |
        * (intersection)

The following table shows a result data type by the operator if collection type is an operand.

Result Data Type by Operand Type

  SET MULTISET LIST
SET + , - , * : SET + , - , * : MULTISET + , - , * : MULTISET
MULTISET + , - , * : MULTISET + , - , * : MULTISET + , - , * : MULTISET
LIST (=SEQUENCE) +, -, * : MULTISET +, -, * : MULTISET + : LIST -, * : MULTISET

The following are the examples which execute arithmetic operations with collection types.

SELECT ((CAST ({3,3,3,2,2,1} AS SET))+(CAST ({4,3,3,2} AS MULTISET)));
 (( cast({3, 3, 3, 2, 2, 1} as set))+( cast({4, 3, 3, 2} as multiset)))
======================
  {1, 2, 2, 3, 3, 3, 4}
SELECT ((CAST ({3,3,3,2,2,1} AS MULTISET))+(CAST ({4,3,3,2} AS MULTISET)));
 (( cast({3, 3, 3, 2, 2, 1} as multiset))+( cast({4, 3, 3, 2} as multiset)))
======================
  {1, 2, 2, 2, 3, 3, 3, 3, 3, 4}
SELECT ((CAST ({3,3,3,2,2,1} AS LIST))+(CAST ({4,3,3,2} AS MULTISET)));
 (( cast({3, 3, 3, 2, 2, 1} as sequence))+( cast({4, 3, 3, 2} as multiset)))
======================
  {1, 2, 2, 2, 3, 3, 3, 3, 3, 4}
SELECT ((CAST ({3,3,3,2,2,1} AS SET))-(CAST ({4,3,3,2} AS MULTISET)));
 (( cast({3, 3, 3, 2, 2, 1} as set))-( cast({4, 3, 3, 2} as multiset)))
======================
  {1}
SELECT ((CAST ({3,3,3,2,2,1} AS MULTISET))-(CAST ({4,3,3,2} AS MULTISET)));
 (( cast({3, 3, 3, 2, 2, 1} as multiset))-( cast({4, 3, 3, 2} as multiset)))
======================
  {1, 2, 3}
SELECT ((CAST ({3,3,3,2,2,1} AS LIST))-(CAST ({4,3,3,2} AS MULTISET)));
 (( cast({3, 3, 3, 2, 2, 1} as sequence))-( cast({4, 3, 3, 2} as multiset)))
======================
  {1, 2, 3}
SELECT ((CAST ({3,3,3,2,2,1} AS SET))*(CAST ({4,3,3,2} AS MULTISET)));
 (( cast({3, 3, 3, 2, 2, 1} as set))*( cast({4, 3, 3, 2} as multiset)))
======================
  {2, 3}
SELECT ((CAST ({3,3,3,2,2,1} AS MULTISET))*(CAST ({4,3,3,2} AS MULTISET)));
 (( cast({3, 3, 3, 2, 2, 1} as multiset))*( cast({4, 3, 3, 2} as multiset)))
======================
  {2, 3, 3}
SELECT ((CAST ({3,3,3,2,2,1} AS LIST))*(CAST ({4,3,3,2} AS MULTISET)));
 (( cast({3, 3, 3, 2, 2, 1} as sequence))*( cast({4, 3, 3, 2} as multiset)))
======================
{2, 3, 3}
Assigning Collection Value to Variable

For a collection value to be assigned to a variable, the outer query must return a single row as a result.

The following example shows how to assign a collection value to a variable. The outer query must return only a single row as follows:

CREATE TABLE people (
    ssn VARCHAR(10),
    name VARCHAR(255)
);

INSERT INTO people
VALUES ('1234', 'Ken'), ('5678', 'Dan'), ('9123', 'Jones');

SELECT SET(SELECT name
FROM people
WHERE ssn in {'1234', '5678'})
TO :name_group;
Statement Set Operators
UNION, DIFFERENCE, INTERSECTION

Statement set operators are used to get union, difference or intersection on the result of more than one query statement specified as an operand. Note that the data types of the data to be retrieved from the target tables of the two query statements must be identical or implicitly castable.

query_term statement_set_operator [qualifier] <query_term>
[{statement_set_operator [qualifier] <query_term>}];

    <query_term> ::=
        query_specification
        subquery
  • qualifier
    • DISTINCT, DISTINCTROW or UNIQUE(A returned instance is a distinct value.)
    • ALL (All instances are returned. Duplicates are allowed.)
  • statement_set_operator
    • UNION (union)
    • DIFFERENCE (difference)
    • INTERSECT | INTERSECTION (intersection)

The following table shows statement set operators supported by CUBRID.

Statement Set Operators

Statement Set Operator Description Note
UNION Union Duplicates are not allowed. Outputs all instance results containing duplicates with UNION ALL
DIFFERENCE Difference Duplicates are not allowed. Same as the EXCEPT operator. Outputs all instance results containing duplicates with DIFFERENCE ALL.
INTERSECTION Intersection Duplicates are not allowed. Same as the INTERSECTION operator. Outputs all instance results containing duplicates with INTERSECTION ALL.

The following are the examples which execute queries with statement set operators.

CREATE TABLE nojoin_tbl_1 (ID INT, Name VARCHAR(32));

INSERT INTO nojoin_tbl_1 VALUES (1,'Kim');
INSERT INTO nojoin_tbl_1 VALUES (2,'Moy');
INSERT INTO nojoin_tbl_1 VALUES (3,'Jonas');
INSERT INTO nojoin_tbl_1 VALUES (4,'Smith');
INSERT INTO nojoin_tbl_1 VALUES (5,'Kim');
INSERT INTO nojoin_tbl_1 VALUES (6,'Smith');
INSERT INTO nojoin_tbl_1 VALUES (7,'Brown');

CREATE TABLE nojoin_tbl_2 (id INT, Name VARCHAR(32));

INSERT INTO nojoin_tbl_2 VALUES (5,'Kim');
INSERT INTO nojoin_tbl_2 VALUES (6,'Smith');
INSERT INTO nojoin_tbl_2 VALUES (7,'Brown');
INSERT INTO nojoin_tbl_2 VALUES (8,'Lin');
INSERT INTO nojoin_tbl_2 VALUES (9,'Edwin');
INSERT INTO nojoin_tbl_2 VALUES (10,'Edwin');

--Using UNION to get only distinct rows
SELECT id, name FROM nojoin_tbl_1
UNION
SELECT id, name FROM nojoin_tbl_2;
           id  name
===================================
            1  'Kim'
            2  'Moy'
            3  'Jonas'
            4  'Smith'
            5  'Kim'
            6  'Smith'
            7  'Brown'
            8  'Lin'
            9  'Edwin'
           10  'Edwin'
--Using UNION ALL not eliminating duplicate selected rows
SELECT id, name FROM nojoin_tbl_1
UNION ALL
SELECT id, name FROM nojoin_tbl_2;
           id  name
===================================
            1  'Kim'
            2  'Moy'
            3  'Jonas'
            4  'Smith'
            5  'Kim'
            6  'Smith'
            7  'Brown'
            5  'Kim'
            6  'Smith'
            7  'Brown'
            8  'Lin'
            9  'Edwin'
           10  'Edwin'
--Using DEFFERENCE to get only rows returned by the first query but not by the second
SELECT id, name FROM nojoin_tbl_1
DIFFERENCE
SELECT id, name FROM nojoin_tbl_2;
           id  name
===================================
            1  'Kim'
            2  'Moy'
            3  'Jonas'
            4  'Smith'
--Using INTERSECTION to get only those rows returned by both queries
SELECT id, name FROM nojoin_tbl_1
INTERSECT
SELECT id, name FROM nojoin_tbl_2;
           id  name
===================================
            5  'Kim'
            6  'Smith'
            7  'Brown'
Containment Operators

Containment operators are used to check the containment relationship by performing comparison operation on operands of the collection data type. Collection data types or subqueries can be specified as operands. The operation returns TRUE or FALSE if there is a containment relationship between the two operands of identical/different/subset/proper subset.

<collection_operand> <containment_operator> <collection_operand>

    <collection_operand> ::=
        <set> |
        <multiset> |
        <sequence> (or <list>) |
        <subquery> |
        NULL

    <containment_operator> ::=
        SETEQ |
        SETNEQ |
        SUPERSET |
        SUBSET |
        SUPERSETEQ |
        SUBSETEQ
  • <collection_operand>: This expression that can be specified as an operand is a single SET-valued attribute, an arithmetic expression containing a SET operator or a SET value enclosed in braces. If the type is not specified, the SET value enclosed in braces is treated as a LIST type by default.

    Subqueries can be specified as operands. If a column which is not a collection type is searched, a collection data type keyword is required for the subquery like SET (subquery). The column retrieved by a subquery must return a single set so that it can be compared with the set of the other operands.

    If the element type of collection is an object, the OIDs, not its contents, are compared. For example, two objects with different OIDs are considered to be different even though they have the same attribute values.

    • NULL: Any of operands to be compared is NULL, NULL is returned.

The description and return values about the containment operators supported by CUBRID are as follows:

Containment Operators Supported by CUBRID

Containment Operator Description Predicates Return Value
A SETEQ B A = B: Elements in A and B are same each other. {1,2} SETEQ {1,2,2} 0
A SETNEQ B A <> B: Elements in A and B are not same each other. {1,2} SETNEQ {1,2,3} 1
A SUPERSET B A > B: B is a proper subset of A. {1,2} SUPERSET {1,2,3} 0
A SUBSET B A < B: A is a proper subset of B. {1,2} SUBSET {1,2,3} 1
A SUPERSETEQ B A >= B: B is a subset of A. {1,2} SUPERSETEQ {1,2,3} 0
A SUBSETEQ B A <= B: A is a subset of B. {1,2} SUBSETEQ {1,2,3} 1

The following table shows than possibility of operation by operand and type conversion if a containment operator is used.

Possibility of Operation by Operand

  SET MULTISET LIST(=SEQUENCE)
SET Operation possible Operation possible Operation possible
MULTISET Operation possible Operation possible Operation possible (LIST is converted into MULTISET)
LIST(=SEQUENCE) Operation possible Operation possible (LIST is converted into MULTISET) Some operation possible (SETEQ, SETNEQ) Error occurs for the rest of operators.
--empty set is a subset of any set
SELECT ({} SUBSETEQ (CAST ({3,1,2} AS SET)));
       Result
=============
            1
--operation between set type and null returns null
SELECT ((CAST ({3,1,2} AS SET)) SUBSETEQ NULL);
       Result
=============
        NULL
--{1,2,3} seteq {1,2,3} returns true
SELECT ((CAST ({3,1,2} AS SET)) SETEQ (CAST ({1,2,3,3} AS SET)));
       Result
=============
            1
--{1,2,3} seteq {1,2,3,3} returns false
SELECT ((CAST ({3,1,2} AS SET)) SETEQ (CAST ({1,2,3,3} AS MULTISET)));
       Result
=============
            0
--{1,2,3} setneq {1,2,3,3} returns true
SELECT ((CAST ({3,1,2} AS SET)) SETNEQ (CAST ({1,2,3,3} AS MULTISET)));
       Result
=============
            1
--{1,2,3} subseteq {1,2,3,4} returns true
SELECT ((CAST ({3,1,2} AS SET)) SUBSETEQ (CAST ({1,2,4,4,3} AS SET)));
       Result
=============
            1
--{1,2,3} subseteq {1,2,3,4,4} returns true
SELECT ((CAST ({3,1,2} AS SET)) SUBSETEQ (CAST ({1,2,4,4,3} AS MULTISET)));
       Result
=============
            1
--{1,2,3} subseteq {1,2,4,4,3} returns true
SELECT ((CAST ({3,1,2} AS SET)) SUBSETEQ (CAST ({1,2,4,4,3} AS LIST)));
       Result
=============
            0
--{1,2,3} subseteq {1,2,3,4,4} returns true
SELECT ((CAST ({3,1,2} AS SET)) SUBSETEQ (CAST ({1,2,3,4,4} AS LIST)));
       Result
=============
            1
--{3,1,2} seteq {3,1,2} returns true
SELECT ((CAST ({3,1,2} AS LIST)) SETEQ (CAST ({3,1,2} AS LIST)));
       Result
=============
            1
--error occurs because LIST subseteq LIST is not supported
SELECT ((CAST ({3,1,2} AS LIST)) SUBSETEQ (CAST ({3,1,2} AS LIST)));
ERROR: ' subseteq ' operator is not defined on types sequence and sequence.
SETEQ

The SETEQ operator returns TRUE if the first operand is the same as the second one. It can perform comparison operator for all collection data type.

collection_operand SETEQ collection_operand
--creating a table with SET type address column and LIST type zip_code column

CREATE TABLE contain_tbl (id INT PRIMARY KEY, name CHAR(10), address SET VARCHAR(20), zip_code LIST INT);
INSERT INTO contain_tbl VALUES(1, 'Kim', {'country', 'state'},{1, 2, 3});
INSERT INTO contain_tbl VALUES(2, 'Moy', {'country', 'state'},{3, 2, 1});
INSERT INTO contain_tbl VALUES(3, 'Jones', {'country', 'state', 'city'},{1,2,3,4});
INSERT INTO contain_tbl VALUES(4, 'Smith', {'country', 'state', 'city', 'street'},{1,2,3,4});
INSERT INTO contain_tbl VALUES(5, 'Kim', {'country', 'state', 'city', 'street'},{1,2,3,4});
INSERT INTO contain_tbl VALUES(6, 'Smith', {'country', 'state', 'city', 'street'},{1,2,3,5});
INSERT INTO contain_tbl VALUES(7, 'Brown', {'country', 'state', 'city', 'street'},{});

--selecting rows when two collection_operands are same in the WEHRE clause
SELECT id, name, address, zip_code FROM contain_tbl WHERE address SETEQ {'country','state', 'city'};
           id  name                  address               zip_code
===============================================================================
            3  'Jones     '          {'city', 'country', 'state'}  {1, 2, 3, 4}

1 row selected.
--selecting rows when two collection_operands are same in the WEHRE clause
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SETEQ {1,2,3};
           id  name                  address               zip_code
===============================================================================
            1  'Kim       '          {'country', 'state'}  {1, 2, 3}

1 rows selected.
SETNEQ

The SETNEQ operator returns TRUE (1) if a first operand is different from a second operand. A comparable operation can be performed for all collection data types.

collection_operand SETNEQ collection_operand
--selecting rows when two collection_operands are not same in the WEHRE clause
SELECT id, name, address, zip_code FROM contain_tbl WHERE address SETNEQ {'country','state', 'city'};
           id  name                  address               zip_code
===============================================================================
            1  'Kim       '          {'country', 'state'}  {1, 2, 3}
            2  'Moy       '          {'country', 'state'}  {3, 2, 1}
            4  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            5  'Kim       '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            6  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 5}
            7  'Brown     '          {'city', 'country', 'state', 'street'}  {}

6 rows selected.
--selecting rows when two collection_operands are not same in the WEHRE clause
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SETNEQ {1,2,3};
           id  name                  address               zip_code
===============================================================================
            2  'Moy       '          {'country', 'state'}  {3, 2, 1}
            3  'Jones     '          {'city', 'country', 'state'}  {1, 2, 3, 4}
            4  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            5  'Kim       '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            6  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 5}
            7  'Brown     '          {'city', 'country', 'state', 'street'}  {}
SUPERSET

The SUPERSET operator returns TRUE (1) when a second operand is a proper subset of a first operand; that is, the first one is larger than the second one. If two operands are identical, FALSE (0) is returned. Note that SUPERSET is not supported if all operands are LIST type.

collection_operand SUPERSET collection_operand
--selecting rows when the first operand is a superset of the second operand and they are not same
SELECT id, name, address, zip_code FROM contain_tbl WHERE address SUPERSET {'country','state','city'};
           id  name                  address               zip_code
===============================================================================
            4  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            5  'Kim       '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            6  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 5}
            7  'Brown     '          {'city', 'country', 'state', 'street'}  {}
--SUPERSET operator cannot be used for comparison between LIST and LIST type values
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SUPERSET {1,2,3};
ERROR: ' superset ' operator is not defined on types sequence and sequence.
--Comparing operands with a SUPERSET operator after casting LIST type as SET type
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SUPERSET (CAST ({1,2,3} AS SET));
           id  name                  address               zip_code
===============================================================================
            3  'Jones     '          {'city', 'country', 'state'}  {1, 2, 3, 4}
            4  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            5  'Kim       '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            6  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 5}
SUPERSETEQ

The SUPERSETEQ operator returns TRUE (1) when a second operand is a subset of a first operand; that is, the first one is identical to or larger than the second one. Note that SUPERSETEQ is not supported if an operand is LIST type.

collection_operand SUPERSETEQ collection_operand
--selecting rows when the first operand is a superset of the second operand
SELECT id, name, address, zip_code FROM contain_tbl WHERE address SUPERSETEQ {'country','state','city'};
           id  name                  address               zip_code
===============================================================================
            3  'Jones     '          {'city', 'country', 'state'}  {1, 2, 3, 4}
            4  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            5  'Kim       '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            6  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 5}
            7  'Brown     '          {'city', 'country', 'state', 'street'}  {}
--SUPERSETEQ operator cannot be used for comparison between LIST and LIST type values
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SUPERSETEQ {1,2,3};
ERROR: ' superseteq ' operator is not defined on types sequence and sequence.
--Comparing operands with a SUPERSETEQ operator after casting LIST type as SET type
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SUPERSETEQ (CAST ({1,2,3} AS SET));
           id  name                  address               zip_code
===============================================================================
            1  'Kim       '          {'country', 'state'}  {1, 2, 3}
            3  'Jones     '          {'city', 'country', 'state'}  {1, 2, 3, 4}
            4  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            5  'Kim       '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 4}
            6  'Smith     '          {'city', 'country', 'state', 'street'}  {1, 2, 3, 5}
SUBSET

The SUBSET operator returns TRUE (1) if the second operand contains all elements of the first operand. If the first and the second collection have the same elements, FALSE (0) is returned. Note that both operands are the LIST type, the SUBSET operation is not supported.

collection_operand SUBSET collection_operand
--selecting rows when the first operand is a subset of the second operand and they are not same
SELECT id, name, address, zip_code FROM contain_tbl WHERE address SUBSET {'country','state','city'};
           id  name                  address               zip_code
===============================================================================
            1  'Kim       '          {'country', 'state'}  {1, 2, 3}
            2  'Moy       '          {'country', 'state'}  {3, 2, 1}

--SUBSET operator cannot be used for comparison between LIST and LIST type values
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SUBSET {1,2,3};
ERROR: ' subset ' operator is not defined on types sequence and sequence.

--Comparing operands with a SUBSET operator after casting LIST type as SET type
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SUBSET (CAST ({1,2,3} AS SET));
           id  name                  address               zip_code
===============================================================================
            7  'Brown     '          {'city', 'country', 'state', 'street'}  {}
SUBSETEQ

The SUBSETEQ operator returns TRUE (1) when a first operand is a subset of a second operand; that is, the second one is identical to or larger than the first one. Note that SUBSETEQ is not supported if an operand is LIST type.

collection_operand SUBSETEQ collection_operand
--selecting rows when the first operand is a subset of the second operand
SELECT id, name, address, zip_code FROM contain_tbl WHERE address SUBSETEQ {'country','state','city'};
           id  name                  address               zip_code
===============================================================================
            1  'Kim       '          {'country', 'state'}  {1, 2, 3}
            2  'Moy       '          {'country', 'state'}  {3, 2, 1}
            3  'Jones     '          {'city', 'country', 'state'}  {1, 2, 3, 4}
--SUBSETEQ operator cannot be used for comparison between LIST and LIST type values
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SUBSETEQ {1,2,3};
ERROR: ' subseteq ' operator is not defined on types sequence and sequence.
--Comparing operands with a SUBSETEQ operator after casting LIST type as SET type
SELECT id, name, address, zip_code FROM contain_tbl WHERE zip_code SUBSETEQ (CAST ({1,2,3} AS SET));
           id  name                  address               zip_code
===============================================================================
            1  'Kim       '          {'country', 'state'}  {1, 2, 3}
            7  'Brown     '          {'city', 'country', 'state', 'street'}  {}
BIT Functions and Operators
Bitwise Operator

A Bitwise operator performs operations in bits, and can be used in arithmetic operations. An integer type is specified as the operand and the BIT type cannot be specified. An integer of BIGINT type (64-bit integer) is returned as a result of the operation. If one or more operands are NULL, NULL is returned.

The following table shows the bitwise operators supported by CUBRID.

The bitwise operators

Bitwise operator Description Expression Return Value
& Performs AND operation in bits and returns a BIGINT integer. 17 & 3 1
| Performs OR operation in bits and returns a BIGINT integer. 17 | 3 19
^ Performs XOR operation in bits and returns a BIGINT integer. 17 ^ 3 18
~ A unary operator. It performs complementary operation that reverses (INVERT) the bit order of the operand and returns a BIGINT integer. ~17 -18
<< Performs the operation to shift bits of the left operand as far to the left as the value of the right operand, and returns a BIGINT integer. 17 << 3 136
>> Performs the operation to shift bits of the left operand as far to the right as the value of the right operand, and returns a BIGINT integer. 17 >> 3 2
BIT_AND
BIT_AND(expr)

As an aggregate function, it performs AND operations in bits on every bit of expr. The return value is a BIGINT type. If there is no row that satisfies the expression, NULL is returned.

Parameters:expr -- An expression of integer type
Return type:BIGINT
CREATE TABLE bit_tbl(id int);
INSERT INTO bit_tbl VALUES (1), (2), (3), (4), (5);
SELECT 1&3&5, BIT_AND(id) FROM bit_tbl WHERE id in(1,3,5);
     1&3&5           bit_and(id)
============================================
         1                     1
BIT_OR
BIT_OR(expr)

As an aggregate function, it performs OR operations in bits on every bit of expr. The return value is a BIGINT type. If there is no row that satisfies the expression, NULL is returned.

Parameters:expr -- An expression of integer type
Return type:BIGINT
SELECT 1|3|5, BIT_OR(id) FROM bit_tbl WHERE id in(1,3,5);
     1|3|5            bit_or(id)
============================================
          7                     7
BIT_XOR
BIT_XOR(expr)

As an aggregate function, it performs XOR operations in bits on every bit of expr. The return value is a BIGINT type. If there is no row that satisfies the expression, NULL is returned.

Parameters:expr -- An expression of integer type
Return type:BIGINT
SELECT 1^2^3, BIT_XOR(id) FROM bit_tbl WHERE id in(1,3,5);
     1^3^5            bit_xor(id)
============================================
          7                     7
BIT_COUNT
BIT_COUNT(expr)

The BIT_COUNT function returns the number of bits of expr that have been set to 1; it is not an aggregate function. The return value is a BIGINT type.

Parameters:expr -- An expression of integer type
Return type:BIGINT
SELECT BIT_COUNT(id) FROM bit_tbl WHERE id in(1,3,5);
   bit_count(id)
================
       1
       2
       2
String Functions and Operators

Note

In the string functions, if the value of oracle_style_empty_string parameter is yes, CUBRID does not separate an empty string and NULL; according to each function, CUBRID regards all of them as NULL or an empty string. For the detail description, see oracle_style_empty_string.

Concatenation Operator

A concatenation operator gets a character string or bit string data type as an operand and returns a concatenated string. The plus sign (+) and double pipe symbol (||) are provided as concatenation operators for character string data. If NULL is specified as an operand, a NULL value is returned.

If pipes_as_concat that is a parameter related to SQL statement is set to no (default value: yes), a double pipe (||) symbol is interpreted as an OR operator. If plus_as_concat is set to no (default value: yes), a plus (+) symbol is interpreted as a plus (+) operator. In such case, It is recommended to concatenate strings or bit strings, by using the CONCAT function.

<concat_operand1> +  <concat_operand1>
<concat_operand2> || <concat_operand2>

    <concat_operand1> ::=
        bit string |
        NULL

    <concat_operand2> ::=
        bit string |
        character string
        NULL
  • <concat_operand1>: Left string after concatenation. String or bit string can be specified.
  • <concat_operand2>: Right string after concatenation. String or bit string can be specified.
SELECT 'CUBRID' || ',' + '2008';
 'CUBRID'||','+'2008'
======================
  'CUBRID,2008'
SELECT 'cubrid' || ',' || B'0010' ||B'0000' ||B'0000' ||B'1000';
 'cubrid'||','||B'0010'||B'0000'||B'0000'||B'1000'
======================
  'cubrid,2008'
SELECT ((EXTRACT(YEAR FROM SYS_TIMESTAMP))||(EXTRACT(MONTH FROM SYS_TIMESTAMP)));
 (( extract(year  from  SYS_TIMESTAMP ))||( extract(month  from  SYS_TIMESTAMP )))
======================
  '200812'
SELECT 'CUBRID' || ',' + NULL;
 'CUBRID'||','+null
======================
  NULL
ASCII
ASCII(str)

The ASCII function returns the ASCII code of the most left character in numeric value. If an input string is NULL, NULL is returned. This ASCII function supports single-byte character sets only. If a numeric value is entered, it is converted into character string and then the ASCII code of the most left character is returned.

Parameters:str -- Input string
Return type:STRING
SELECT ASCII('5');
53
SELECT ASCII('ab');
97
BIN
BIN(n)

The BIN function converts a BIGINT type number into binary string. If an input string is NULL, NULL is returned. When you input the string which cannot be transformed into BIGINT, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:n -- A BIGINT type number
Return type:STRING
SELECT BIN(12);
'1100'
BIT_LENGTH
BIT_LENGTH(string)

The BIT_LENGTH function returns the length (bits) of a character string or bit string as an integer value. The return value of the BIT_LENGTH function may depend on the character set, because for the character string, the number of bytes taken up by a single character is different depending on the character set of the data input environment (e.g., UTF-8 Korean characters: one Korean character is 3*8 bits). For details about character sets supported by CUBRID, see Character Strings. When you input the invalid value, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:string -- Specifies the character string or bit string whose number of bits is to be calculated. If this value is NULL, NULL is returned.
Return type:INT
SELECT BIT_LENGTH('');
   bit_length('')
=================
                0
SELECT BIT_LENGTH('CUBRID');
   bit_length('CUBRID')
=======================
                     48
-- UTF-8 Korean character
SELECT BIT_LENGTH('큐브리드');
     bit_length('큐브리드')
=========================
                       96
SELECT BIT_LENGTH(B'010101010');
   bit_length(B'010101010')
===========================
                          9
CREATE TABLE bit_length_tbl (char_1 CHAR, char_2 CHAR(5), varchar_1 VARCHAR, bit_var_1 BIT VARYING);
INSERT INTO bit_length_tbl VALUES('', '', '', B''); --Length of empty string
INSERT INTO bit_length_tbl VALUES('a', 'a', 'a', B'010101010'); --English character
INSERT INTO bit_length_tbl VALUES(NULL, '큐', '큐', B'010101010'); --UTF-8 Korean character and NULL
INSERT INTO bit_length_tbl VALUES(' ', ' 큐', ' 큐', B'010101010'); --UTF-8 Korean character and space

SELECT BIT_LENGTH(char_1), BIT_LENGTH(char_2), BIT_LENGTH(varchar_1), BIT_LENGTH(bit_var_1) FROM bit_length_tbl;
bit_length(char_1)  bit_length(char_2)      bit_length(varchar_1)   bit_length(bit_var_1)
================================================================================
8                   40                       0                       0
8                   40                       8                       9
NULL                56                      24                       9
8                   40                      32                       9
CHAR_LENGTH, CHARACTER_LENGTH, LENGTHB, LENGTH
CHAR_LENGTH(string)
CHARACTER_LENGTH(string)
LENGTHB(string)
LENGTH(string)

CHAR_LENGTH, CHARACTER_LENGTH, LENGTHB, and LENGTH are used interchangeably. The number of characters is returned as an integer. For details on character set supported by CUBRID, see An Overview of Globalization.

Parameters:string -- Specifies the string whose length will be calculated according to the number of characters. If the character string is NULL, NULL is returned.
Return type:INT

Note

  • In versions lower than CUBRID 9.0, the multibyte string returns the number of bytes in the string. Therefore, the length of one character is calculated as 2- or 3-bytes according to the charset.
  • The length of each space character that is included in a character string is one byte.
  • The length of empty quotes (") to represent a space character is 0. Note that in a CHAR (n) type, the length of a space character is n, and it is specified as 1 if n is omitted.
--character set is UTF-8 for Korean characters
SELECT LENGTH('');
char length('')
==================
                 0
SELECT LENGTH('CUBRID');
char length('CUBRID')
==================
                 6
SELECT LENGTH('큐브리드');
char length('큐브리드')
==================
                 4
CREATE TABLE length_tbl (char_1 CHAR, char_2 CHAR(5), varchar_1 VARCHAR, varchar_2 VARCHAR);
INSERT INTO length_tbl VALUES('', '', '', ''); --Length of empty string
INSERT INTO length_tbl VALUES('a', 'a', 'a', 'a'); --English character
INSERT INTO length_tbl VALUES(NULL, '큐', '큐', '큐'); --Korean character and NULL
INSERT INTO length_tbl VALUES(' ', ' 큐', ' 큐', ' 큐'); --Korean character and space

SELECT LENGTH(char_1), LENGTH(char_2), LENGTH(varchar_1), LENGTH(varchar_2) FROM length_tbl;
char_length(char_1) char_length(char_2) char_length(varchar_1) char_length(varchar_2)
================================================================================
1                     5                        0             0
1                     5                        1             1
NULL                  5                        1             1
1                     5                        2             2
CHR
CHR(number_operand [USING charset_name])

The CHR function returns a character that corresponds to the return value of the expression specified as an argument. When you input the code value within invalid ranges, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:
  • number_operand -- Specifies an expression that returns a numeric value.
  • charset_name -- Characterset name. It supports utf8 and iso88591.
Return type:

STRING

SELECT CHR(68) || CHR(68-2);
   chr(68)|| chr(68-2)
======================
  'DB'

If you want to get a multibyte character with the CHR function, input a number with the valid range of the charset.

SELECT CHR(14909886 USING utf8);
-- Below query's result is the same as above.
SET NAMES utf8;
SELECT CHR(14909886);
   chr(14909886 using utf8)
======================
  'ま'

If you want to get the hexadecimal string from a character, use HEX function.

SET NAMES utf8;
SELECT HEX('ま');
   hex(_utf8'ま')
======================
  'E381BE'

If you want to get the decimal string from a hexadecimal string, use CONV function.

SET NAMES utf8;
SELECT CONV('E381BE',16,10);
   conv(_utf8'E381BE', 16, 10)
======================
  '14909886'
CONCAT
CONCAT(string1, string2 [,string3 [, ... [, stringN]...]])

The CONCAT function has at least one argument specified for it and returns a string as a result of concatenating all argument values. The number of parameters that can be specified is unlimited. Automatic type casting takes place if a non-string type is specified as the argument. If any of the arguments is specified as NULL, NULL is returned.

If you want to insert separators between strings specified as arguments for concatenation, use the CONCAT_WS() Function.

Parameters:strings -- character string
Return type:STRING
SELECT CONCAT('CUBRID', '2008' , 'R3.0');
   concat('CUBRID', '2008', 'R3.0')
======================
'CUBRID2008R3.0'
--it returns null when null is specified for one of parameters
SELECT CONCAT('CUBRID', '2008' , 'R3.0', NULL);
   concat('CUBRID', '2008', 'R3.0', null)
======================
  NULL
--it converts number types and then returns concatenated strings
SELECT CONCAT(2008, 3.0);
   concat(2008, 3.0)
======================
  '20083.0'
CONCAT_WS
CONCAT_WS(string1, string2 [,string3 [, ... [, stringN]...]])

The CONCAT_WS function has at least two arguments specified for it. The function uses the first argument value as the separator and returns the result.

Parameters:strings -- character string
Return type:STRING
SELECT CONCAT_WS(' ', 'CUBRID', '2008' , 'R3.0');
concat_ws(' ', 'CUBRID', '2008', 'R3.0')
======================
  'CUBRID 2008 R3.0'
--it returns strings even if null is specified for one of parameters
SELECT CONCAT_WS(' ', 'CUBRID', '2008', NULL, 'R3.0');
concat_ws(' ', 'CUBRID', '2008', null, 'R3.0')
======================
  'CUBRID 2008 R3.0'
--it converts number types and then returns concatenated strings with separator
SELECT CONCAT_WS(' ',2008, 3.0);
concat_ws(' ', 2008, 3.0)
======================
  '2008 3.0'
ELT
ELT(N, string1, string2, ...)

If N is 1, the ELT function returns string1 and if N is 2, it returns string2. The return value is a VARCHAR type. You can add conditional expressions as needed.

The maximum byte length of the character string is 33,554,432 and if this length is exceeded, NULL will be returned.

If N is 0 or a negative number, an empty string will be returned. If N is greater than the number of this input character string, NULL will be returned as it is out of range. If N is a type that cannot be converted to an integer, an error will be returned.

Parameters:
  • N -- A position of a string to return among the list of strings
  • strings -- The list of strings
Return type:

STRING

SELECT ELT(3,'string1','string2','string3');
  elt(3, 'string1', 'string2', 'string3')
======================
  'string3'
SELECT ELT('3','1/1/1','23:00:00','2001-03-04');
  elt('3', '1/1/1', '23:00:00', '2001-03-04')
======================
  '2001-03-04'
SELECT ELT(-1, 'string1','string2','string3');
  elt(-1, 'string1','string2','string3')
======================
  NULL
SELECT ELT(4,'string1','string2','string3');
  elt(4, 'string1', 'string2', 'string3')
======================
  NULL
SELECT ELT(3.2,'string1','string2','string3');
  elt(3.2, 'string1', 'string2', 'string3')
======================
  'string3'
SELECT ELT('a','string1','string2','string3');
ERROR: Cannot coerce 'a' to type bigint.
FIELD
FIELD( search_string, string1 [,string2 [, ... [, stringN]...]])

The FIELD function returns the location index value (position) of a string of string1, string2. The function returns 0 if it does not have a parameter value which is the same as search_string. It returns 0 if search_string is NULL because it cannot perform the comparison operation with the other arguments.

If all arguments specified for FIELD function are of string type, string comparison operation is performed: if all of them are of number type, numeric comparison operation is performed. If the type of one argument is different from that of another, a comparison operation is performed by casting each argument to the type of the first argument. If type casting fails during the comparison operation with each argument, the function considers the result of the comparison operation as FALSE and resumes the other operations.

Parameters:
  • search_string -- A string pattern to search
  • strings -- The list of strings to be searched
Return type:

INT

SELECT FIELD('abc', 'a', 'ab', 'abc', 'abcd', 'abcde');
   field('abc', 'a', 'ab', 'abc', 'abcd', 'abcde')
==================================================
                                                 3
--it returns 0 when no same string is found in the list
SELECT FIELD('abc', 'a', 'ab', NULL);
   field('abc', 'a', 'ab', null)
================================
                               0
--it returns 0 when null is specified in the first parameter
SELECT FIELD(NULL, 'a', 'ab', NULL);
   field(null, 'a', 'ab', null)
===============================
                              0
SELECT FIELD('123', 1, 12, 123.0, 1234, 12345);
   field('123', 1, 12, 123.0, 1234, 12345)
==========================================
                                         0
SELECT FIELD(123, 1, 12, '123.0', 1234, 12345);
   field(123, 1, 12, '123.0', 1234, 12345)
==============================================
                                             3
FIND_IN_SET
FIND_IN_SET(str, strlist)

The FIND_IN_SET function looks for the string str in the string list strlist and returns a position of str if it exists. A string list is a string composed of substrings separated by a comma (,). If str is not in strlist or strlist is an empty string, 0 is returned. If either argument is NULL, NULL is returned. This function does not work properly if str contains a comma (,).

Parameters:
  • str -- A string to be searched
  • strlist -- A group of strings separated by a comma
Return type:

INT

SELECT FIND_IN_SET('b','a,b,c,d');
2
FROM_BASE64
FROM_BASE64(str)

FROM_BASE64 function returns the the decoded result as binary string from the input string encoded as base-64 rule, which is used in TO_BASE64 function. If the input value is NULL, it returns NULL. When you input the invalid base-64 string, it returns an error if the value of **return_null_on_function_errors in cubrid.conf is no(the default); NULL if this value is yes. See TO_BASE64() for more details on base-64 encoding rules.

Parameters:str -- Input string
Return type:STRING
SELECT TO_BASE64('abcd'), FROM_BASE64(TO_BASE64('abcd'));
   to_base64('abcd') from_base64( to_base64('abcd'))
============================================
  'YWJjZA==' 'abcd'

See also

TO_BASE64()

INSERT
INSERT(str, pos, len, string)

The INSERT function inserts a partial character string as long as the length from the specific location of the input character string. The return value is a VARCHAR type. The maximum length of the character string is 33,554,432 and if this length is exceeded, NULL will be returned.

Parameters:
  • str -- Input character string
  • pos -- str location. Starts from 1. If pos is smaller than 1 or greater than the length of string + 1, the string will not be inserted and the str will be returned instead.
  • len -- Length of string to insert pos of str. If len exceeds the length of the partial character string, insert as many values as string in the pos of the str . If len is a negative number, str will be the end of the character string.
  • string -- Partial character string to insert to str
Return type:

STRING

SELECT INSERT('cubrid',2,2,'dbsql');
  insert('cubrid', 2, 2, 'dbsql')
======================
  'cdbsqlrid'
SELECT INSERT('cubrid',0,3,'db');
  insert('cubrid', 0, 3, 'db')
======================
  'cubrid'
SELECT INSERT('cubrid',-3,3,'db');
  insert('cubrid', -3, 3, 'db')
======================
  'cubrid'
SELECT INSERT('cubrid',3,100,'db');
  insert('cubrid', 3, 100, 'db')
======================
  'cudb'
SELECT INSERT('cubrid',7,100,'db');
  insert('cubrid', 7, 100, 'db')
======================
  'cubriddb'
SELECT INSERT('cubrid',3,-1,'db');
  insert('cubrid', 3, -1, 'db')
======================
  'cudb'
INSTR
INSTR(string, substring[, position])

The INSTR function, similarly to the POSITION, returns the position of a substring within string; the position. For the INSTR function, you can specify the starting position of the search for substring to make it possible to search for duplicate substring.

Parameters:
  • string -- Specifies the input character string.
  • substring -- Specifies the character string whose position is to be returned.
  • position -- Optional. Represents the position of a string where the search begins in character unit. If omitted, the default value 1 is applied. The first position of the string is specified as 1. If the value is negative, the system counts backward from the end of the string.
Return type:

INT

Note

In the earlier versions of CUBRID 9.0, position value is returned in byte unit, not character unit. When a multi-byte character set is used, the number of bytes representing one character is different; so the return value may not the same.

--character set is UTF-8 for Korean characters
--it returns position of the first 'b'
SELECT INSTR ('12345abcdeabcde','b');
   instr('12345abcdeabcde', 'b', 1)
===================================
                                  7
-- it returns position of the first '나' on UTF-8 Korean charset
SELECT INSTR ('12345가나다라마가나다라마', '나' );
   instr('12345가나다라마가나다라마', '나', 1)
=================================
                                7
-- it returns position of the second '나' on UTF-8 Korean charset
SELECT INSTR ('12345가나다라마가나다라마', '나', 11 );
   instr('12345가나다라마가나다라마', '나', 11)
=================================
                               12
--it returns position of the 'b' searching from the 8th position
SELECT INSTR ('12345abcdeabcde','b', 8);
   instr('12345abcdeabcde', 'b', 8)
===================================
                                 12
--it returns position of the 'b' searching backwardly from the end
SELECT INSTR ('12345abcdeabcde','b', -1);
   instr('12345abcdeabcde', 'b', -1)
====================================
                                  12
--it returns position of the 'b' searching backwardly from a specified position
SELECT INSTR ('12345abcdeabcde','b', -8);
   instr('12345abcdeabcde', 'b', -8)
====================================
                                   7
LCASE, LOWER
LCASE(string)
LOWER(string)

The functions LCASE and LOWER are used interchangeably. They convert uppercase characters included in string to lowercase characters.

Parameters:string -- Specifies the string in which uppercase characters are to be converted to lowercase. If the value is NULL, NULL is returned.
Return type:STRING
SELECT LOWER('');
  lower('')
======================
  ''
SELECT LOWER(NULL);
  lower(null)
======================
  NULL
SELECT LOWER('Cubrid');
  lower('Cubrid')
======================
  'cubrid'

Note that the LOWER function may not work properly by specified collation. For example, when you try to change character Ă used in Romanian as lower character, this function works as follows by collation.

If collation is utf8_bin, this character is not changed.

SET NAMES utf8 COLLATE utf8_bin;
SELECT LOWER('Ă');

   lower(_utf8'Ă')
======================
  'Ă'

If collation is utf8_ro_RO, 'Ă' can be changed.

SET NAMES utf8 COLLATE utf8_ro_cs;
SELECT LOWER('Ă');

   lower(_utf8'Ă' COLLATE utf8_ro_cs)
======================
  'ă'

For supporting collations in CUBRID, see CUBRID Collation.

LEFT
LEFT(string, length)

The LEFT function returns a length number of characters from the leftmost string. If any of the arguments is NULL, NULL is returned. If a value greater than the length of the string or a negative number is specified for a length, the entire string is returned. To extract a length number of characters from the rightmost string, use the RIGHT().

Parameters:
  • string -- Input string
  • length -- The length of a string to be returned
Return type:

STRING

SELECT LEFT('CUBRID', 3);
 left('CUBRID', 3)
======================
  'CUB'
SELECT LEFT('CUBRID', 10);
  left('CUBRID', 10)
======================
  'CUBRID'
LOCATE
LOCATE(substring, string[, position])

The LOCATE function returns the location index value of a substring within a character string. The third argument position can be omitted. If this argument is specified, the function searches for substring from the given position and returns the location index value of the first occurrence. If the substring cannot be found within the string, 0 is returned. The LOCATE function behaves like the POSITION(), but you cannot use LOCATE for bit strings.

Parameters:
  • substring -- A string pattern to search
  • string -- A whole string to be searched
  • position -- Starting position of a whole string to be searched
Return type:

INT

--it returns 1 when substring is empty space
SELECT LOCATE ('', '12345abcdeabcde');
 locate('', '12345abcdeabcde')
===============================
                             1
--it returns position of the first 'abc'
SELECT LOCATE ('abc', '12345abcdeabcde');
 locate('abc', '12345abcdeabcde')
================================
                               6
--it returns position of the second 'abc'
SELECT LOCATE ('abc', '12345abcdeabcde', 8);
 locate('abc', '12345abcdeabcde', 8)
======================================
                                  11
--it returns 0 when no substring found in the string
SELECT LOCATE ('ABC', '12345abcdeabcde');
 locate('ABC', '12345abcdeabcde')
=================================
                                0
LPAD
LPAD(char1, n[, char2])

The LPAD function pads the left side of a string until the string length reaches the specified value.

Parameters:
  • char1 -- Specifies the string to pad characters to. If n is smaller than the length of char1, padding is not performed, and char1 is truncated to length n and then returned. If the value is NULL, NULL is returned.
  • n -- Specifies the total length of char1 in bytes. If the value is NULL, NULL is returned.
  • char2 -- Specifies the string to pad to the left until the length of char1 reaches n. If it is not specified, empty characters (' ') are used as a default. If the value is NULL, NULL is returned.
Return type:

STRING

Note

In versions lower than CUBRID 9.0, a single character is processed as 2 or 3 bytes in a multi-byte character set environment. If n is truncated up to the first byte representing a character according to a value of char1, the last byte is removed and a space character (1 byte) is added to the left because the last character cannot be represented normally. When the value is NULL, NULL is returned as its result.

--character set is UTF-8 for Korean characters

--it returns only 3 characters if not enough length is specified
SELECT LPAD ('CUBRID', 3, '?');
  lpad('CUBRID', 3, '?')
======================
  'CUB'

SELECT LPAD ('큐브리드', 3, '?');
 lpad('큐브리드', 3, '?')
======================
  '큐브리'
--padding spaces on the left till char_length is 10
SELECT LPAD ('CUBRID', 10);
 lpad('CUBRID', 10)
======================
  '    CUBRID'
--padding specific characters on the left till char_length is 10
SELECT LPAD ('CUBRID', 10, '?');
 lpad('CUBRID', 10, '?')
======================
  '????CUBRID'
--padding specific characters on the left till char_length is 10
SELECT LPAD ('큐브리드', 10, '?');
 lpad('큐브리드', 10, '?')
======================
  '??????큐브리드'
--padding 4 characters on the left
SELECT LPAD ('큐브리드', LENGTH('큐브리드')+4, '?');
 lpad('큐브리드',  char_length('큐브리드')+4, '?')
======================
  '????큐브리드'
LTRIM
LTRIM(string[, trim_string])

The LTRIM function removes all specified characters from the left-hand side of a string.

Parameters:
  • string -- Enters a string or string-type column to trim. If this value is NULL, NULL is returned.
  • trim_string -- You can specify a specific string to be removed in the left side of string. If it is not specified, empty characters (' ') is automatically specified so that the empty characters in the left side are removed.
Return type:

STRING

--trimming spaces on the left
SELECT LTRIM ('     Olympic     ');
  ltrim('     Olympic     ')
======================
  'Olympic     '
--If NULL is specified, it returns NULL
SELECT LTRIM ('iiiiiOlympiciiiii', NULL);
  ltrim('iiiiiOlympiciiiii', null)
======================
  NULL
-- trimming specific strings on the left
SELECT LTRIM ('iiiiiOlympiciiiii', 'i');
  ltrim('iiiiiOlympiciiiii', 'i')
======================
  'Olympiciiiii'
MID
MID(string, position, substring_length)

The MID function extracts a string with the length of substring_length from a position within the string and then returns it. If a negative number is specified as a position value, the position is calculated in a reverse direction from the end of the string. substring_length cannot be omitted. If a negative value is specified, the function considers this as 0 and returns an empty string.

The MID function is working like the SUBSTR(), but there are differences in that it cannot be used for bit strings, that the substring_length argument must be specified, and that it returns an empty string if a negative number is specified for substring_length.

Parameters:
  • string -- Specifies an input character string. If this value is NULL, NULL is returned.
  • position -- Specifies the starting position from which the string is to be extracted. The position of the first character is 1. It is considered to be 1 even if it is specified as 0. If the input value is NULL, NULL is returned.
  • substring_length -- Specifies the length of the string to be extracted. If 0 or a negative number is specified, an empty string is returned; if NULL is specified, NULL is returned.
Return type:

STRING

CREATE TABLE mid_tbl(a VARCHAR);
INSERT INTO mid_tbl VALUES('12345abcdeabcde');

--it returns empty string when substring_length is 0
SELECT MID(a, 6, 0), SUBSTR(a, 6, 0), SUBSTRING(a, 6, 0) FROM mid_tbl;
  mid(a, 6, 0)          substr(a, 6, 0)       substring(a from 6 for 0)
==================================================================
  ''                    ''                    ''
--it returns 4-length substrings counting from the 6th position
SELECT MID(a, 6, 4), SUBSTR(a, 6, 4), SUBSTRING(a, 6, 4) FROM mid_tbl;
  mid(a, 6, 4)          substr(a, 6, 4)       substring(a from 6 for 4)
==================================================================
  'abcd'                'abcd'                'abcd'
--it returns an empty string when substring_length < 0
SELECT MID(a, 6, -4), SUBSTR(a, 6, -4), SUBSTRING(a, 6, -4) FROM mid_tbl;
  mid(a, 6, -4)         substr(a, 6, -4)      substring(a from 6 for -4)
==================================================================
  ''                    NULL                  'abcdeabcde'
--it returns 4-length substrings at 6th position counting backward from the end
SELECT MID(a, -6, 4), SUBSTR(a, -6, 4), SUBSTRING(a, -6, 4) FROM mid_tbl;
  mid(a, -6, 4)         substr(a, -6, 4)      substring(a from -6 for 4)
==================================================================
  'eabc'                'eabc'                '1234'
OCTET_LENGTH
OCTET_LENGTH(string)

The OCTET_LENGTH function returns the length (byte) of a character string or bit string as an integer. Therefore, it returns 1 (byte) if the length of the bit string is 8 bits, but 2 (bytes) if the length is 9 bits.

Parameters:string -- Specifies the character or bit string whose length is to be returned in bytes. If the value is NULL, NULL is returned.
Return type:INT
--character set is UTF-8 for Korean characters

SELECT OCTET_LENGTH('');
 octet_length('')
==================
                 0
SELECT OCTET_LENGTH('CUBRID');
 octet_length('CUBRID')
==================
                 6
SELECT OCTET_LENGTH('큐브리드');
 octet_length('큐브리드')
==================
                 12
SELECT OCTET_LENGTH(B'010101010');
 octet_length(B'010101010')
==================
                 2
CREATE TABLE octet_length_tbl (char_1 CHAR, char_2 CHAR(5), varchar_1 VARCHAR, bit_var_1 BIT VARYING);
INSERT INTO octet_length_tbl VALUES('', '', '', B''); --Length of empty string
INSERT INTO octet_length_tbl VALUES('a', 'a', 'a', B'010101010'); --English character
INSERT INTO octet_length_tbl VALUES(NULL, '큐', '큐', B'010101010'); --Korean character and NULL
INSERT INTO octet_length_tbl VALUES(' ', ' 큐', ' 큐', B'010101010'); --Korean character and space

SELECT OCTET_LENGTH(char_1), OCTET_LENGTH(char_2), OCTET_LENGTH(varchar_1), OCTET_LENGTH(bit_var_1) FROM octet_length_tbl;
octet_length(char_1) octet_length(char_2) octet_length(varchar_1) octet_length(bit_var_1)
================================================================================
1                      5                         0                       0
1                      5                         1                       2
NULL                   7                         3                       2
1                      7                         4                       2
POSITION
POSITION(substring IN string)

The POSITION function returns the position of a character string corresponding to substring within a character string corresponding to string.

An expression that returns a character string or a bit string can be specified as an argument of this function. The return value is an integer greater than or equal to 0. This function returns the position value in character unit for a character string, and in bits for a bit string.

The POSITION function is occasionally used in combination with other functions. For example, if you want to extract a certain string from another string, you can use the result of the POSITION function as an input to the SUBSTRING function.

Note

The location is returned in the unit of byte, not the character, in version lower than CUBRID 9.0. The multi-byte charset uses different numbers of bytes to express one character, so the result value may differ.

Parameters:substring -- Specifies the character string whose position is to be returned. If the value is an empty character, 1 is returned. If the value is NULL, NULL is returned.
Return type:INT
--character set is UTF-8 for Korean characters

--it returns 1 when substring is empty space
SELECT POSITION ('' IN '12345abcdeabcde');
  position('' in '12345abcdeabcde')
===============================
                              1
--it returns position of the first 'b'
SELECT POSITION ('b' IN '12345abcdeabcde');
  position('b' in '12345abcdeabcde')
================================
                               7
-- it returns position of the first '나'
SELECT POSITION ('나' IN '12345가나다라마가나다라마');
  position('나' in '12345가나다라마가나다라마')
=================================
                                7
--it returns 0 when no substring found in the string
SELECT POSITION ('f' IN '12345abcdeabcde');
  position('f' in '12345abcdeabcde')
=================================
                                0
SELECT POSITION (B'1' IN B'000011110000');
  position(B'1' in B'000011110000')
=================================
                                5
REPEAT
REPEAT(string, count)

The REPEAT function returns the character string with a length equal to the number of repeated input character strings. The return value is a VARCHAR type. The maximum length of the character string is 33,554,432 and if it this length is exceeded, NULL will be returned. If one of the parameters is NULL, NULL will be returned.

Parameters:
  • substring -- Character string
  • count -- Repeat count. If you enter 0 or a negative number, an empty string will be returned and if you enter a non-numeric data type, an error will be returned.
Return type:

STRING

SELECT REPEAT('cubrid',3);
   repeat('cubrid', 3)
======================
  'cubridcubridcubrid'
SELECT REPEAT('cubrid',32000000);
   repeat('cubrid', 32000000)
======================
  NULL
SELECT REPEAT('cubrid',-1);
   repeat('cubrid', -1)
======================
  ''
SELECT REPEAT('cubrid','a');
ERROR: Cannot coerce 'a' to type integer.
REPLACE
REPLACE(string, search_string[, replacement_string])

The REPLACE function searches for a character string, search_string, within a given character string, string, and replaces it with a character string, replacement_string. If the string to be replaced, replacement_string is omitted, all search_strings retrieved from string are removed. If NULL is specified as an argument, NULL is returned.

Parameters:
  • string -- Specifies the original string. If the value is NULL, NULL is returned.
  • search_string -- Specifies the string to be searched. If the value is NULL, NULL is returned
  • replacement_string -- Specifies the string to replace the search_string. If this value is omitted, string is returned with the search_string removed. If the value is NULL, NULL is returned.
Return type:

STRING

--it returns NULL when an argument is specified with NULL value
SELECT REPLACE('12345abcdeabcde','abcde',NULL);
replace('12345abcdeabcde', 'abcde', null)
======================
  NULL
--not only the first substring but all substrings into 'ABCDE' are replaced
SELECT REPLACE('12345abcdeabcde','abcde','ABCDE');
replace('12345abcdeabcde', 'abcde', 'ABCDE')
======================
  '12345ABCDEABCDE'
--it removes all of substrings when replace_string is omitted
SELECT REPLACE('12345abcdeabcde','abcde');
replace('12345abcdeabcde', 'abcde')
======================
  '12345'

The following shows how to print out the newline as "\n".

-- no_backslash_escapes=yes (default)

CREATE TABLE tbl (cmt_no INT PRIMARY KEY, cmt VARCHAR(1024));
INSERT INTO tbl VALUES (1234,
'This is a test for

 new line.');

SELECT REPLACE(cmt, CHR(10), '\n')
FROM tbl
WHERE cmt_no=1234;
This is a test for\n\n new line.
REVERSE
REVERSE(string)

The REVERSE function returns string converted in the reverse order.

Parameters:string -- Specifies an input character string. If the value is an empty string, empty value is returned. If the value is NULL, NULL is returned.
Return type:STRING
SELECT REVERSE('CUBRID');
 reverse('CUBRID')
======================
  'DIRBUC'
RPAD
RPAD(char1, n[, char2])

The RPAD function pads the right side of a string until the string length reaches the specified value.

Parameters:
  • char1 -- Specifies the string to pad characters to. If n is smaller than the length of char1, padding is not performed, and char1 is truncated to length n and then returned. If the value is NULL, NULL is specified.
  • n -- Specifies the total length of char1. If the value is NULL, NULL is specified.
  • char2 -- Specifies the string to pad to the right until the length of char1 reaches n. If it is not specified, empty characters (' ') are used as a default. If the value is NULL, NULL is returned.
Return type:

STRING

Note

In versions lower than CUBRID 9.0, a single character is processed as 2 or 3 bytes in a multi-byte character set environment. If n is truncated up to the first byte representing a character according to a value of char1, the last byte is removed and a space character (1 byte) is added to the right because the last character cannot be represented normally. When the value is NULL, NULL is returned as its result.

--character set is UTF-8 for Korean characters

--it returns only 3 characters if not enough length is specified
SELECT RPAD ('CUBRID', 3, '?');
 rpad('CUBRID', 3, '?')
======================
  'CUB'
--on multi-byte charset, it returns the first character only with a right-padded space
SELECT RPAD ('큐브리드', 3, '?');
 rpad('큐브리드', 3, '?')
======================
  '큐브리'
--padding spaces on the right till char_length is 10
SELECT RPAD ('CUBRID', 10);
 rpad('CUBRID', 10)
======================
  'CUBRID    '
--padding specific characters on the right till char_length is 10
SELECT RPAD ('CUBRID', 10, '?');
 rpad('CUBRID', 10, '?')
======================
  'CUBRID????'
--padding specific characters on the right till char_length is 10
SELECT RPAD ('큐브리드', 10, '?');
 rpad('큐브리드', 10, '?')
======================
  '큐브리드??????'
--padding 4 characters on the right
SELECT RPAD ('큐브리드', LENGTH('큐브리드')+4, '?');
 rpad('',  char_length('')+4, '?')
======================
  '큐브리드????'
RTRIM
RTRIM(string[, trim_string])

The RTRIM function removes specified characters from the right-hand side of a string.

Parameters:
  • string -- Enters a string or string-type column to trim. If this value is NULL, NULL is returned.
  • trim_string -- You can specify a specific string to be removed in the right side of string. If it is not specified, empty characters (' ') is automatically specified so that the empty characters in the right side are removed.
Return type:

STRING

SELECT RTRIM ('     Olympic     ');
 rtrim('     Olympic     ')
======================
  '     Olympic'
--If NULL is specified, it returns NULL
SELECT RTRIM ('iiiiiOlympiciiiii', NULL);
 rtrim('iiiiiOlympiciiiii', null)
======================
  NULL
-- trimming specific strings on the right
SELECT RTRIM ('iiiiiOlympiciiiii', 'i');
 rtrim('iiiiiOlympiciiiii', 'i')
======================
  'iiiiiOlympic'
SPACE
SPACE(N)

The SPACE function returns as many empty strings as the number specified. The return value is a VARCHAR type.

Parameters:N -- Space count. It cannot be greater than the value specified in the system parameter, string_max_size_bytes (default 1048576). If it exceeds the specified value, NULL will be returned. The maximum value is 33,554,432; if this length is exceeded, NULL will be returned. If you enter 0 or a negative number, an empty string will be returned; if you enter a type that can't be converted to a numeric value, an error will be returned.
Return type:STRING
SELECT SPACE(8);
   space(8)
======================
  '        '
SELECT LENGTH(space(1048576));
   char_length( space(1048576))
===============================
                        1048576
SELECT LENGTH(space(1048577));
   char_length( space(1048577))
===============================
                           NULL
-- string_max_size_bytes=33554432
SELECT LENGTH(space('33554432'));
   char_length( space('33554432'))
==================================
                          33554432
SELECT SPACE('aaa');
ERROR: Cannot coerce 'aaa' to type bigint.
STRCMP
STRCMP(string1, string2)

The STRCMP function compares two strings, string1 and string2, and returns 0 if they are identical, 1 if string1 is greater, or -1 if string1 is smaller. If any of the parameters is NULL, NULL is returned.

Parameters:
  • string1 -- A string to be compared
  • string2 -- A string to be compared
Return type:

INT

SELECT STRCMP('abc', 'abc');
0
SELECT STRCMP ('acc', 'abc');
1

Note

Until the previous version of 9.0, STRCMP did not distinguish an uppercase and a lowercase. From 9.0, it compares the strings case-sensitively. To make STRCMP case-insensitive, you should use case-insensitive collation(e.g.: utf8_en_ci).

-- In previous version of 9.0 STRCMP works case-insensitively
SELECT STRCMP ('ABC','abc');
0
-- From 9.0 version, STRCMP distinguish the uppercase and the lowercase when the collation is case-sensitive.
-- charset is en_US.iso88591

SELECT STRCMP ('ABC','abc');
-1
-- If the collation is case-insensitive, it does not distinguish the uppercase and the lowercase.
-- charset is en_US.iso88591

SELECT STRCMP ('ABC' COLLATE utf8_en_ci ,'abc' COLLATE utf8_en_ci);
0
SUBSTR
SUBSTR(string, position[, substring_length])

The SUBSTR function extracts a character string with the length of substring_length from a position, position, within character string, string, and then returns it.

Note

In the previous versions of CUBRID 9.0, the starting position and string length are calculated in byte unit, not in character unit; therefore, in a multi-byte character set, you must specify the parameter in consideration of the number of bytes representing a single character.

Parameters:
  • string -- Specifies the input character string. If the input value is NULL, NULL is returned.
  • position -- Specifies the position from where the string is to be extracted in bytes. Even though the position of the first character is specified as 1 or a negative number, it is considered as 1. If a value greater than the string length or NULL is specified, NULL is returned.
  • substring_length -- Specifies the length of the string to be extracted in bytes. If this argument is omitted, character strings between the given position, position, and the end of them are extracted. NULL cannot be specified as an argument value of this function. If 0 is specified, an empty string is returned; if a negative value is specified, NULL is returned.
Return type:

STRING

--character set is UTF-8 for Korean characters

--it returns empty string when substring_length is 0
SELECT SUBSTR('12345abcdeabcde',6, 0);
 substr('12345abcdeabcde', 6, 0)
======================
  ''
--it returns 4-length substrings counting from the position
SELECT SUBSTR('12345abcdeabcde', 6, 4), SUBSTR('12345abcdeabcde', -6, 4);
 substr('12345abcdeabcde', 6, 4)   substr('12345abcdeabcde', -6, 4)
============================================
  'abcd'                'eabc'
--it returns substrings counting from the position to the end
SELECT SUBSTR('12345abcdeabcde', 6), SUBSTR('12345abcdeabcde', -6);
 substr('12345abcdeabcde', 6)   substr('12345abcdeabcde', -6)
============================================
  'abcdeabcde'          'eabcde'
-- it returns 4-length substrings counting from 11th position
SELECT SUBSTR ('12345가나다라마가나다라마', 11 , 4);
 substr('12345가나다라마가나다라마', 11 , 4)
======================
  '가나다라'
SUBSTRING
SUBSTRING ( string, position [, substring_length]),
SUBSTRING( string FROM position [FOR substring_length] )

The SUBSTRING function, operating like SUBSTR, extracts a character string having the length of substring_length from a position, position, within character string, string, and returns it. If a negative number is specified as the position value, the SUBSTRING function calculates the position from the beginning of the string. And SUBSTR function calculates the position from the end of the string. If a negative number is specified as the substring_length value, the SUBSTRING function handles the argument is omitted, but the SUBSTR function returns NULL.

Parameters:
  • string -- Specifies the input character string. If the input value is NULL, NULL is returned.
  • position -- Specifies the position from where the string is to be extracted. If the position of the first character is specified as 0 or a negative number, it is considered as 1. If a value greater than the string length is specified, an empty string is returned. If NULL, NULL is returned.
  • substring_length -- Specifies the length of the string to be extracted. If this argument is omitted, character strings between the given position, position, and the end of them are extracted. NULL cannot be specified as an argument value of this function. If 0 is specified, an empty string is returned; if a negative value is specified, NULL is returned.
Return type:

STRING

SELECT SUBSTRING('12345abcdeabcde', -6 ,4), SUBSTR('12345abcdeabcde', -6 ,4);
  substring('12345abcdeabcde' from -6 for 4)   substr('12345abcdeabcde', -6, 4)
============================================
  '1234'                'eabc'
SELECT SUBSTRING('12345abcdeabcde', 16), SUBSTR('12345abcdeabcde', 16);
  substring('12345abcdeabcde' from 16)   substr('12345abcdeabcde', 16)
============================================
  ''                    NULL
SELECT SUBSTRING('12345abcdeabcde', 6, -4), SUBSTR('12345abcdeabcde', 6, -4);
  substring('12345abcdeabcde' from 6 for -4)   substr('12345abcdeabcde', 6, -4)
============================================
  'abcdeabcde'          NULL
SUBSTRING_INDEX
SUBSTRING_INDEX(string, delim, count)

The SUBSTRING_INDEX function counts the separators included in the partial character string and will return the partial character string before the count-th separator. The return value is a VARCHAR type.

Parameters:
  • string -- Input character string. The maximum length is 33,554,432 and if this length is exceeded, NULL will be returned.
  • delim -- Delimiter. It is case-sensitive.
  • count -- Delimiter occurrence count. If you enter a positive number, it counts the character string from the left and if you enter a negative number, it counts it from the right. If it is 0, an empty string will be returned. If the type cannot be converted, an error will be returned.
Return type:

STRING

SELECT SUBSTRING_INDEX('www.cubrid.org','.','2');
  substring_index('www.cubrid.org', '.', '2')
======================
  'www.cubrid'
SELECT SUBSTRING_INDEX('www.cubrid.org','.','2.3');
  substring_index('www.cubrid.org', '.', '2.3')
======================
  'www.cubrid'
SELECT SUBSTRING_INDEX('www.cubrid.org',':','2.3');
  substring_index('www.cubrid.org', ':', '2.3')
======================
  'www.cubrid.org'
SELECT SUBSTRING_INDEX('www.cubrid.org','cubrid',1);
  substring_index('www.cubrid.org', 'cubrid', 1)
======================
  'www.'
SELECT SUBSTRING_INDEX('www.cubrid.org','.',100);
  substring_index('www.cubrid.org', '.', 100)
======================
  'www.cubrid.org'
TO_BASE64
TO_BASE64(str)

Returns the result as the transformed base-64 string. If the input argument is not a string, it is changed into a string before it is transformed. If the input argument is NULL, it returns NULL. The base-64 encoded string can be decoded with FROM_BASE64() function.

Parameters:str -- Input string
Return type:STRING
SELECT TO_BASE64('abcd'), FROM_BASE64(TO_BASE64('abcd'));
   to_base64('abcd') from_base64( to_base64('abcd'))
============================================
  'YWJjZA==' 'abcd'

The following is rules for TO_BASE64() function and FROM_BASE64().

  • The encoded character for the alphabet value 62 is '+'.
  • The encoded character for the alphabet value 63 is '/'.
  • The encoded result consists of character groups, and each group has 4 characters which can be printed out. The 3 bytes of the input data are encoded into 4 bytes. If the last group are not filled with 4 characters, '=' character is padded into that group and 4 characters are made.
  • To divide the long output into the several lines, a newline is added into each 76 encoded output characters.
  • Decoding process indicates newline, carriage return, tab, and space and ignore them.

See also

FROM_BASE64()

TRANSLATE
TRANSLATE(string, from_substring, to_substring)

The TRANSLATE function replaces a character into the character specified in to_substring if the character exists in the specified string. Correspondence relationship is determined based on the order of characters specified in from_substring and to_substring. Any characters in from_substring that do not have one on one relationship to to_substring are all removed. This function is working like the REPLACE() but the argument of to_substring cannot be omitted in this function.

Parameters:
  • string -- Specifies the original string. If the value is NULL, NULL is returned.
  • from_substring -- Specifies the string to be retrieved. If the value is NULL, NULL is returned.
  • to_substring -- Specifies the character string in the from_substring to be replaced. It cannot be omitted. If the value is NULL, NULL is returned.
Return type:

STRING

--it returns NULL when an argument is specified with NULL value
SELECT TRANSLATE('12345abcdeabcde','abcde', NULL);
  translate('12345abcdeabcde', 'abcde', null)
======================
  NULL
--it translates 'a','b','c','d','e' into '1', '2', '3', '4', '5' respectively
SELECT TRANSLATE('12345abcdeabcde', 'abcde', '12345');
  translate('12345abcdeabcde', 'abcde', '12345')
======================
  '123451234512345'
--it translates 'a','b','c' into '1', '2', '3' respectively and removes 'd's and 'e's
SELECT TRANSLATE('12345abcdeabcde','abcde', '123');
  translate('12345abcdeabcde', 'abcde', '123')
======================
  '12345123123'
--it removes 'a's,'b's,'c's,'d's, and 'e's in the string
SELECT TRANSLATE('12345abcdeabcde','abcde', '');
  translate('12345abcdeabcde', 'abcde', '')
======================
  '12345'
--it only translates 'a','b','c' into '3', '4', '5' respectively
SELECT TRANSLATE('12345abcdeabcde','ABabc', '12345');
  translate('12345abcdeabcde', 'ABabc', '12345')
======================
  '12345345de345de'
TRIM
TRIM( [ [ LEADING | TRAILING | BOTH ] [ trim_string ] FROM ] string )

The TRIM function removes specific characters which are located before and after the string.

Parameters:
  • trim_string -- Specifies a specific string to be removed that is in front of or at the back of the target string. If it is not specified, an empty character (' ') is automatically specified so that spaces in front of or at the back of the target string are removed.
  • string -- Enters a string or string-type column to trim. If this value is NULL, NULL is returned.
Return type:

STRING

  • [LEADING|TRAILING|BOTH] : You can specify an option to trim a specified string that is in a certain position of the target string. If it is LEADING, trimming is performed in front of a character string if it is TRAILING, trimming is performed at the back of a character string if it is BOTH, trimming is performed in front and at the back of a character string. If the option is not specified, BOTH is specified by default.
  • The character string of trim_string and string should have the same character set.
--trimming NULL returns NULL
SELECT TRIM (NULL);
 trim(both  from null)
======================
  NULL
--trimming spaces on both leading and trailing parts
SELECT TRIM ('     Olympic     ');
 trim(both  from '     Olympic     ')
======================
  'Olympic'
--trimming specific strings on both leading and trailing parts
SELECT TRIM ('i' FROM 'iiiiiOlympiciiiii');
 trim(both 'i' from 'iiiiiOlympiciiiii')
======================
  'Olympic'
--trimming specific strings on the leading part
SELECT TRIM (LEADING 'i' FROM 'iiiiiOlympiciiiii');
 trim(leading 'i' from 'iiiiiOlympiciiiii')
======================
  'Olympiciiiii'
--trimming specific strings on the trailing part
SELECT TRIM (TRAILING 'i' FROM 'iiiiiOlympiciiiii');
 trim(trailing 'i' from 'iiiiiOlympiciiiii')
======================
  'iiiiiOlympic'
UCASE, UPPER
UCASE(string)
UPPER(string)

The function UCASE or UPPER converts lowercase characters that are included in a character string to uppercase characters.

Parameters:string -- Specifies the string in which lowercase characters are to be converted to uppercase. If the value is NULL, NULL is returned.
Return type:STRING
SELECT UPPER('');
 upper('')
======================
  ''
SELECT UPPER(NULL);
 upper(null)
======================
  NULL
SELECT UPPER('Cubrid');
 upper('Cubrid')
======================
  'CUBRID'

Note that the UPPER function may not work properly by specified collation. For example, when you try to change character 'ă' used in Romanian as upper character, this function works as follows by collation.

If collation is utf8_bin, it is not changed.

SET NAMES utf8 COLLATE utf8_bin;
SELECT UPPER('ă');

   upper(_utf8'ă')
======================
  'ă'

If collation is utf8_ro_RO, this can be changed.

SET NAMES utf8 COLLATE utf8_ro_cs;
SELECT UPPER('ă');

   upper(_utf8'ă' COLLATE utf8_ro_cs)
======================
  'Ă'

Regarding collations which CUBRID supports, see CUBRID Collation.

Numeric/Mathematical Functions
ABS
ABS(number_expr)

The ABS function returns the absolute value of a given number. The data type of the return value is the same as that of the argument. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:number_expr -- An operator which returns a numeric value
Return type:same as that of the argument
--it returns the absolute value of the argument
SELECT ABS(12.3), ABS(-12.3), ABS(-12.3000), ABS(0.0);
  abs(12.3)             abs(-12.3)            abs(-12.3000)         abs(0.0)
================================================================================
  12.3                  12.3                  12.3000               .0
ACOS
ACOS(x)

The ACOS function returns an arc cosine value of the argument. That is, it returns a value whose cosine is x in radian. The return value is a DOUBLE type. x must be a value between -1 and 1, inclusive. Otherwise, NULL is returned. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a numeric value
Return type:DOUBLE
SELECT ACOS(1), ACOS(0), ACOS(-1);
  acos(1)                   acos(0)                  acos(-1)
==================================================================================
  0.000000000000000e+00     1.570796326794897e+00     3.141592653589793e+00
ASIN
ASIN(x)

The ASIN function returns an arc sine value of the argument. That is, it returns a value whose sine is x in radian. The return value is a DOUBLE type. x must be a value between -1 and 1, inclusive. Otherwise, NULL is returned. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a numeric value
Return type:DOUBLE
SELECT ASIN(1), ASIN(0), ASIN(-1);
  asin(1)                   asin(0)                  asin(-1)
==============================================================================
  1.570796326794897e+00     0.000000000000000e+00    -1.570796326794897e+00
ATAN
ATAN([y, ]x)

The ATAN function returns a value whose tangent is x in radian. The argument y can be omitted. If y is specified, the function calculates the arc tangent value of y/x. The return value is a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x,y -- An expression that returns a numeric value
Return type:DOUBLE
SELECT ATAN(1), ATAN(-1), ATAN(1,-1);
                   atan(1)                  atan(-1)              atan2(1, -1)
==============================================================================
     7.853981633974483e-01    -7.853981633974483e-01     2.356194490192345e+000
ATAN2
ATAN2(y, x)

The ATAN2 function returns the arc tangent value of y/x in radian. This function is working like the ATAN(). Arguments x and y must be specified. The return value is a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x,y -- An expression that returns a numeric value
Return type:DOUBLE
SELECT ATAN2(1,1), ATAN2(-1,-1), ATAN2(Pi(),0);
atan2(1, 1)             atan2(-1, -1)           atan2( pi(), 0)
==============================================================================
 7.853981633974483e-01    -2.356194490192345e+00     1.570796326794897e+00
CEIL
CEIL(number_operand)

The CEIL function returns the smallest integer that is not less than its argument. The return value is determined based on the valid number of digits that are specified as the number_operand argument. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:number_operand -- An expression that returns a numeric value
Return type:INT
SELECT CEIL(34567.34567), CEIL(-34567.34567);
  ceil(34567.34567)     ceil(-34567.34567)
============================================
  34568.00000           -34567.00000

SELECT CEIL(34567.1), CEIL(-34567.1);
  ceil(34567.1)         ceil(-34567.1)
=============================
  34568.0         -34567.0
CONV
CONV(number, from_base, to_base)

The CONV function converts numbers between different number bases. This function returns a string representation of a converted number. The minimum value is 2 and the maximum value is 36. If to_base (representing the base to be returned) is negative, number is regarded as a signed number. Otherwise, it regarded as a unsigned number. When you input the string which cannot be transformed into the number to from_base or to_base, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:
  • number -- An input number
  • from_base -- The base of an input number
  • to_base -- The base of an returned value
Return type:

STRING

SELECT CONV('f',16,2);
'1111'
SELECT CONV('6H',20,8);
'211'
SELECT CONV(-30,10,-20);
'-1A'
COS
COS(x)

The COS function returns a cosine value of the argument. The argument x must be a radian value. The return value is a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a numeric value
Return type:DOUBLE
SELECT COS(pi()/6), COS(pi()/3), COS(pi());
  cos( pi()/6)              cos( pi()/3)                cos( pi())
==============================================================================
  8.660254037844387e-01     5.000000000000001e-01    -1.000000000000000e+00
COT
COT(x)

The COT function returns the cotangent value of the argument x. That is, it returns a value whose tangent is x in radian. The return value is a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a numeric value
Return type:DOUBLE
SELECT COT(1), COT(-1), COT(0);
  cot(1)                   cot(-1)   cot(0)
==========================================================================
  6.420926159343306e-01    -6.420926159343306e-01  NULL
CRC32
CRC32(string)

The CRC32 function returns a cyclic redundancy check value as 32-bit integer. When NULL is given as input, it returns NULL.

Parameters:string -- An expression that returns a string value
Return type:INTEGER
SELECT CRC32('cubrid');
   crc32('cubrid')
==================
         908740081
DEGREES
DEGREES(x)

The DEGREES function returns the argument x specified in radian converted to a degree value. The return value is a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a numeric value
Return type:DOUBLE
SELECT DEGREES(pi()/6), DEGREES(pi()/3), DEGREES (pi());
  degrees( pi()/6)          degrees( pi()/3)            degrees( pi())
==============================================================================
  3.000000000000000e+01     5.999999999999999e+01     1.800000000000000e+02
DRANDOM, DRAND
DRANDOM([seed])
DRAND([seed])

The function DRANDOM or DRAND returns a random double-precision floating point value in the range of between 0.0 and 1.0. A seed argument that is INTEGER type can be specified. It rounds up real numbers and an error is returned when it exceeds the range of INTEGER.

When seed value is not given, the DRAND function performs the operation only once to produce only one random number regardless of the number of rows where the operation is output, but the DRANDOM function performs the operation every time the statement is repeated to produce a different random value for each row. Therefore, to output rows in a random order, you must use the DRANDOM function in the ORDER BY clause. To obtain a random integer value, use the RANDOM().

Parameters:seed -- seed value
Return type:DOUBLE
SELECT DRAND(), DRAND(1), DRAND(1.4);
                   drand()                  drand(1)                drand(1.4)
==============================================================================
    2.849646518006921e-001    4.163034446537495e-002    4.163034446537495e-002
CREATE TABLE rand_tbl (
    id INT,
    name VARCHAR(255)
);

INSERT INTO rand_tbl VALUES
    (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'),
    (6, 'f'), (7, 'g'), (8, 'h'), (9, 'i'), (10, 'j');

SELECT * FROM rand_tbl;
           id  name
===================================
            1  'a'
            2  'b'
            3  'c'
            4  'd'
            5  'e'
            6  'f'
            7  'g'
            8  'h'
            9  'i'
           10  'j'
--drandom() returns random values on every row
SELECT DRAND(), DRANDOM() FROM rand_tbl;
   drand()                 drandom()
==============================================================================
   7.638782921842098e-001    1.018707846308786e-001
   7.638782921842098e-001    3.191320535905026e-001
   7.638782921842098e-001    3.461714529862361e-001
   7.638782921842098e-001    6.791894283883175e-001
   7.638782921842098e-001    4.533829767754143e-001
   7.638782921842098e-001    1.714224677266762e-001
   7.638782921842098e-001    1.698049867244484e-001
   7.638782921842098e-001    4.507583849604786e-002
   7.638782921842098e-001    5.279091769157994e-001
   7.638782921842098e-001    7.021088290047914e-001
--selecting rows in random order
SELECT * FROM rand_tbl ORDER BY DRANDOM();
           id  name
===================================
            6  'f'
            2  'b'
            7  'g'
            8  'h'
            1  'a'
            4  'd'
           10  'j'
            9  'i'
            5  'e'
            3  'c'
EXP
EXP(x)

The EXP function returns e x (the base of natural logarithm) raised to a power. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An operator which returns a numeric value
Return type:DOUBLE
SELECT EXP(1), EXP(0);
  exp(1)                    exp(0)
====================================================
  2.718281828459045e+000 1.000000000000000e+000
SELECT EXP(-1), EXP(2.00);
  exp(-1)                 exp(2.00)
====================================================
  3.678794411714423e-001 7.389056098930650e+000
FLOOR
FLOOR(number_operand)

The FLOOR function returns the largest integer that is not greater than its argument. The data type of the return value is the same as that of the argument. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:number_operand -- An operator which returns a numeric value
Return type:same as that of the argument
--it returns the largest integer less than or equal to the arguments
SELECT FLOOR(34567.34567), FLOOR(-34567.34567);
  floor(34567.34567)    floor(-34567.34567)
============================================
  34567.00000           -34568.00000
SELECT FLOOR(34567), FLOOR(-34567);
  floor(34567)   floor(-34567)
=============================
         34567         -34567
HEX
HEX(n)

The HEX function returns a hexadecimal string about the string which is specified as an argument; it returns a hexadecimal string of the number if a number is specified as an argument. If a number is specified as an argument, it returns a value like CONV(num, 10, 16).

Parameters:n -- A string or a number
Return type:STRING
SELECT HEX('ab'), HEX(128), CONV(HEX(128), 16, 10);
hex('ab')             hex(128)              conv(hex(128), 16, 10)
==================================================================
  '6162'                '80'                  '128'
LN
LN(x)

The LN function returns the natural log value (base = e) of an antilogarithm x. The return value is a DOUBLE type. If the antilogarithm is 0 or a negative number, an error is returned. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a positive number
Return type:DOUBLE
SELECT ln(1), ln(2.72);
     ln(1)                     ln(2.72)
=====================================================
     0.000000000000000e+00     1.000631880307906e+00
LOG2
LOG2(x)

The LOG2 function returns a log value whose antilogarithm is x and base is 2. The return value is a DOUBLE type. If the antilogarithm is 0 or a negative number, an error is returned. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a positive number
Return type:DOUBLE
SELECT log2(1), log2(8);
     log2(1)                   log2(8)
======================================================
     0.000000000000000e+00     3.000000000000000e+00
LOG10
LOG10(x)

The LOG10 function returns the common log value of an antilogarithm x. The return value is a DOUBLE type. If the antilogarithm is 0 or a negative number, an error is returned. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a positive number
Return type:DOUBLE
SELECT log10(1), log10(1000);
     log10(1)                  log10(1000)
====================================================
     0.000000000000000e+00     3.000000000000000e+00
MOD
MOD(m, n)

The MOD function returns the remainder of the first parameter m divided by the second parameter n. If n is 0, m is returned without the division operation being performed. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Note that if the dividend, the parameter m of the MOD function, is a negative number, the function operates differently from a typical operation (classical modulus) method.

Result of MOD

m n MOD(m, n) Classical Modulus m-n*FLOOR(m/n)
11 4 3 3
11 -4 3 -1
-11 4 -3 1
-11 -4 -3 -3
11 0 11 Divided by 0 error
Parameters:
  • m -- Represents a dividend. It is an expression that returns a numeric value.
  • n -- Represents a divisor. It is an expression that returns a numeric value.
Return type:

INT

--it returns the reminder of m divided by n
SELECT MOD(11, 4), MOD(11, -4), MOD(-11, 4), MOD(-11, -4), MOD(11,0);
    mod(11, 4)   mod(11, -4)   mod(-11, 4)   mod(-11, -4)   mod(11, 0)
=====================================================================
            3             3            -3             -3           11
SELECT MOD(11.0, 4), MOD(11.000, 4), MOD(11, 4.0), MOD(11, 4.000);
  mod(11.0, 4)          mod(11.000, 4)        mod(11, 4.0)          mod(11, 4.000)
=========================================================================
  3.0                   3.000                 3.0                   3.000
PI
PI()

The PI function returns the ? value of type DOUBLE.

Return type:DOUBLE
SELECT PI(), PI()/2;
     pi()                      pi()/2
====================================================
     3.141592653589793e+00     1.570796326794897e+00
POW, POWER
POW(x, y)
POWER(x, y)

The POW function returns x to the power of y. The functions POW and POWER are used interchangeably. The return value is a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:
  • x -- It represents the base. It is an expression that returns a numeric value. An expression that returns a numeric value.
  • y -- It represents the exponent. An expression that returns a numeric value. If the base is a negative number, an integer must specified as the exponent.
Return type:

DOUBLE

SELECT POWER(2, 5), POWER(-2, 5), POWER(0, 0), POWER(1,0);
 power(2, 5)              power(-2, 5)               power(0, 0)               power(1, 0)
====================================================================================================
 3.200000000000000e+01    -3.200000000000000e+01     1.000000000000000e+00     1.000000000000000e+00
--it returns an error when the negative base is powered by a non-int exponent
SELECT POWER(-2, -5.1), POWER(-2, -5.1);
ERROR: Argument of power() is out of range.
RADIANS
RADIANS(x)

The RADIANS function returns the argument x specified in degrees converted to a radian value. The return value is a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a numeric value
Return type:DOUBLE
SELECT RADIANS(90), RADIANS(180), RADIANS(360);
     radians(90)               radians(180)              radians(360)
==============================================================================
     1.570796326794897e+00     3.141592653589793e+00     6.283185307179586e+00
RANDOM, RAND
RANDOM([seed])
RAND([seed])

The function RANDOM or RAND returns any integer value, which is greater than or equal to 0 and less than 2 31, and a seed argument that is INTEGER type can be specified. It rounds up real numbers and an error is returned when it exceeds the range of INTEGER.

When seed value is not given, the RAND function performs the operation only once to produce only one random number regardless of the number of rows where the operation is output, but the RANDOM function performs the operation every time the statement is repeated to produce a different random value for each row. Therefore, to output rows in a random order, you must use the RANDOM function.

To obtain a random real number, use the DRANDOM().

Parameters:seed --
Return type:INT
SELECT RAND(), RAND(1), RAND(1.4);
       rand()      rand(1)    rand(1.4)
=======================================
   1526981144     89400484     89400484
--creating a new table
SELECT * FROM rand_tbl;
           id  name
===================================
            1  'a'
            2  'b'
            3  'c'
            4  'd'
            5  'e'
            6  'f'
            7  'g'
            8  'h'
            9  'i'
           10  'j'
--random() returns random values on every row
SELECT RAND(),RANDOM() FROM rand_tbl;
       rand()       random()
============================
   2078876566     1753698891
   2078876566     1508854032
   2078876566      625052132
   2078876566      279624236
   2078876566     1449981446
   2078876566     1360529082
   2078876566     1563510619
   2078876566     1598680194
   2078876566     1160177096
   2078876566     2075234419
--selecting rows in random order
SELECT * FROM rand_tbl ORDER BY RANDOM();
           id  name
===================================
            6  'f'
            1  'a'
            5  'e'
            4  'd'
            2  'b'
            7  'g'
           10  'j'
            9  'i'
            3  'c'
            8  'h'
ROUND
ROUND(number_operand, integer)

The ROUND function returns the specified argument, number_operand, rounded to the number of places after the decimal point specified by the integer. If the integer argument is a negative number, it rounds to a place before the decimal point, that is, at the integer part. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:
  • number_operand -- An expression that returns a numeric value
  • integer -- Specifies the place to round to. If a positive integer n is specified, the number is represented to the nth place after the decimal point; if a negative integer n is specified, the number is rounded to the n th place before the decimal point.
Return type:

same type as the number_operand

--it rounds a number to one decimal point when the second argument is omitted
SELECT ROUND(34567.34567), ROUND(-34567.34567);
  round(34567.34567, 0)   round(-34567.34567, 0)
============================================
  34567.00000           -34567.00000
--it rounds a number to three decimal point
SELECT ROUND(34567.34567, 3), ROUND(-34567.34567, 3)  FROM db_root;
 round(34567.34567, 3)   round(-34567.34567, 3)
============================================
  34567.34600           -34567.34600
--it rounds a number three digit to the left of the decimal point
SELECT ROUND(34567.34567, -3), ROUND(-34567.34567, -3);
 round(34567.34567, -3)   round(-34567.34567, -3)
============================================
  35000.00000           -35000.00000
SIGN
SIGN(number_operand)

The SIGN function returns the sign of a given number. It returns 1 for a positive value, -1 for a negative value, and 0 for zero. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:number_operand -- An operator which returns a numeric value
Return type:INT
--it returns the sign of the argument
SELECT SIGN(12.3), SIGN(-12.3), SIGN(0);
    sign(12.3)   sign(-12.3)      sign(0)
========================================
            1            -1            0
SIN
SIN(x)

The SIN function returns a sine value of the parameter. The argument x must be a radian value. The return value is a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a numeric value
Return type:DOUBLE
SELECT SIN(pi()/6), SIN(pi()/3), SIN(pi());
     sin( pi()/6)              sin( pi()/3)              sin( pi())
==============================================================================
     4.999999999999999e-01     8.660254037844386e-01     1.224646799147353e-16
SQRT
SQRT(x)

The SQRT function returns the square root of x as a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a numeric value. An error is returned if this value is a negative number.
Return type:DOUBLE
SELECT SQRT(4), SQRT(16.0);
     sqrt(4)                   sqrt(16.0)
====================================================
     2.000000000000000e+00     4.000000000000000e+00
TAN
TAN(x)

The TAN function returns a tangent value of the argument. The argument x must be a radian value. The return value is a DOUBLE type. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:x -- An expression that returns a numeric value
Return type:DOUBLE
SELECT TAN(pi()/6), TAN(pi()/3), TAN(pi()/4);
     tan( pi()/6)              tan( pi()/3)              tan( pi()/4)
==============================================================================
     5.773502691896257e-01     1.732050807568877e+00     9.999999999999999e-01
TRUNC, TRUNCATE
TRUNC(x[, dec])
TRUNCATE(x, dec)

The function TRUNC or TRUNCATE truncates the numbers of the specified argument x to the right of the dec position. If the dec argument is a negative number, it displays 0s to the dec- th position left to the decimal point. Note that the dec argument of the TRUNC function can be omitted, but that of the TRUNCATE function cannot be omitted. If the dec argument is a negative number, it displays 0s to the dec -th position left to the decimal point. The number of digits of the return value to be represented follows the argument x. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

Parameters:
  • x -- An expression that returns a numeric value
  • dec -- The place to be truncated is specified. If a positive integer n is specified, the number is represented to the n-th place after the decimal point; if a negative integer n is specified, the number is truncated to the n-th place before the decimal point. It truncates to the first place after the decimal point if the dec argument is 0 or omitted. Note that the dec argument cannot be omitted in the TRUNCATE function.
Return type:

same type as the x

--it returns a number truncated to 0 places
SELECT TRUNC(34567.34567), TRUNCATE(34567.34567, 0);
  trunc(34567.34567, 0)   trunc(34567.34567, 0)
============================================
  34567.00000            34567.00000
--it returns a number truncated to three decimal places
SELECT TRUNC(34567.34567, 3), TRUNC(-34567.34567, 3);
  trunc(34567.34567, 3)   trunc(-34567.34567, 3)
============================================
  34567.34500           -34567.34500
--it returns a number truncated to three digits left of the decimal point
SELECT TRUNC(34567.34567, -3), TRUNC(-34567.34567, -3);
  trunc(34567.34567, -3)   trunc(-34567.34567, -3)
============================================
  34000.00000           -34000.00000
WIDTH_BUCKET
WIDTH_BUCKET(expression, from, to, num_buckets)

WIDTH_BUCKET distributes the rows in an ordered partition into a specified number of buckets. The buckets are numbered, starting from one. That is, WIDTH_BUCKET function creates an equi-width histogram. The return value is an integer. When you input the string which cannot be transformed into the number, it returns an error if the value of return_null_on_function_errors in cubrid.conf is no(the default), or returns NULL if it is yes.

This function equally divides the range by the given number of buckets and assigns the bucket number to each bucket. That is, every interval (bucket) has the identical size.

Note that NTILE() function equally divides the number of rows by the given number of buckets and assigns the bucket number to each bucket. That is, every bucket has the same number of rows.

Parameters:
  • expression -- an input value to assign the bucket number. It specifies a certain expression which returns the number.
  • from -- a start value of the range, which is given to expression. It is included in the entire range.
  • to -- an end value of the range, which is given to expression. It is not included in the entire range.
  • num_buckets -- the number of buckets. The #0 bucket and the #(num_buckets + 1) bucket are created to include the contents beyond the range.
Return type:

INT

expression is an input value to assign the bucket number. from and to should be numeric values, date/time values, or the string which can be converted to date/time value. from is included in the acceptable range, but to is beyond the range.

For example, WIDTH_BUCKET (score, 80, 50, 3) returns

  • 0 when the score is larger than 80,
  • 1 for [80, 70),
  • 2 for [70, 60),
  • 3 for [60, 50),
  • and 4 when the score is 50 or smaller.

The following example divides the range equal to 80 or smaller and larger than 50 into the score range that has the identical score range from 1 to 3. If any score is beyond the range, 0 is given for the score larger than 80 and 4 is given for the score of 50 or smaller than 50.

CREATE TABLE t_score (name VARCHAR(10), score INT);
INSERT INTO t_score VALUES
    ('Amie', 60),
    ('Jane', 80),
    ('Lora', 60),
    ('James', 75),
    ('Peter', 70),
    ('Tom', 50),
    ('Ralph', 99),
    ('David', 55);

SELECT name, score, WIDTH_BUCKET (score, 80, 50, 3) grade
FROM t_score
ORDER BY grade ASC, score DESC;
  name                        score        grade
================================================
  'Ralph'                        99            0
  'Jane'                         80            1
  'James'                        75            1
  'Peter'                        70            2
  'Amie'                         60            3
  'Lora'                         60            3
  'David'                        55            3
  'Tom'                          50            4

In the following example, WIDTH_BUCKET function evenly divides the birthdate range into buckets and assigns the bucket number based on the range. It divides the range of eight customers from '1950-01-01' to '1999-12-31' into five buckets based on their dates of birth. If the birthdate value is beyond the range, 0 or 6 (num_buckets + 1) is returned.

CREATE TABLE t_customer (name VARCHAR(10), birthdate DATE);
INSERT INTO t_customer VALUES
    ('Amie', date'1978-03-18'),
    ('Jane', date'1983-05-12'),
    ('Lora', date'1987-03-26'),
    ('James', date'1948-12-28'),
    ('Peter', date'1988-10-25'),
    ('Tom', date'1980-07-28'),
    ('Ralph', date'1995-03-17'),
    ('David', date'1986-07-28');

SELECT name, birthdate, WIDTH_BUCKET (birthdate, date'1950-01-01', date'2000-1-1', 5) age_group
FROM t_customer
ORDER BY birthdate;
  name                  birthdate     age_group
===============================================
  'James'               12/28/1948            0
  'Amie'                03/18/1978            4
  'Tom'                 07/28/1980            4
  'Jane'                05/12/1983            5
  'David'               07/28/1986            5
  'Lora'                03/26/1987            5
  'Peter'               10/25/1988            5
  'Ralph'               03/17/1995            6
Date/Time Functions and Operators
ADDDATE, DATE_ADD
ADDDATE(date, INTERVAL expr unit)
ADDDATE(date, days)
DATE_ADD(date, INTERVAL expr unit)

The ADDDATE function performs an addition or subtraction operation on a specific DATE value; ADDDATE and DATE_ADD are used interchangeably. The return value is a DATE or DATETIME type. The DATETIME type is returned in the following cases.

  • The first argument is a DATETIME or TIMESTAMP type
  • The first argument is a DATE type and the unit of INTERVAL value specified is less than the unit of day

Therefore, to return value of DATETIME type, you should convert the value of first argument by using the CAST function. Even though the date resulting from the operation exceeds the last day of the month, the function returns a valid DATE value considering the last date of the month.

If every input argument value of date and time is 0, the return value is determined by the return_null_on_function_errors system parameter; if it is set to yes, then NULL is returned; if it is set to no, an error is returned. The default value is no.

If the calculated value is between '0000-00-00 00:00:00' and '0001-01-01 00:00:00', a value having 0 for all arguments is returned in DATE or DATETIME type. Note that operation in JDBC program is determined by the configuration of zeroDateTimeBehavior, connection URL property. For more information about JDBC connection URL, please see Configuration Connection.

Parameters:
  • date -- It is a DATE, TIMETIME, or TIMESTAMP expression that represents the start date. If an invalid DATE value such as '2006-07-00' is specified, an error is returned.
  • expr -- It represents the interval value to be added to the start date. If a negative number is specified next to the INTERVAL keyword, the interval value is subtracted from the start date.
  • unit -- It represents the unit of the interval value specified in the expr expression. See the following table to specify the format for the interpretation of the interval value. If the value of expr unit is less than the number requested in the unit, it is specified from the smallest unit. For example, if it is HOUR_SECOND, three values such as 'HOURS:MINUTES:SECONDS' are required. In the case, if only two values such as "1:1" are given, it is regarded as 'MINUTES:SECONDS'.
Return type:

DATE or DATETIME

Format of expr for unit

unit Value expr Format Example
MILLISECOND MILLISECONDS ADDDATE(SYSDATE, INTERVAL 123 MILLISECOND)
SECOND SECONDS ADDDATE(SYSDATE, INTERVAL 123 SECOND)
MINUTE MINUTES ADDDATE(SYSDATE, INTERVAL 123 MINUTE)
HOUR HOURS ADDDATE(SYSDATE, INTERVAL 123 HOUR)
DAY DAYS ADDDATE(SYSDATE, INTERVAL 123 DAY)
WEEK WEEKS ADDDATE(SYSDATE, INTERVAL 123 WEEK)
MONTH MONTHS ADDDATE(SYSDATE, INTERVAL 12 MONTH)
QUARTER QUARTERS ADDDATE(SYSDATE, INTERVAL 12 QUARTER)
YEAR YEARS ADDDATE(SYSDATE, INTERVAL 12 YEAR)
SECOND_MILLISECOND 'SECONDS.MILLISECONDS' ADDDATE(SYSDATE, INTERVAL '12.123' SECOND_MILLISECOND)
MINUTE_MILLISECOND 'MINUTES:SECONDS.MILLISECONDS' ADDDATE(SYSDATE, INTERVAL '12:12.123' MINUTE_MILLISECOND)
MINUTE_SECOND 'MINUTES:SECONDS' ADDDATE(SYSDATE, INTERVAL '12:12' MINUTE_SECOND)
HOUR_MILLISECOND 'HOURS:MINUTES:SECONDS.MILLISECONDS' ADDDATE(SYSDATE, INTERVAL '12:12:12.123' HOUR_MILLISECOND)
HOUR_SECOND 'HOURS:MINUTES:SECONDS' ADDDATE(SYSDATE, INTERVAL '12:12:12' HOUR_SECOND)
HOUR_MINUTE 'HOURS:MINUTES' ADDDATE(SYSDATE, INTERVAL '12:12' HOUR_MINUTE)
DAY_MILLISECOND 'DAYS HOURS:MINUTES:SECONDS.MILLISECONDS' ADDDATE(SYSDATE, INTERVAL '12 12:12:12.123' DAY_MILLISECOND)
DAY_SECOND 'DAYS HOURS:MINUTES:SECONDS' ADDDATE(SYSDATE, INTERVAL '12 12:12:12' DAY_SECOND)
DAY_MINUTE 'DAYS HOURS:MINUTES' ADDDATE(SYSDATE, INTERVAL '12 12:12' DAY_MINUTE)
DAY_HOUR 'DAYS HOURS' ADDDATE(SYSDATE, INTERVAL '12 12' DAY_HOUR)
YEAR_MONTH 'YEARS-MONTHS' ADDDATE(SYSDATE, INTERVAL '12-13' YEAR_MONTH)
SELECT SYSDATE, ADDDATE(SYSDATE,INTERVAL 24 HOUR), ADDDATE(SYSDATE, 1);
03/30/2010  12:00:00.000 AM 03/31/2010               03/31/2010
--it subtracts days when argument < 0
SELECT SYSDATE, ADDDATE(SYSDATE,INTERVAL -24 HOUR), ADDDATE(SYSDATE, -1);
03/30/2010  12:00:00.000 AM 03/29/2010               03/29/2010
--when expr is not fully specified for unit
SELECT SYS_DATETIME, ADDDATE(SYS_DATETIME, INTERVAL '1:20' HOUR_SECOND);
06:18:24.149 PM 06/28/2010     06:19:44.149 PM 06/28/2010
SELECT ADDDATE('0000-00-00', 1 );
ERROR: Conversion error in date format.
SELECT ADDDATE('0001-01-01 00:00:00', -1);
'12:00:00.000 AM 00/00/0000'
ADDTIME
ADDTIME(expr1, expr2)

The ADDTIME function adds or subtracts a value of specific time. The first argument is DATE, DATETIME, TIMESTAMP, or TIME type and the second argument is TIME, DATETIME, or TIMESTAMP type. Time should be included in the second argument, and the date of the second argument is ignored. The return type for each argument type is follows:

First Argument Type Second Argument Type Return Type Note
TIME TIME, DATETIME, TIMESTAMP TIME The result value must be equal to or less than 24 hours.
DATE TIME, DATETIME, TIMESTAMP DATETIME  
DATETIME TIME, DATETIME, TIMESTAMP DATETIME  
date/time string TIME, DATETIME, TIMESTAMP or time string VARCHAR The result string includes time.
Parameters:
  • expr1 -- DATE, DATETIME, TIME or TIMESTAMP type
  • expr2 -- DATETIME, TIMESTAMP, TIME type or date/time string
SELECT ADDTIME(datetime'2007-12-31 23:59:59', time'1:1:2');
01:01:01.000 AM 01/01/2008
SELECT ADDTIME(time'01:00:00', time'02:00:01');
03:00:01 AM
ADD_MONTHS
ADD_MONTHS(date_argument, month)

The ADD_MONTHS function adds a month value to the expression date_argument of DATE type, and it returns a DATE type value. If the day (dd) of the value specified as an argument exists within the month of the result value of the operation, it returns the given day (dd); otherwise returns the last day of the given month (dd). If the result value of the operation exceeds the expression range of the DATE type, it returns an error.

Parameters:
  • date_argument -- Specifies an expression of DATE type. To specify a TIMESTAMP or DATETIME value, an explicit casting to DATE type is required. If the value is NULL, NULL is returned.
  • month -- Specifies the number of the months to be added to the date_argument. Both positive and negative values can be specified. If the given value is not an integer type, conversion to an integer type by an implicit casting (rounding to the first place after the decimal point) is performed. If the value is NULL, NULL is returned.
--it returns DATE type value by adding month to the first argument
SELECT ADD_MONTHS(DATE '2008-12-25', 5), ADD_MONTHS(DATE '2008-12-25', -5);
05/25/2009                         07/25/2008
SELECT ADD_MONTHS(DATE '2008-12-31', 5.5), ADD_MONTHS(DATE '2008-12-31', -5.5);
06/30/2009                           06/30/2008
SELECT ADD_MONTHS(CAST (SYS_DATETIME AS DATE), 5), ADD_MONTHS(CAST (SYS_TIMESTAMP AS DATE), 5);
07/03/2010                                     07/03/2010

The following are examples of using timezone type values. For timezone related description, see Date/Time Types with Timezone.

SELECT ADD_MONTHS (datetimeltz'2001-10-11 10:11:12', 1);
11/11/2001
SELECT ADD_MONTHS (datetimetz'2001-10-11 10:11:12 Europe/Paris', 1);
11/11/2001
SELECT ADD_MONTHS (timestampltz'2001-10-11 10:11:12', 1);
11/11/2001
SELECT ADD_MONTHS (timestamptz'2001-10-11 10:11:12 Europe/Paris', 1);
11/11/2001
CURDATE, CURRENT_DATE
CURDATE()
CURRENT_DATE()
CURRENT_DATE

CURDATE (), CURRENT_DATE and CURRENT_DATE () are used interchangeably and they return the current date of session as the DATE type (MM/DD/YYYY or YYYY-MM-DD). The unit is day. When the time zone of the current session is same as that of server, these functions are same as SYS_DATE, SYSDATE. Please refer SYS_DATE, SYSDATE and the following examples to find a difference and DBTIMEZONE(), SESSIONTIMEZONE() for details of the functions.

If input every argument value of year, month, and day is 0, the return value is determined by the return_null_on_function_errors system parameter; if it is set to yes, then NULL is returned; if it is set to no, an error is returned. The default value is no.

Return type:DATE
SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'Asia/Seoul'

-- it returns the current date in DATE type

SELECT CURDATE(), CURRENT_DATE(), CURRENT_DATE, SYS_DATE, SYSDATE;

   CURRENT_DATE    CURRENT_DATE    CURRENT_DATE    SYS_DATE    SYS_DATE
========================================================================
  02/05/2016      02/05/2016      02/05/2016      02/05/2016  02/05/2016
-- it returns the date 60 days added to the current date

SELECT CURDATE()+60;

   CURRENT_DATE +60
===================
  04/05/2016
-- change session time from 'Asia/Seoul' to 'America/Los_Angeles'

SET TIME ZONE 'America/Los_Angeles';

SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'America/Los_Angeles'

-- Note that CURDATE() and SYS_DATE returns different results

SELECT CURDATE(), CURRENT_DATE(), CURRENT_DATE, SYS_DATE, SYSDATE;

   CURRENT_DATE    CURRENT_DATE    CURRENT_DATE    SYS_DATE    SYS_DATE
========================================================================
  02/04/2016      02/04/2016      02/04/2016      02/05/2016  02/05/2016

Warning

As 10.0, CURDATE (), CURRENT_DATE, CURRENT_DATE () are different from SYS_DATE and SYSDATE. They are synonym for 9.x and lower.

CURRENT_DATETIME, NOW
CURRENT_DATETIME()
CURRENT_DATETIME
NOW()

CURRENT_DATETIME, CURRENT_DATETIME () and NOW () are used interchangeably, and they return the current date and time of session in DATETIME type. The unit is millisecond. When the time zone of the current session is same as that of server, these functions are same as SYS_DATETIME, SYSDATETIME. Please also refer SYS_DATETIME, SYSDATETIME to find a difference and DBTIMEZONE(), SESSIONTIMEZONE() for details of the functions.

Return type:DATETIME
SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'Asia/Seoul'

-- it returns the current date and time in DATETIME type

SELECT NOW(), SYS_DATETIME;

   CURRENT_DATETIME               SYS_DATETIME
==============================================================
  04:05:09.292 PM 02/05/2016     04:05:09.292 PM 02/05/2016
-- it returns the timestamp value 1 hour added to the current sys_datetime value

SELECT TO_CHAR(SYSDATETIME+3600*1000, 'YYYY-MM-DD HH24:MI');

   to_char( SYS_DATETIME +3600*1000, 'YYYY-MM-DD HH24:MI')
======================
  '2016-02-05 17:05'
-- change session time from 'Asia/Seoul' to 'America/Los_Angeles'

set time zone 'America/Los_Angeles';

SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'America/Los_Angeles'

-- Note that NOW() and SYS_DATETIME return different results

SELECT NOW(), SYS_DATETIME;

   CURRENT_DATETIME               SYS_DATETIME
==============================================================
  11:08:57.041 PM 02/04/2016     04:08:57.041 PM 02/05/2016

Warning

As 10.0, CURRENT_DATETIME (), NOW () are different from SYS_DATEIME, SYSDATETIME. They are synonym for 9.x and lower.

CURTIME, CURRENT_TIME
CURTIME()
CURRENT_TIME
CURRENT_TIME()

CURTIME (), CURRENT_TIME and CURRENT_TIME () are used interchangeably and they return the current time of session as TIME type (HH:MI:SS). The unit is second. When the time zone of the current session is same as that of server, these functions are same as SYS_TIME, SYSTIME. Please also refer SYS_TIME, SYSTIME to find a difference and DBTIMEZONE(), SESSIONTIMEZONE() for details of the functions.

Return type:TIME
SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'Asia/Seoul'

-- it returns the current time in TIME type

SELECT CURTIME(), CURRENT_TIME(), CURRENT_TIME, SYS_TIME, SYSTIME;

   CURRENT_TIME    CURRENT_TIME    CURRENT_TIME    SYS_TIME     SYS_TIME
==========================================================================
  04:22:54 PM     04:22:54 PM     04:22:54 PM     04:22:54 PM  04:22:54 PM
-- change session time from 'Asia/Seoul' to 'America/Los_Angeles'

SET TIME ZONE 'AMERICA/LOS_ANGELES';

SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'America/Los_Angeles'

-- Note that CURTIME() and SYS_TIME return different results

SELECT CURTIME(), CURRENT_TIME(), CURRENT_TIME, SYS_TIME, SYSTIME;

   CURRENT_TIME    CURRENT_TIME    CURRENT_TIME    SYS_TIME     SYS_TIME
==========================================================================
  11:23:16 PM     11:23:16 PM     11:23:16 PM     04:23:16 PM  04:23:16 PM

Warning

As 10.0, CURTIME (), CURRENT_TIME () are different from SYS_TIME, SYSTIME. They are synonym for 9.x and lower.

CURRENT_TIMESTAMP, LOCALTIME, LOCALTIMESTAMP
CURRENT_TIMESTAMP
CURRENT_TIMESTAMP()
LOCALTIME
LOCALTIME()
LOCALTIMESTAMP
LOCALTIMESTAMP()

CURRENT_TIMESTAMP, CURRENT_TIMESTAMP (), LOCALTIME, LOCALTIME (), LOCALTIMESTAMP and LOCALTIMESTAMP () are used interchangeably and they return the current date and time of session as TIMESTAMP type. The unit is second. When the time zone of the current session is same as that of server, these functions are same as SYS_TIMESTAMP, SYSTIMESTAMP. Please also refer SYS_TIMESTAMP, SYSTIMESTAMP to find a difference and DBTIMEZONE(), SESSIONTIMEZONE() for details of the functions.

Return type:TIMESTAMP
SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'Asia/Seoul'

-- it returns the current date and time in TIMESTAMP type of session and server timezones.

SELECT LOCALTIME, SYS_TIMESTAMP;

   CURRENT_TIMESTAMP          SYS_TIMESTAMP
======================================================
  04:34:16 PM 02/05/2016     04:34:16 PM 02/05/2016
-- change session time from 'Asia/Seoul' to 'America/Los_Angeles'

SET TIME ZONE 'America/Los_Angeles';

SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'America/Los_Angeles'

-- Note that LOCALTIME() and SYS_TIMESTAMP return different results

SELECT LOCALTIME, SYS_TIMESTAMP;

   CURRENT_TIMESTAMP          SYS_TIMESTAMP
======================================================
  11:34:37 PM 02/04/2016     04:34:37 PM 02/05/2016

Warning

As 10.0, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP (), LOCALTIME, LOCALTIME (), LOCALTIMESTAMP and LOCALTIMESTAMP () are different from SYS_TIMESTAMP (), SYSTIMESTAMP. They are synonym for 9.x and lower.

DATE
DATE(date)

The DATE function extracts the date part from specified argument, and returns it as 'MM/DD/YYYY' format string. Arguments that can be specified are DATE, TIMESTAMP and DATETIME types. The return value is a VARCHAR type.

0 is not allowed in the argument value corresponding to year, month, and day; however, if 0 is inputted in every argument value corresponding to date and time, string where 0 is specified for year, month, and day is returned.

Parameters:date -- DATE, TIMESTAMP or DATETIME can be specified.
Return type:STRING
SELECT DATE('2010-02-27 15:10:23');
'02/27/2010'
SELECT DATE(NOW());
'04/01/2010'
SELECT DATE('0000-00-00 00:00:00');
'00/00/0000'
DATEDIFF
DATEDIFF(date1, date2)

The DATEDIFF function returns the difference between two arguments as an integer representing the number of days. Arguments that can be specified are DATE, TIMESTAMP and DATETIME types and its return value is only INTEGER type.

If every input argument value of date and time is 0, the return value is determined by the return_null_on_function_errors system parameter; if it is set to yes, then NULL is returned; if it is set to no, an error is returned. The default value is no.

Parameters:date1,date2 -- Specifies the types that include date (DATE, TIMESTAMP or DATETIME) type or string that represents the value of corresponding type. If invalid string is specified, an error is returned.
Return type:INT
SELECT DATEDIFF('2010-2-28 23:59:59','2010-03-02');
-2
SELECT DATEDIFF('0000-00-00 00:00:00', '2010-2-28 23:59:59');
ERROR: Conversion error in date format.

The following are examples of using timezone type values. For timezone related description, see Date/Time Types with Timezone.

SELECT IF(DATEDIFF('2002-03-03 12:00:00 AM','1990-01-01 11:59:59 PM') = DATEDIFF(timestampltz'2002-03-03 12:00:00 AM',timestampltz'1990-01-01 11:59:59 PM'),'ok','nok');
'ok'
DATE_SUB, SUBDATE
DATE_SUB(date, INTERVAL expr unit)
SUBDATE(date, INTERVAL expr unit)
SUBDATE(date, days)

The functions DATE_SUB and SUBDATE () are used interchangeably and they perform an addition or subtraction operation on a specific DATE value. The value is returned in DATE or DATETIME type. If the date resulting from the operation exceeds the last day of the month, the function returns a valid DATE value considering the last date of the month.

If every input argument value of date and time is 0, the return value is determined by the return_null_on_function_errors system parameter; if it is set to yes, then NULL is returned; if it is set to no, an error is returned. The default value is no.

If the calculated value is between '0000-00-00 00:00:00' and '0001-01-01 00:00:00', a value having 0 for all arguments is returned in DATE or DATETIME type. Note that operation in JDBC program is determined by the configuration of zeroDateTimeBehavior, connection URL property (see Configuration Connection for details).

Parameters:
  • date -- It is a DATE or TIMESTAMP expression that represents the start date. If an invalid DATE value such as '2006-07-00' is specified, NULL is returned.
  • expr -- It represents the interval value to be subtracted from the start date. If a negative number is specified next to the INTERVAL keyword, the interval value is added to the start date.
  • unit -- It represents the unit of the interval value specified in the exp expression. To check the expr argument for the unit value, see the table of ADDDATE().
Return type:

DATE or DATETIME

SELECT SYSDATE, SUBDATE(SYSDATE,INTERVAL 24 HOUR), SUBDATE(SYSDATE, 1);
03/30/2010  12:00:00.000 AM 03/29/2010               03/29/2010
--it adds days when argument < 0
SELECT SYSDATE, SUBDATE(SYSDATE,INTERVAL -24 HOUR), SUBDATE(SYSDATE, -1);
03/30/2010  12:00:00.000 AM 03/31/2010               03/31/2010
SELECT SUBDATE('0000-00-00 00:00:00', -50);
ERROR: Conversion error in date format.
SELECT SUBDATE('0001-01-01 00:00:00', 10);
'12:00:00.000 AM 00/00/0000'
DAY, DAYOFMONTH
DAY(date)
DAYOFMONTH(date)

The function DAY or DAYOFMONTH returns day in the range of 1 to 31 from the specified parameter. You can specify the DATE, TIMESTAMP or DATETIME type; the value is returned in INTEGER type.

0 is not allowed in the argument value corresponding to year, month, and day; however, if 0 is inputted in every argument value corresponding to year, month, and day, 0 is returned as an exception.

Parameters:date -- Date
Return type:INT
SELECT DAYOFMONTH('2010-09-09');
9
SELECT DAY('2010-09-09 19:49:29');
9
SELECT DAYOFMONTH('0000-00-00 00:00:00');
0
DAYOFWEEK
DAYOFWEEK(date)

The DAYOFWEEK function returns a day in the range of 1 to 7 (1: Sunday, 2: Monday, ..., 7: Saturday) from the specified parameters. The day index is same as the ODBC standards. You can specify the DATE, TIMESTAMP or DATETIME type; the value is returned in INTEGER type.

If every input argument value of year, month, and day is 0, the return value is determined by the return_null_on_function_errors system parameter; if it is set to yes, then NULL is returned; if it is set to no, an error is returned. The default value is no.

Parameters:date -- Date
Return type:INT
SELECT DAYOFWEEK('2010-09-09');
5
SELECT DAYOFWEEK('2010-09-09 19:49:29');
5
SELECT DAYOFWEEK('0000-00-00');
ERROR: Conversion error in date format.
DAYOFYEAR
DAYOFYEAR(date)

The DAYOFYEAR function returns the day of a year in the range of 1 to 366. You can specify the DATE, TIMESTAMP or DATETIME types; the value is returned in INTEGER type.

If every input argument value of year, month, and day is 0, the return value is determined by the return_null_on_function_errors system parameter; if it is set to yes, then NULL is returned; if it is set to no, an error is returned. The default value is no.

Parameters:date -- Date
Return type:INT
SELECT DAYOFYEAR('2010-09-09');
252
SELECT DAYOFYEAR('2010-09-09 19:49:29');
252
SELECT DAYOFYEAR('0000-00-00');
ERROR: Conversion error in date format.
EXTRACT
EXTRACT(field FROM date-time_argument)

The EXTRACT operator extracts the values from date-time_argument and then converts the value type into INTEGER.

0 is not allowed in the input argument value corresponding to year, month, and day; however, if 0 is inputted in every argument value corresponding to date and time, 0 is returned as an exception.

Parameters:
  • field -- Specifies a value to be extracted from date-time expression.
  • date-time_argument -- An expression that returns a value of date-time. This expression must be one of TIME, DATE, TIMESTAMP, or DATETIME types. If the value is NULL, NULL is returned.
Return type:

INT

SELECT EXTRACT(MONTH FROM DATETIME '2008-12-25 10:30:20.123' );
12
SELECT EXTRACT(HOUR FROM DATETIME '2008-12-25 10:30:20.123' );
10
SELECT EXTRACT(MILLISECOND FROM DATETIME '2008-12-25 10:30:20.123' );
123
SELECT EXTRACT(MONTH FROM '0000-00-00 00:00:00');
0

The following are examples of using timezone type values. For timezone related description, see Date/Time Types with Timezone.

SELECT EXTRACT (MONTH FROM datetimetz'10/15/1986 5:45:15.135 am Europe/Bucharest');
10
SELECT EXTRACT (MONTH FROM datetimeltz'10/15/1986 5:45:15.135 am Europe/Bucharest');
10
SELECT EXTRACT (MONTH FROM timestampltz'10/15/1986 5:45:15 am Europe/Bucharest');
10
SELECT EXTRACT (MONTH FROM timestamptz'10/15/1986 5:45:15 am Europe/Bucharest');
10
FROM_DAYS
FROM_DAYS(N)

The FROM_DAYS function returns a date value in DATE type if INTEGER type is inputted as an argument.

It is not recommended to use the FROM_DAYS function for dates prior to the year 1582 because the function does not take dates prior to the introduction of the Gregorian Calendar into account.

If a value in the range of 0 to 3,652,424 can be inputted as an argument. If a value in the range of 0 to 365 is inputted, 0 is returned. 3,652,424, which is the maximum value, means the last day of year 9999.

Parameters:N -- Integer in the range of 0 to 3,652,424
Return type:DATE
SELECT FROM_DAYS(719528);
01/01/1970
SELECT FROM_DAYS('366');
01/03/0001
SELECT FROM_DAYS(3652424);
12/31/9999
SELECT FROM_DAYS(0);
00/00/0000
FROM_TZ
FROM_TZ(datetime, timezone_string)

Converts date/time type without timezone as date/time type with timezone by adding timezone to DATETIME typed value. Input value's type is DATETIME, and the result value's type is DATETIMETZ.

Parameters:
  • datetime -- DATETIME
  • timezone_string -- String representing a timezone name or and offset '+05:00', 'Asia/Seoul'.
Return type:

DATETIMETZ

SELECT FROM_TZ(datetime '10/10/2014 00:00:00 AM', 'Europe/Vienna');
12:00:00.000 AM 10/10/2014 Europe/Vienna CEST
SELECT FROM_TZ(datetime '10/10/2014 23:59:59 PM', '+03:25:25');
11:59:59.000 PM 10/10/2014 +03:25:25

For timezone related description, see Date/Time Types with Timezone.

FROM_UNIXTIME
FROM_UNIXTIME(unix_timestamp[, format])

The FROM_UNIXTIME function returns the string of the specified format in VARCHAR type if the argument format is specified; if the argument format is omitted, it returns a value of TIMESTAMP type. Specify the arguement unix_timestamp as an INTEGER type that corresponds to the UNIX timestamp. The returned value is displayed in the current time zone.

It displays the result according to the format that you specified, and the date/time format, format follows the Date/Time Format 2 table of DATE_FORMAT().

The relation is not one of one-to-one correspondence between TIMESTAMP and UNIX timestamp so if you use UNIX_TIMESTAMP() or FROM_UNIXTIME function, partial value could be lost. For details, see UNIX_TIMESTAMP().

0 is not allowed in the argument value corresponding to year, month, and day; however, if 0 is inputted in every argument value corresponding to date and time, string where 0 is specified for every date and time value is returned. Note that operation in JDBC program is determined by the configuration of zeroDateTimeBehavior, connection URL property (see Configuration Connection for details).

Parameters:
  • unix_timestamp -- Positive integer
  • format -- Time format. Follows the date/time format of the DATE_FORMAT().
Return type:

STRING, INT

SELECT FROM_UNIXTIME(1234567890);
01:31:30 AM 02/14/2009
SELECT FROM_UNIXTIME('1000000000');
04:46:40 AM 09/09/2001
SELECT FROM_UNIXTIME(1234567890,'%M %Y %W');
'February 2009 Saturday'
SELECT FROM_UNIXTIME('1234567890','%M %Y %W');
'February 2009 Saturday'
SELECT FROM_UNIXTIME(0);
12:00:00 AM 00/00/0000
HOUR
HOUR(time)

The HOUR function extracts the hour from the specified parameter and then returns the value in integer. The type TIME, TIMESTAMP or DATETIME can be specified and a value is returned in the INTEGER type.

Parameters:time -- Time
Return type:INT
SELECT HOUR('12:34:56');
12
SELECT HOUR('2010-01-01 12:34:56');
12
SELECT HOUR(datetime'2010-01-01 12:34:56');
12
LAST_DAY
LAST_DAY(date_argument)

The LAST_DAY function returns the last day of the given month as DATE type.

If every input argument value of year, month, and day is 0, the return value is determined by the return_null_on_function_errors system parameter; if it is set to yes, then NULL is returned; if it is set to no, an error is returned. The default value is no.

Parameters:date_argument -- Specifies an expression of DATE type. To specify a TIMESTAMP or DATETIME value, explicit casting to DATE is required. If the value is NULL, NULL is returned.
Return type:DATE
--it returns last day of the month in DATE type
SELECT LAST_DAY(DATE '1980-02-01'), LAST_DAY(DATE '2010-02-01');
02/28/1980                    02/28/2010
--it returns last day of the month when explicitly casted to DATE type
SELECT LAST_DAY(CAST (SYS_TIMESTAMP AS DATE)), LAST_DAY(CAST (SYS_DATETIME AS DATE));
02/28/2010                                 02/28/2010
SELECT LAST_DAY('0000-00-00');
ERROR: Conversion error in date format.
MAKEDATE
MAKEDATE(year, dayofyear)

The MAKEDATE function returns a date from the specified parameter. You can specify an INTEGER type corresponding to the day of the year in the range of 1 to 9999 as an argument; the value in the range of 1/1/1 to 12/31/9999 is returned in DATE type. If the day of the year has passed the corresponding year, it will become the next year. For example, MAKEDATE(1999, 366) will return 2000-01-01. However, if you input a value in the range of 0 to 69 as the year, it will be processed as the year 2000-2069, if it is a value in the range of 70 to 99, it will be processed as the year 1970-1999.

If every value specified in year and dayofyear is 0, the return value is determined by the return_null_on_function_errors system parameter; if it is set to yes, then NULL is returned; if it is set to no, an error is returned. The default value is no.

Parameters:
  • year -- Year in the range of 1 to 9999
  • dayofyear -- If you input a value in the range of 0 to 99 in the argument, it is handled as an exception; dayofyear must be equal to or less than 3,615,902 and the return value of MAKEDATE(100, 3615902) is 9999/12/31.
Return type:

DATE

SELECT MAKEDATE(2010,277);
10/04/2010
SELECT MAKEDATE(10,277);
10/04/2010
SELECT MAKEDATE(70,277);
10/04/1970
SELECT MAKEDATE(100,3615902);
12/31/9999
SELECT MAKEDATE(9999,365);
12/31/9999
SELECT MAKEDATE(0,0);
ERROR: Conversion error in date format.
MAKETIME
MAKETIME(hour, min, sec)

The MAKETIME function returns the hour from specified argument in the AM/PM format. You can specify the INTEGER types corresponding hours, minutes and seconds as arguments; the value is returned in DATETIME.

Parameters:
  • hour -- An integer representing the hours in the range of 0 to 23
  • min -- An integer representing the minutes in the range of 0 to 59
  • sec -- An integer representing the minutes in the range of 0 to 59
Return type:

DATETIME

SELECT MAKETIME(13,34,4);
01:34:04 PM
SELECT MAKETIME('1','34','4');
01:34:04 AM
SELECT MAKETIME(24,0,0);
ERROR: Conversion error in time format.
MINUTE
MINUTE(time)

The MINUTE function returns the minutes in the range of 0 to 59 from specified argument. You can specify the TIME , TIMESTAMP or DATETIME type; the value is returned in INTEGER type.

Parameters:time -- Time
Return type:INT
SELECT MINUTE('12:34:56');
34
SELECT MINUTE('2010-01-01 12:34:56');
34
SELECT MINUTE('2010-01-01 12:34:56.7890');
34
MONTH
MONTH(date)

The MONTH function returns the month in the range of 1 to 12 from specified argument. You can specify the DATE, TIMESTAMP or DATETIME type; the value is returned in INTEGER type.

0 is not allowed in the argument value corresponding to year, month, and day; however, if 0 is inputted in every argument value corresponding to date, 0 is returned as an exception.

Parameters:date -- Date
Return type:INT
SELECT MONTH('2010-01-02');
1
SELECT MONTH('2010-01-02 12:34:56');
1
SELECT MONTH('2010-01-02 12:34:56.7890');
1
SELECT MONTH('0000-00-00');
0
MONTHS_BETWEEN
MONTHS_BETWEEN(date_argument, date_argument)

The MONTHS_BETWEEN function returns the difference between the given DATE value. The return value is DOUBLE type. An integer value is returned if the two dates specified as arguments are identical or are the last day of the given month; otherwise, a value obtained by dividing the day difference by 31 is returned.

Parameters:date_argument -- Specifies an expression of DATE type. TIMESTAMP or DATETIME value also can be used. If the value is NULL, NULL is returned.
Return type:DOUBLE
--it returns the negative months when the first argument is the previous date
SELECT MONTHS_BETWEEN(DATE '2008-12-31', DATE '2010-6-30');
-1.800000000000000e+001
--it returns integer values when each date is the last date of the month
SELECT MONTHS_BETWEEN(DATE '2010-6-30', DATE '2008-12-31');
1.800000000000000e+001
--it returns months between two arguments when explicitly casted to DATE type
SELECT MONTHS_BETWEEN(CAST (SYS_TIMESTAMP AS DATE), DATE '2008-12-25');
1.332258064516129e+001
--it returns months between two arguments when explicitly casted to DATE type
SELECT MONTHS_BETWEEN(CAST (SYS_DATETIME AS DATE), DATE '2008-12-25');
1.332258064516129e+001

The following are examples of using timezone type values. For timezone related description, see Date/Time Types with Timezone.

SELECT MONTHS_BETWEEN(datetimetz'2001-10-11 10:11:12 +02:00', datetimetz'2001-05-11 10:11:12 +03:00');
5.000000000000000e+00
NEW_TIME
NEW_TIME(src_datetime, src_timezone, dst_timezone)

Moves a date value from a timezone to the other timezone. The type of src_datetime is DATETIME or TIME, and the return value's type is the same with the src_datetime's value.

Parameters:
  • src_datetime -- input value of DATETIME or TIME
  • src_timezone -- a region name of a source timezone
  • dst_timezion -- a region name of a target timezone
Return type:

the same type with a src_datetimes type

SELECT NEW_TIME(datetime '10/10/2014 10:10:10 AM', 'Europe/Vienna', 'Europe/Bucharest');
11:10:10.000 AM 10/10/2014

TIME type only accept an offset timezone as an input argument; a region name is not allowed.

SELECT NEW_TIME(time '10:10:10 PM', '+03:00', '+10:00');
05:10:10 AM

To see the timezone related description, see Date/Time Types with Timezone.

QUARTER
QUARTER(date)

The QUARTER function returns the quarter in the range of 1 to 4 from specified argument. You can specify the DATE, TIMESTAMP or DATETIME type; the value is returned in INTEGER type.

Parameters:date -- Date
Return type:INT
SELECT QUARTER('2010-05-05');
2
SELECT QUARTER('2010-05-05 12:34:56');
2
SELECT QUARTER('2010-05-05 12:34:56.7890');
2

The following are examples of using timezone type values. For timezone related description, see Date/Time Types with Timezone.

SELECT QUARTER('2008-04-01 01:02:03 Asia/Seoul');
2
SELECT QUARTER(datetimetz'2003-12-31 01:02:03.1234 Europe/Paris');
4
ROUND
ROUND(date, fmt)

This function rounds date to the unit specified by the format string, fmt. It returns a value of DATE type.

Parameters:
  • date -- The value of DATE, TIMESTAMP or DATETIME
  • fmt -- Specifies the format for the truncating unit. If omitted, "dd" is default.
Return type:

DATE

The format and its unit and the return value are as follows:

Format Unit Return value
'yyyy' or 'yy' year a value rounded to year
'mm' or 'month' month a value rounded to month
'q' quarter a value rounded to quarter, one of 1/1, 4/1, 7/1, 10/1
'day' week a value rounded to week, this Sunday of date week or the next Sunday of date week
'dd' day a value rounded to day
'hh' hour a value rounded to hour
'mi' minute a value rounded to minute
'ss' second a value rounded to second
SELECT ROUND(date'2012-10-26', 'yyyy');
01/01/2013
SELECT ROUND(timestamp'2012-10-26 12:10:10', 'mm');
11/01/2012
SELECT ROUND(datetime'2012-12-26 12:10:10', 'dd');
12/27/2012
SELECT ROUND(datetime'2012-12-26 12:10:10', 'day');
12/30/2012
SELECT ROUND(datetime'2012-08-26 12:10:10', 'q');
10/01/2012
SELECT TRUNC(datetime'2012-08-26 12:10:10', 'q');
07/01/2012
SELECT ROUND(datetime'2012-02-28 23:10:00', 'hh');
02/28/2012
SELECT ROUND(datetime'2012-02-28 23:58:59', 'hh');
02/29/2012
SELECT ROUND(datetime'2012-02-28 23:59:59', 'mi');
02/29/2012
SELECT ROUND(datetime'2012-02-28 23:59:59.500', 'ss');
02/29/2012

In order to truncate date instead of rounding, please see TRUNC(date, fmt).

SEC_TO_TIME
SEC_TO_TIME(second)

The SEC_TO_TIME function returns the time including hours, minutes and seconds from specified argument. You can specify the INTEGER type in the range of 0 to 86,399; the value is returned in TIME type.

Parameters:second -- Seconds in the range of 0 to 86,399
Return type:TIME
SELECT SEC_TO_TIME(82800);
  sec_to_time(82800)
=====================
  11:00:00 PM
SELECT SEC_TO_TIME('82800.3');
  sec_to_time('82800.3')
=========================
  11:00:00 PM
SELECT SEC_TO_TIME(86399);
  sec_to_time(86399)
=====================
  11:59:59 PM
SECOND
SECOND(time)

The SECOND function returns the seconds in the range of 0 to 59 from specified argument. You can specify the TIME, TIMESTAMP or DATETIME; the value is returned in INTEGER type.

Parameters:time -- Time
Return type:INT
SELECT SECOND('12:34:56');
   second('12:34:56')
=====================
                   56
SELECT SECOND('2010-01-01 12:34:56');
   second('2010-01-01 12:34:56')
================================
                              56
SELECT SECOND('2010-01-01 12:34:56.7890');
   second('2010-01-01 12:34:56.7890')
=====================================
                                   56
SYS_DATE, SYSDATE
SYS_DATE
SYSDATE

SYS_DATE and SYSDATE are used interchangeably and they return the current date of server as the DATE type (MM/DD/YYYY or YYYY-MM-DD). The unit is day. When the time zone of the current session is same as that of server, these functions are same as CURDATE(), CURRENT_DATE() and CURRENT_DATE. Please also refer CURDATE(), CURRENT_DATE() to find a difference and DBTIMEZONE(), SESSIONTIMEZONE() for details of the functions.

If input every argument value of year, month, and day is 0, the return value is determined by the return_null_on_function_errors system parameter; if it is set to yes, then NULL is returned; if it is set to no, an error is returned. The default value is no.

Return type:DATE
SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'Asia/Seoul'

-- it returns the current date in DATE type

SELECT CURDATE(), CURRENT_DATE(), CURRENT_DATE, SYS_DATE, SYSDATE;

   CURRENT_DATE    CURRENT_DATE    CURRENT_DATE    SYS_DATE    SYS_DATE
========================================================================
  02/05/2016      02/05/2016      02/05/2016      02/05/2016  02/05/2016
-- it returns the date 60 days added to the current date

SELECT CURDATE()+60;

   CURRENT_DATE +60
===================
  04/05/2016
-- change session time from 'Asia/Seoul' to 'America/Los_Angeles'

SET TIME ZONE 'America/Los_Angeles';

SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'America/Los_Angeles'

-- Note that CURDATE() and SYS_DATE returns different results

SELECT CURDATE(), CURRENT_DATE(), CURRENT_DATE, SYS_DATE, SYSDATE;

   CURRENT_DATE    CURRENT_DATE    CURRENT_DATE    SYS_DATE    SYS_DATE
========================================================================
  02/04/2016      02/04/2016      02/04/2016      02/05/2016  02/05/2016

Warning

As 10.0, SYS_DATE and SYSDATE are different from CURDATE (), CURRENT_DATE, CURRENT_DATE (). They are synonym for 9.x and lower.

SYS_DATETIME, SYSDATETIME
SYS_DATETIME
SYSDATETIME

SYS_DATETIME and SYSDATETIME are used interchangeably, and they return the current date and time of server in DATETIME type. The unit is millisecond. When the time zone of the current session is same as that of server, these functions are same as CURRENT_DATETIME(), CURRENT_DATETIME, NOW(). Please also refer CURRENT_DATETIME(), NOW() to find a difference and DBTIMEZONE(), SESSIONTIMEZONE() for details of the functions.

Return type:DATETIME
SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'Asia/Seoul'

-- it returns the current date and time in DATETIME type

SELECT NOW(), SYS_DATETIME;

   CURRENT_DATETIME               SYS_DATETIME
==============================================================
  04:05:09.292 PM 02/05/2016     04:05:09.292 PM 02/05/2016
-- it returns the timestamp value 1 hour added to the current sys_datetime value

SELECT TO_CHAR(SYSDATETIME+3600*1000, 'YYYY-MM-DD HH24:MI');

   to_char( SYS_DATETIME +3600*1000, 'YYYY-MM-DD HH24:MI')
======================
  '2016-02-05 17:05'
-- change session time from 'Asia/Seoul' to 'America/Los_Angeles'

SET TIME ZONE 'America/Los_Angeles';

SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'America/Los_Angeles'

-- Note that NOW() and SYS_DATETIME return different results

SELECT NOW(), SYS_DATETIME;

   CURRENT_DATETIME               SYS_DATETIME
==============================================================
  11:08:57.041 PM 02/04/2016     04:08:57.041 PM 02/05/2016

Warning

As 10.0, SYS_DATEIME, SYSDATETIME are different from CURRENT_DATETIME (), NOW (). They are synonym for 9.x and lower.

SYS_TIME, SYSTIME
SYS_TIME
SYSTIME

SYS_TIME and SYSTIME are used interchangeably and they return the current time of server as TIME type (HH:MI:SS). The unit is second. When the time zone of the current session is same as that of server, these functions are same as CURTIME(), CURRENT_TIME, CURRENT_TIME(). Please also refer CURTIME(), CURRENT_TIME() to find a difference and DBTIMEZONE(), SESSIONTIMEZONE() for details of the functions.

Return type:TIME
select dbtimezone(), sessiontimezone();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'Asia/Seoul'

-- it returns the current time in TIME type

SELECT CURTIME(), CURRENT_TIME(), CURRENT_TIME, SYS_TIME, SYSTIME;

   CURRENT_TIME    CURRENT_TIME    CURRENT_TIME    SYS_TIME     SYS_TIME
==========================================================================
  04:22:54 PM     04:22:54 PM     04:22:54 PM     04:22:54 PM  04:22:54 PM
-- change session time from 'Asia/Seoul' to 'America/Los_Angeles'

SET TIME ZONE 'America/Los_Angeles';

select dbtimezone(), sessiontimezone();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'America/Los_Angeles'

-- Note that CURTIME() and SYS_TIME return different results

SELECT CURTIME(), CURRENT_TIME(), CURRENT_TIME, SYS_TIME, SYSTIME;

   CURRENT_TIME    CURRENT_TIME    CURRENT_TIME    SYS_TIME     SYS_TIME
==========================================================================
  11:23:16 PM     11:23:16 PM     11:23:16 PM     04:23:16 PM  04:23:16 PM

Warning

As 10.0, SYS_TIME, SYSTIME are different from CURTIME (), CURRENT_TIME (). They are synonym for 9.x and lower.

SYS_TIMESTAMP, SYSTIMESTAMP
SYS_TIMESTAMP
SYSTIMESTAMP

SYS_TIMESTAMP and SYSTIMESTAMP are used interchangeably and they return the current date and time of server as TIMESTAMP type. The unit is second. When the time zone of the current session is same as that of server, these functions are same as CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, LOCALTIMESTAMP(). Please also refer CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, LOCALTIMESTAMP() to find a difference and DBTIMEZONE(), SESSIONTIMEZONE() for details of the functions.

Return type:TIMESTAMP
SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'Asia/Seoul'

-- it returns the current date and time in TIMESTAMP type of session and server timezones.

SELECT LOCALTIME, SYS_TIMESTAMP;

   CURRENT_TIMESTAMP          SYS_TIMESTAMP
======================================================
  04:34:16 PM 02/05/2016     04:34:16 PM 02/05/2016
-- change session time from 'Asia/Seoul' to 'America/Los_Angeles'

SET TIME ZONE 'America/Los_Angeles';

SELECT DBTIMEZONE(), SESSIONTIMEZONE();

  dbtimezone            sessiontimezone
============================================
  'Asia/Seoul'          'America/Los_Angeles'

-- Note that LOCALTIME() and SYS_TIMESTAMP return different results

SELECT LOCALTIME, SYS_TIMESTAMP;

   CURRENT_TIMESTAMP          SYS_TIMESTAMP
======================================================
  11:34:37 PM 02/04/2016     04:34:37 PM 02/05/2016

Warning

As 10.0, SYS_TIMESTAMP (), SYSTIMESTAMP are different from CURRENT_TIMESTAMP, CURRENT_TIMESTAMP (), LOCALTIME, LOCALTIME (), LOCALTIMESTAMP and LOCALTIMESTAMP (). They are synonym for 9.x and lower.

TIME
TIME(time)

The TIME function extracts the time part from specified argument and returns the VARCHAR type string in the 'HH:MI:SS' format. You can specify the TIME, TIMESTAMP and DATETIME types.

Parameters:time -- Time
Return type:STRING
SELECT TIME('12:34:56');
   time('12:34:56')
======================
  '12:34:56'
SELECT TIME('2010-01-01 12:34:56');
   time('2010-01-01 12:34:56')
======================
  '12:34:56'
SELECT TIME(datetime'2010-01-01 12:34:56');
   time(datetime '2010-01-01 12:34:56')
======================
  '12:34:56'

The following are examples of using timezone type values. For timezone related description, see Date/Time Types with Timezone.

SELECT TIME(datetimetz'1996-02-03 02:03:04 AM America/Lima PET');
'02:03:04'
SELECT TIME(datetimeltz'1996-02-03 02:03:04 AM America/Lima PET');
'16:03:04'
SELECT TIME(datetimeltz'2000-12-31 17:34:23.1234 -05:00');
'07:34:23.123'
SELECT TIME(datetimetz'2000-12-31 17:34:23.1234 -05:00');
'17:34:23.123'
TIME_TO_SEC
TIME_TO_SEC(time)

The TIME_TO_SEC function returns the seconds in the range of 0 to 86,399 from specified argument. You can specify the TIME, TIMESTAMP or DATETIME type; the value is returned in INTEGER type.

Parameters:time -- Time
Return type:INT
SELECT TIME_TO_SEC('23:00:00');
82800
SELECT TIME_TO_SEC('2010-10-04 23:00:00');
82800
SELECT TIME_TO_SEC('2010-10-04 23:00:00.1234');
82800

The following are examples of using timezone type values. For timezone related description, see Date/Time Types with Timezone.

SELECT TIME_TO_SEC(datetimeltz'1996-02-03 02:03:04 AM America/Lima PET');

57784
SELECT TIME_TO_SEC(datetimetz'1996-02-03 02:03:04 AM America/Lima PET');

7384
TIMEDIFF
TIMEDIFF(expr1, expr2)

The TIMEDIFF function returns the time difference between the two specified time arguments. You can enter a date/time type, the TIME, DATE, TIMESTAMP or DATETIME type and the data types of the two arguments must be identical. The TIME will be returned and the time difference between the two arguments must be in the range of 00:00:00 -23:59:59. If it exceeds the range, an error will be returned.

Parameters:expr2 (expr1,) -- Time. The data types of the two arguments must be identical.
Return type:TIME
SELECT TIMEDIFF(time '17:18:19', time '12:05:52');
05:12:27 AM
SELECT TIMEDIFF('17:18:19','12:05:52');
05:12:27 AM
SELECT TIMEDIFF('2010-01-01 06:53:45', '2010-01-01 03:04:05');
03:49:40 AM

The following are examples of using timezone type values. For timezone related description, see Date/Time Types with Timezone.

SELECT TIMEDIFF (datetimeltz'2013-10-28 03:11:12 AM Asia/Seoul', datetimeltz'2013-10-27 04:11:12 AM Asia/Seoul');
11:00:00 PM
TIMESTAMP
TIMESTAMP(date[, time])

The TIMESTAMP function converts a DATE or TIMESTAMP type expression to DATETIME type.

If the DATE format string ('YYYY-MM-DD' or 'MM/DD/YYYY') or TIMESTAMP format string ('YYYY-MM-DD HH:MI:SS' or 'HH:MI:SS MM/DD/ YYYY') is specified as the first argument, the function returns it as DATETIME.

If the TIME format string ('HH:MI:SS.*FF*') is specified as the second, the function adds it to the first argument and returns the result as a DATETIME type. If the second argument is not specified, 12:00:00.000 AM is specified by default.

Parameters:
  • date -- The format strings can be specified as follows: 'YYYY-MM-DD', 'MM/DD/YYYY', 'YYYY-MM-DD HH:MI:SS.*FF*', 'HH:MI:SS.*FF* MM/DD/YYYY'.
  • time -- The format string can be specified as follows: 'HH:MI:SS*[.*FF]'.
Return type:

DATETIME

SELECT TIMESTAMP('2009-12-31'), TIMESTAMP('2009-12-31','12:00:00');
12:00:00.000 AM 12/31/2009     12:00:00.000 PM 12/31/2009
SELECT TIMESTAMP('2010-12-31 12:00:00','12:00:00');
12:00:00.000 AM 01/01/2011
SELECT TIMESTAMP('13:10:30 12/25/2008');
01:10:30.000 PM 12/25/2008

The following are examples of using timezone type values. For timezone related description, see Date/Time Types with Timezone.

SELECT TIMESTAMP(datetimetz'2010-12-31 12:00:00 America/New_York', '03:00');
03:00:00.000 PM 12/31/2010
SELECT TIMESTAMP(datetimeltz'2010-12-31 12:00:00 America/New_York', '03:00');
05:00:00.000 AM 01/01/2011
TO_DAYS
TO_DAYS(date)

The TO_DAYS function returns the number of days after year 0 in the rage of 366 to 3652424 from specified argument. You can specify DATE type; the value is returned in INTEGER type.

It is not recommended to use the TO_DAYS function for dates prior to the year 1582, as the function does not take dates prior to the introduction of the Gregorian Calendar into account.

Parameters:date -- Date
Return type:INT
SELECT TO_DAYS('2010-10-04');
   to_days('2010-10-04')
========================
                  734414
SELECT TO_DAYS('2010-10-04 12:34:56');
   to_days('2010-10-04 12:34:56')
================================
                          734414
SELECT TO_DAYS('2010-10-04 12:34:56.7890');
   to_days('2010-10-04 12:34:56.7890')
======================================
                                734414
SELECT TO_DAYS('1-1-1');
   to_days('1-1-1')
===================
                366
SELECT TO_DAYS('9999-12-31');
   to_days('9999-12-31')
========================
                 3652424
TRUNC
TRUNC(date[, fmt])

This function truncates date to the unit specified by the format string, fmt. It returns a value of DATE type.

Parameters:
  • date -- The value of DATE, TIMESTAMP or DATETIME
  • fmt -- Specifies the format for the truncating unit. If omitted, "dd" is default.
Return type:

DATE

The format and its unit and the return value are as follows:

Format Unit Return value
'yyyy' or 'yy' year the same year with Jan. 1st
'mm' or 'month' month the same month with 1st
'q' quarter the same quarter with one of Jan. 1st, Apr. 1st, Jul. 1st, Oct. 1st
'day' week Sunday of the same week(starting date of the week including date)
'dd' day the same date with date
SELECT TRUNC(date'2012-12-26', 'yyyy');
01/01/2012
SELECT TRUNC(timestamp'2012-12-26 12:10:10', 'mm');
12/01/2012
SELECT TRUNC(datetime'2012-12-26 12:10:10', 'q');
10/01/2012
SELECT TRUNC(datetime'2012-12-26 12:10:10', 'dd');
12/26/2012
// It returns the date of Sunday of the week which includes date'2012-12-26'
SELECT TRUNC(datetime'2012-12-26 12:10:10', 'day');
12/23/2012

In order to round date instead of truncation, please see ROUND(date, fmt).

TZ_OFFSET
TZ_OFFSET(timezone_string)

This returns a timezone offset from a timezone offset or timezone region name (e.g. '-05:00', or 'Europe/Vienna').

Parameters:timezone_string -- timezone offset of timezone region name.
Return type:STRING
SELECT TZ_OFFSET('+05:00');
'+05:00'
SELECT TZ_OFFSET('Asia/Seoul');
'+09:00'

For timezone related description, see Date/Time Types with Timezone.

UNIX_TIMESTAMP
UNIX_TIMESTAMP([date])

The argument of the UNIX_TIMESTAMP function can be omitted. If it is omitted, the function returns the interval between '1970-01-01 00:00:00' UTC and the current system date/time in seconds as INTEGER type. If the date argument is specified, the function returns the interval between '1970-01-01 00:00:00' UTC and the specified date/time in seconds.

0 is not allowed in the argument value corresponding to year, month, and day; however, if 0 is given in every argument value corresponding to date and time, 0 is returned as an exception.

Argument of DATETIME type is considered in session timezone.

Parameters:date -- DATE type, TIMESTAMP type, TIMESTAMPTZ type, TIMESTAMPLTZ type, DATETIME type, DATETIMETZ type, DATETIMELTZ type, DATE format string ('YYYY-MM-DD' or 'MM/DD/YYYY'), TIMESTAMP format string ('YYYY-MM-DD HH:MI:SS', 'HH:MI:SS MM/DD/YYYY') or 'YYYYMMDD' format string can be specified.
Return type:INT
SELECT UNIX_TIMESTAMP('1970-01-02'), UNIX_TIMESTAMP();
   unix_timestamp('1970-01-02')   unix_timestamp()
==================================================
                          54000         1270196737
SELECT UNIX_TIMESTAMP ('0000-00-00 00:00:00');
   unix_timestamp('0000-00-00 00:00:00')
========================================
                                       0
 -- when used without argument, it returns the exact value at the moment of execution of each occurence
 SELECT  UNIX_TIMESTAMP(), SLEEP(1), UNIX_TIMESTAMP();

   unix_timestamp()     sleep(1)   unix_timestamp()
===================================================
         1454661297            0         1454661298
UTC_DATE
UTC_DATE()

The UTC_DATE function returns the UTC date in 'YYYY-MM-DD' format.

Return type:STRING
SELECT UTC_DATE();
  utc_date()
==============
  01/12/2011
UTC_TIME
UTC_TIME()

The UTC_TIME function returns the UTC time in 'HH:MI:SS' format.

Return type:STRING
SELECT UTC_TIME();
  utc_time()
==============
  10:35:52 AM
WEEK
WEEK(date[, mode])

The WEEK function returns the week in the range of 0 to 53 from specified argument. You can specify the DATE, TIMESTAMP or DATETIME type; the value is returned in INTEGER type.

Parameters:
  • date -- Date
  • mode -- Value in the range of 0 to 7
Return type:

INT

You can omit the second argument, mode and must input a value in the range of 0 to 7. You can set that a week starts from Sunday or Monday and the range of the return value is from 0 to 53 or 1 to 53 with this value. If you omit the mode, the system parameter, default_week_format value(default: 0) will be used. The mode value means as follows:

mode Start Day of the Week Range The First Week of the Year
0 Sunday 0~53 The first week that Sunday is included in the year
1 Monday 0~53 The first week that more than three days are included in the year
2 Sunday 1~53 The first week in the year that includes a Sunday
3 Monday 1~53 The first week in the year that includes more than three days
4 Sunday 0~53 The first week in the year that includes more than three days
5 Monday 0~53 The first week in the year that includes Monday
6 Sunday 1~53 The first week in the year that includes more than three days
7 Monday 1~53 The first week in the year that includes Monday

If the mode value is one of 0, 1, 4 or 5, and the date corresponds to the last week of the previous year, the WEEK function will return 0. The purpose is to see what nth of the year the week is so it returns 0 for the 52th week of the year 1999.

SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);
   year('2000-01-01')   week('2000-01-01', 0)
=============================================
                2000                       0

To see what n-th the week is based on the year including the start day of the week, use 0, 2, 5 or 7 as the mode value.

SELECT WEEK('2000-01-01',2);
    week('2000-01-01', 2)
========================
                      52
SELECT WEEK('2010-04-05');
   week('2010-04-05', 0)
========================
                      14
SELECT WEEK('2010-04-05 12:34:56',2);
   week('2010-04-05 12:34:56',2)
===============================
                              14
SELECT WEEK('2010-04-05 12:34:56.7890',4);
   week('2010-04-05 12:34:56.7890',4)
====================================
                                  14
WEEKDAY
WEEKDAY(date)

The WEEKDAY function returns the day of week in the range of 0 to 6 (0: Monday, 1: Tuesday, ..., 6: Sunday) from the specified parameter. You can specify DATE, TIMESTAMP, DATETIME types as parameters and an INTEGER type will be returned.

Parameters:date -- Date
Return type:INT
SELECT WEEKDAY('2010-09-09');
   weekday('2010-09-09')
========================
                       3
SELECT WEEKDAY('2010-09-09 13:16:00');
   weekday('2010-09-09 13:16:00')
=================================
                                3
YEAR
YEAR(date)

The YEAR function returns the year in the range of 1 to 9,999 from the specified parameter. You can specify DATE, TIMESTAMP or DATETIME type; the value is returned in INTEGER type.

Parameters:date -- Date
Return type:INT
SELECT YEAR('2010-10-04');
   year('2010-10-04')
=====================
                 2010
SELECT YEAR('2010-10-04 12:34:56');
   year('2010-10-04 12:34:56')
==============================
                          2010
SELECT YEAR('2010-10-04 12:34:56.7890');
   year('2010-10-04 12:34:56.7890')
===================================
                               2010
LOB Functions
BIT_TO_BLOB
BIT_TO_BLOB(blob_type_column_or_value)

This function converts BIT or VARYING BIT type into BLOB type.

Parameters:blob_type_column_or_value -- Target column or value to convert
Return type:BLOB
BLOB_FROM_FILE
BLOB_FROM_FILE(file_pathname)

This function read the contents from the file with VARCHAR type data and returns BLOB type data.

Parameters:file_pathname -- the path on the server which DB clients like CAS or CSQL are started
Return type:BLOB
SELECT CAST(BLOB_FROM_FILE('local:/home/cubrid/demo/lob/ces_622/image_t.00001352246696287352_4131')
   AS BIT VARYING) result;

SELECT CAST(BLOB_FROM_FILE('file:/home/cubrid/demo/lob/ces_622/image_t.00001352246696287352_4131')
   AS BIT VARYING) result;
BLOB_LENGTH
BLOB_LENGTH(blob_column)

The length of LOB data stored in BLOB file is returned.

Parameters:clob_column -- The column to get the length of BLOB
Return type:INT
BLOB_TO_BIT
BLOB_TO_BIT(blob_type_column)

This function converts BLOB type to VARYING BIT type.

Parameters:blob_type_column -- Target column to convert
Return type:VARYING BIT
CHAR_TO_BLOB
CHAR_TO_BLOB(char_type_column_or_value)

This function converts CHAR or VARCHAR type into BLOB type.

Parameters:char_type_column_or_value -- Target column or value to convert
Return type:BLOB
CHAR_TO_CLOB
CHAR_TO_CLOB(char_type_column_or_value)

This function converts CHAR or VARCHAR type into CLOB type.

Parameters:char_type_column_or_value -- Target column or value to convert
Return type:CLOB
CLOB_FROM_FILE
CLOB_FROM_FILE(file_pathname)

This function read the contents from the file with VARCHAR type data and returns CLOB type data.

Parameters:file_pathname -- the path on the server which DB clients like CAS or CSQL are started
Return type:CLOB

If you specify the file_pathname as the relative path, the parent path will be the current working directory.

For the statement including this function, the query plan is not cached.

SELECT CAST(CLOB_FROM_FILE('local:/home/cubrid/demo/lob/ces_622/image_t.00001352246696287352_4131')
   AS VARCHAR) result;

SELECT CAST(CLOB_FROM_FILE('file:/home/cubrid/demo/lob/ces_622/image_t.00001352246696287352_4131')
   AS VARCHAR) result;
CLOB_LENGTH
CLOB_LENGTH(clob_column)

The length of LOB data stored in CLOB file is returned.

Parameters:clob_column -- The column to get the length of CLOB
Return type:INT
CLOB_TO_CHAR
CLOB_TO_CHAR( clob_type_column [USING charset] )

This function converts CLOB type into VARCHAR type.

Parameters:
  • clob_type_column -- Target column to convert
  • charset -- The character set of string to convert. It can be utf8, euckr or iso88591.
Return type:

STRING

Data Type Casting Functions and Operators
CAST
CAST(cast_operand AS cast_target)

The CAST operator can be used to explicitly cast one data type to another in the SELECT statement. A query list or a value expression in the WHERE clause can be cast to another data type.

Parameters:
  • cast_operand -- Declares the value to cast to a different data type.
  • cast_target -- Specifies the type to cast to.
Return type:

cast_target

Depending on the situation, data type can be automatically converted without using the CAST operator. For details, see Implicit Type Conversion.

See CASTing a String to Date/Time Type regarding to convert the string of date/time type into date/time type.

The following table shows a summary of explicit type conversions (casts) using the CAST operator in CUBRID.

From \ To EN AN VC FC VB FB ENUM BLOB CLOB D T UT UTZ DT DTZ S MS SQ
EN Yes Yes Yes Yes No No No No No No No Yes Yes No No No No No
AN Yes Yes Yes Yes No No No No No No No Yes Yes No No No No No
VC Yes Yes Yes(*) Yes(*) Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes No No No
FC Yes Yes Yes(*) Yes(*) Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes No No No
VB No No Yes Yes Yes Yes No Yes Yes No No No No No No No No No
FB No No Yes Yes Yes Yes No Yes Yes No No No No No No No No No
ENUM No No Yes Yes No No Yes No No No No No No No No No No No
BLOB No No No No Yes Yes Yes Yes No No No No No No No No No No
CLOB No No Yes Yes No No Yes No Yes No No No No No No No No No
D No No Yes Yes No No No No No Yes No Yes Yes Yes Yes No No No
T No No Yes Yes No No No No No No Yes No No No No No No No
UT No No Yes Yes No No No No No Yes Yes Yes Yes Yes Yes No No No
UTZ No No Yes Yes No No No No No Yes Yes Yes Yes Yes Yes No No No
DT No No Yes Yes No No No No No Yes Yes Yes Yes Yes Yes No No No
DTZ No No Yes Yes No No No No No Yes Yes Yes Yes Yes Yes No No No
S No No No No No No No No No No No No No No No Yes Yes Yes
MS No No No No No No No No No No No No No No No Yes Yes Yes
SQ No No No No No No No No No No No No No No No Yes Yes Yes

(*): The CAST operation is allowed only when the value expression and the data type to be cast have the same character set.

  • Data Type Key
    • EN: Exact numeric data type (INTEGER, SMALLINT, BIGINT, NUMERIC, DECIMAL)
    • AN: Approximate numeric data type (FLOAT/REAL, DOUBLE)
    • VC: Variable-length character string (VARCHAR (n))
    • FC: Fixed-length character string (CHAR (n))
    • VB: Variable-length bit string (BIT VARYING (n))
    • FB: Fixed-length bit string (BIT (n))
    • ENUM: ENUM type
    • BLOB: Binary data that is stored outside DB
    • CLOB: String data that is stored inside DB
    • D: DATE
    • T: TIME
    • DT: DATETIME
    • DTZ: DATETIME WITH TIME ZONE and DATETIME WITH LOCAL TIME ZONE data types
    • UT: TIMESTAMP
    • UTZ: TIMESTAMP WITH TIME ZONE and TIMESTAMP WITH LOCAL TIME ZONE data types
    • S: SET
    • MS: MULTISET
    • SQ: LIST (= SEQUENCE)
--operation after casting character as INT type returns 2
SELECT (1+CAST ('1' AS INT));
2
--cannot cast the string which is out of range as SMALLINT
SELECT (1+CAST('1234567890' AS SMALLINT));
ERROR: Cannot coerce value of domain "character" to domain "smallint".
--operation after casting returns 1+1234567890
SELECT (1+CAST('1234567890' AS INT));
1234567891
--'1234.567890' is casted to 1235 after rounding up
SELECT (1+CAST('1234.567890' AS INT));
1236
--'1234.567890' is casted to string containing only first 5 letters.
SELECT (CAST('1234.567890' AS CHAR(5)));
'1234.'
--numeric type can be casted to CHAR type only when enough length is specified
SELECT (CAST(1234.567890 AS CHAR(5)));
ERROR: Cannot coerce value of domain "numeric" to domain "character".
--numeric type can be casted to CHAR type only when enough length is specified
SELECT (CAST(1234.567890 AS CHAR(11)));
'1234.567890'
--numeric type can be casted to CHAR type only when enough length is specified
SELECT (CAST(1234.567890 AS VARCHAR));
'1234.567890'
--string can be casted to time/date types only when its literal is correctly specified
SELECT (CAST('2008-12-25 10:30:20' AS TIMESTAMP));
10:30:20 AM 12/25/2008
SELECT (CAST('10:30:20' AS TIME));
10:30:20 AM
--string can be casted to TIME type when its literal is same as TIME's.
SELECT (CAST('2008-12-25 10:30:20' AS TIME));
10:30:20 AM
--string can be casted to TIME type after specifying its type of the string
SELECT (CAST(TIMESTAMP'2008-12-25 10:30:20' AS TIME));
10:30:20 AM
SELECT CAST('abcde' AS BLOB);
file:/home1/user1/db/tdb/lob/ces_743/ces_temp.00001283232024309172_1342
SELECT CAST(B'11010000' as varchar(10));
'd0'
SELECT CAST('1A' AS BLOB);
X'1a00'
--numbers can be casted to TIMESTAMP type
SELECT CAST (1 AS TIMESTAMP), CAST (1.2F AS TIMESTAMP);
09:00:01 AM 01/01/1970     09:00:01 AM 01/01/1970
--numbers cannot be casted to DATETIME type
SELECT CAST (1 AS DATETIME);
Cannot coerce 1 to type datetime
--TIMESTAMP cannot be casted to numbers
SELECT CAST (TIMESTAMP'09:00:01 AM 01/01/1970' AS INT)
Cannot coerce timestamp '09:00:01 AM 01/01/1970' to type integer.

Note

  • CAST is allowed only between data types having the same character set.
  • If you cast an approximate data type(FLOAT, DOUBLE) to integer type, the number is rounded to zero decimal places.
  • If you cast an exact numeric data type(NUMERIC) to integer type, the number is rounded to zero decimal places.
  • If you cast a numeric data type to string character type, it should be longer than the length of significant figures + decimal point. An error occurs otherwise.
  • If you cast a character string type A to a character string type B, B should be longer than the A. The end of character string is truncated otherwise.
  • If you cast a character string type A to a date-time date type B, it is converted only when literal of A and B type match one another. An error occurs otherwise.
  • You must explicitly do type casting for numeric data stored in a character string so that an arithmetic operation can be performed.
DATE_FORMAT
DATE_FORMAT(date, format)

The DATE_FORMAT function converts the value of date/time data type which include a date to specified date/time format and then return the value with the VARCHAR data type. For the format parameter to assign, refer to Date/Time Format 2 table of the DATE_FORMAT(). The Date/Time Format 2 table is used in DATE_FORMAT(), TIME_FORMAT(), and STR_TO_DATE() functions.

Parameters:
  • date -- A value of DATE, TIMESTAMP, DATETIME, DATETIMETZ, DATETIMELTZ, TIMESTAMPTZ, or TIMESTAMP.
  • format -- Specifies the output format. The format specifier starting with '%' is used.
Return type:

STRING

When the format argument is assigned, the string is interpreted according to the specified language. At that time, the language specified as the intl_date_lang system parameter is applied. If the intl_date_lang value is not set, the language specified when creating DB is applied.

For example, when the language is "de_DE" and the format is "%d %M %Y", the string "3 Oktober 2009" is interpreted as the DATE type of "2009-10-03". When the specified format argument does not correspond to the given string, an error is returned.

In the following Date/Time Format 2 table, the month/day, date, and AM/PM in characters are different by language.

Date/Time Format 2

format Value Meaning
%a Weekday, English abbreviation (Sun, ... , Sat)
%b Month, English abbreviation (Jan, ... , Dec)
%c Month (1, ... , 12)
%D Day of the month, English ordinal number (1st, 2nd, 3rd, ...)
%d Day of the month, two-digit number (01, ... , 31)
%e Day of the month (1, ... , 31)
%f Microseconds, three-digit number (000, ... , 999)
%H Hour, 24-hour based, number with at least two--digit (00, ... , 23, ... , 100, ... )
%h Hour, 12-hour based two-digit number (01, ... , 12)
%I Hour, 12-hour based two-digit number (01, ... , 12)
%i Minutes, two-digit number (00, ... , 59)
%j Day of year, three-digit number (001, ... , 366)
%k Hour, 24-hour based, number with at least one-digit (0, ... , 23, ... , 100, ... )
%l Hour, 12-hour based (1, ... , 12)
%M Month, English string (January, ... , December)
%m Month, two-digit number (01, ... , 12)
%p AM or PM
%r Time, 12-hour based, hour:minute:second (hh:mi:ss AM or hh:mi:ss PM)
%S Seconds, two-digit number (00, ... , 59)
%s Seconds, two-digit number (00, ... , 59)
%T Time, 24-hour based, hour:minute:second (hh:mi:ss)
%U Week, two-digit number, week number of the year with Sunday being the first day Week (00, ... , 53)
%u Week, two-digit number, week number of the year with Monday being the first day (00, ... , 53)
%V Week, two-digit number, week number of the year with Sunday being the first day Week (00, ... , 53) (Available to use in combination with %X)
%v Week, two-digit number, week number of the year with Monday being the first day (00, ... , 53) (Available to use in combination with %x)
%W Weekday, English string (Sunday, ... , Saturday)
%w Day of the week, number index (0=Sunday, ... , 6=Saturday)
%X Year, four-digit number calculated as the week number with Sunday being the first day of the week (0000, ... , 9999) (Available to use in combination with %V)
%x Year, four-digit number calculated as the week number with Monday being the first day of the week (0000, ... , 9999) (Available to use in combination with %v)
%Y Year, four-digit number (0001, ... , 9999)
%y Year, two-digit number (00, 01, ... , 99)
%% Output the special character "%" as a string
%x Output an arbitrary character x as a string out of English letters that are not used as format specifiers.
%TZR Time zone region information. e.g. US/Pacific.
%TZD Daylight saving information. e.g. KST, KT, EET
%TZH Timezone hour offset. e.g. +09, -09
%TZM Timezone minute offset. e.g. +00, +30

Note

%TZR, %TZD, %TZH, %TZM can be used only in timezone types.

Note

A format specifying a number after TZD

See A format specifying a number after TZD.

The following example shows the case when the system parameter intl_date_lang is "en_US".

SELECT DATE_FORMAT(datetime'2009-10-04 22:23:00', '%W %M %Y');
'Sunday October 2009'
SELECT DATE_FORMAT(datetime'2007-10-04 22:23:00', '%H:%i:%s');
'22:23:00'
SELECT DATE_FORMAT(datetime'1900-10-04 22:23:00', '%D %y %a %d %m %b %j');
'4th 00 Thu 04 10 Oct 277'
SELECT DATE_FORMAT(date'1999-01-01', '%X %V');
'1998 52'

The following example shows the case when the system parameter intl_date_lang is "de_DE".

SET SYSTEM PARAMETERS 'intl_date_lang="de_DE"';
SELECT DATE_FORMAT(datetime'2009-10-04 22:23:00', '%W %M %Y');
'Sonntag Oktober 2009'
SELECT DATE_FORMAT(datetime'2007-10-04 22:23:00', '%H:%i:%s %p');
'22:23:00 Nachm.'
SELECT DATE_FORMAT(datetime'1900-10-04 22:23:00', '%D %y %a %d %m %b %j');
'4 00 Do. 04 10 Okt 277'

Note

When the charset is ISO-8859-1, the language that can be changed by the system parameter intl_date_lang is "ko_KR" and "tr_TR" except "en_US". If the charset is UTF-8, it can be changed to any language supported by CUBRID. For details, see Note in the TO_CHAR()).

The following example outputs the value of DATETIMETZ type which includes timezone information as the desired format.

SELECT DATE_FORMAT(datetimetz'2012-02-02 10:10:10 Europe/Zurich CET', '%TZR %TZD %TZH %TZM');
::
'Europe/Zurich CET 01 00'
FORMAT
FORMAT(x, dec)

The FORMAT function displays the number x by using digit grouping symbol as a thousands separator, so that its format becomes '#,###,###.#####' and performs rounding after the decimal point symbol to express as many as dec digits after it. The return value is a VARCHAR type.

Parameters:
  • x -- An expression that returns a numeric value
  • dec -- the number of digits of fractional parts
Return type:

STRING

Thousands separator symbol and decimal point symbol is output in the format according to the specified language. The language is specified by the intl_number_lang system parameter. If the value of intl_number_lang is not set, the language specified when creating DB is applied.

For example, when the language is one of the European languages, such as "de_DE" or "fr_FR", "." is interpreted as the thousands separator and "," as the decimal point symbol (see Default output of number by language of the TO_CHAR()).

The following example shows command execution by setting the value of the intl_number_lang system parameter to "en_US".

SET SYSTEM PARAMETERS 'intl_number_lang="en_US"';
SELECT FORMAT(12000.123456,3), FORMAT(12000.123456,0);
'12,000.123'          '12,000'

The following example shows command execution on the database by setting the value of the intl_number_lang system parameter to "de_DE". In the number output format of most European countries, such as Germany and France, "." is the cipher identifier and "," is the decimal point symbol.

SET SYSTEM PARAMETERS 'intl_number_lang="de_DE"';
SELECT FORMAT(12000.123456,3), FORMAT(12000.123456,0);
'12.000,123'          '12.000'
STR_TO_DATE
STR_TO_DATE(string, format)

The STR_TO_DATE function converts the given character string to a date/time value by interpreting it according to the specified format and operates in the opposite way to the DATE_FORMAT() function. The return value is determined by the date/time part included in the character string.

Parameters:
  • string -- String.
  • format -- Specifies the format to interpret the character string. You should use character strings including % for the format specifiers. See Date/Time Format 2 table of DATE_FORMAT() function.
Return type:

DATETIME, DATE, TIME, DATETIMETZ

For the format argument to assign, see Date/Time Format 2 table of the DATE_FORMAT().

If string is invalid date/time value or format is invalid, it returns an error.

When the format argument is assigned, the string is interpreted according to the specified language. At that time, the language specified as the intl_date_lang system parameter is applied. If the intl_date_lang value is not set, the language specified when creating DB is applied.

For example, when the language is "de_DE" and the format is "%d %M %Y", the string "3 Oktober 2009" is interpreted as the DATE type of "2009-10-03". If the format argument does not correspond to the given string, an error is returned.

0 is not allowed in the argument value corresponding to year, month, and day; however, if 0 is inputted in every argument value corresponding to date and time, the value of DATE or DATETIME type that has 0 for every date and time value is returned as an exception. Note that operation in JDBC program is determined by the configuration of zeroDateTimeBehavior, connection URL property. For more information about zeroDateTimeBehavior, please see Configuration Connection.

The following example shows the case when the system parameter intl_date_lang is "en_US".

SET SYSTEM PARAMETERS 'intl_date_lang="en_US"';
SELECT STR_TO_DATE('01,5,2013','%d,%m,%Y');
05/01/2013
SELECT STR_TO_DATE('May 1, 2013','%M %d,%Y');
05/01/2013
SELECT STR_TO_DATE('13:30:17','%H:%i');
01:30:00 PM
SELECT STR_TO_DATE('09:30:17 PM','%r');
09:30:17 PM
SELECT STR_TO_DATE('0,0,0000','%d,%m,%Y');
00/00/0000

The following example shows the case when the system parameter intl_date_lang is "de_DE". The German Oktober is interpreted to 10.

SET SYSTEM PARAMETERS 'intl_date_lang="de_DE"';
SELECT STR_TO_DATE('3 Oktober 2009', '%d %M %Y');
10/03/2009

Note

When the charset is ISO-8859-1, the language that can be changed by the system parameter intl_date_lang is "ko_KR" and "tr_TR" except "en_US". If the charset is UTF-8, it can be changed to any language supported by CUBRID. For details, see Note in the TO_CHAR()).

The following example shows which converts a date/time string with timezone information into DATETIMETZ type value.

SELECT STR_TO_DATE('2001-10-11 02:03:04 AM Europe/Bucharest EEST', '%Y-%m-%d %h:%i:%s %p %TZR %TZD');
02:03:04.000 AM 10/11/2001 Europe/Bucharest EEST
TIME_FORMAT
TIME_FORMAT(time, format)

The TIME_FORMAT function converts the date/time data type value including time value into a string of specified date/time format, and returns the value with the VARCHAR data type.

Parameters:
  • time -- A value of a type with time. (TIME, TIMESTAMP, DATETIME, TIMESTAMPTZ or DATETIMETZ)
  • format -- Specifies the output format. Use a string that contains '%' as a specifier. See the table Date/Time Format 2 of DATE_FORMAT() function.
Return type:

STRING

When the format argument is assigned, the time is output according to the specified language. At this time, the language specified as the intl_date_lang system parameter is applied. If intl_date_lang system parameter is not set, the language specified when creating DB is applied.

For example, when the language is set to "de_DE" and the format is "%h:%i:%s %p", "08:46:53 PM" is output as "08:46:53 Nachm.". When the format argument specified does not correspond to the given string, an error is returned.

The following example shows the case when the system parameter intl_date_lang is "en_US".

SET SYSTEM PARAMETERS 'intl_date_lang="en_US"';
SELECT TIME_FORMAT(time'22:23:00', '%H %i %s');
'22 23 00'
SELECT TIME_FORMAT(time'23:59:00', '%H %h %i %s %f');
'23 11 59 00 000'
SELECT SYSTIME, TIME_FORMAT(SYSTIME, '%p');
08:46:53 PM  'PM'

The following example shows the case when the system parameter intl_date_lang is "de_DE".

SET SYSTEM PARAMETERS 'intl_date_lang="de_DE"';
SELECT SYSTIME, TIME_FORMAT(SYSTIME, '%p');
08:46:53 PM  'Nachm.'

Note

When the charset is ISO-8859-1, the language that can be changed by the system parameter intl_date_lang is "ko_KR" and "tr_TR" except "en_US". If the charset is UTF-8, it can be changed to any language supported by CUBRID. For details, see Note in the TO_CHAR()).

The following outputs the value with a timezone information into a specified format string.

SELECT TIME_FORMAT(datetimetz'2001-10-11 02:03:04 AM Europe/Bucharest EEST', '%h:%i:%s %p %TZR %TZD');
'02:03:04 AM Europe/Bucharest EEST'
TO_CHAR(date_time)
TO_CHAR(date_time[, format[, date_lang_string_literal]])

The TO_CHAR (date_time) function converts the value of date/time types (TIME, DATE, TIMESTAMP, DATETIME) to a string depending on the table Date/Time Format 1 and then returns the value. The type of the return value is VARCHAR.

Parameters:
  • date_time -- A value of date/time type. (TIME, DATE, TIMESTAMP, DATETIME, DATETIMETZ, DATETIMELTZ, TIMESTAMPTZ, TIMESTAMPLTZ)
  • format -- A format of return value.
  • date_lang_string_literal -- Specifies a language applied to a return value.
Return type:

STRING

When the format argument is specified, the date_time is output according to the specified language (see the Date/Time Format 1 table). A language is defined by the date_lang_string_literal. If date_lang_string_literal is omitted, the language specified by the intl_date_lang parameter is applied; if the value of intl_date_lang is not specified, the language specified when creating DB is applied.

For example, when the language is set to "de_DE" and the format is "HH:MI:SS:AM", "08:46:53 PM" is output as "08:46:53 Nachm.". When the format argument specified does not correspond to the given string, an error is returned.

When the format argument is omitted, the date_time is output as a string according to the default output format of the "en_US"(see the following table Default Date/Time Output Format for Each Language).

Note

The CUBRID_DATE_LANG environment used in earlier version of CUBRID 9.0 is no longer supported.

Default Date/Time Output Format for Each Language

LANG DATE TIME TIMESTAMP DATETIME TIMESTAMP WITH TIME ZONE DATETIME WITH TIME ZONE
en_US 'MM/DD/YYYY' 'HH:MI:SS AM' 'HH:MI:SS AM MM/DD/YYYY' 'HH:MI:SS.FF AM MM/DD/YYYY' 'HH:MI:SS AM MM/DD/YYYY TZR' 'HH:MI:SS.FF AM MM/DD/YYYY TZR'
de_DE 'DD.MM.YYYY' 'HH24:MI:SS' 'HH24:MI:SS DD.MM.YYYY' 'HH24:MI:SS.FF DD.MM.YYYY' 'HH24:MI:SS DD.MM.YYYY TZR' 'HH24:MI:SS.FF DD.MM.YYYY TZR'
es_ES 'DD.MM.YYYY' 'HH24:MI:SS' 'HH24:MI:SS DD.MM.YYYY' 'HH24:MI:SS.FF DD.MM.YYYY' 'HH24:MI:SS DD/MM/YYYY TZR' 'HH24:MI:SS.FF DD/MM/YYYY TZR'
fr_FR 'DD.MM.YYYY' 'HH24:MI:SS' 'HH24:MI:SS DD.MM.YYYY' 'HH24:MI:SS.FF DD.MM.YYYY' 'HH24:MI:SS DD/MM/YYYY TZR' 'HH24:MI:SS.FF DD/MM/YYYY TZR'
it_IT 'DD.MM.YYYY' 'HH24:MI:SS' 'HH24:MI:SS DD.MM.YYYY' 'HH24:MI:SS.FF DD.MM.YYYY' 'HH24:MI:SS DD/MM/YYYY TZR' 'HH24:MI:SS.FF DD/MM/YYYY TZR'
ja_JP 'YYYY/MM/DD' 'HH24:MI:SS' 'HH24:MI:SS YYYY/MM/DD' 'HH24:MI:SS.FF YYYY/MM/DD' 'HH24:MI:SS YYYY/MM/DD TZR' 'HH24:MI:SS.FF YYYY/MM/DD TZR'
km_KH 'DD/MM/YYYY' 'HH24:MI:SS' 'HH24:MI:SS DD/MM/YYYY' 'HH24:MI:SS.FF DD/MM/YYYY' 'HH24:MI:SS DD/MM/YYYY TZR' 'HH24:MI:SS.FF DD/MM/YYYY TZR'
ko_KR 'YYYY.MM.DD' 'HH24:MI:SS' 'HH24:MI:SS YYYY.MM.DD' 'HH24:MI:SS.FF YYYY.MM.DD' 'HH24:MI:SS YYYY.MM.DD TZR' 'HH24:MI:SS.FF YYYY.MM.DD TZR'
tr_TR 'DD.MM.YYYY' 'HH24:MI:SS' 'HH24:MI:SS DD.MM.YYYY' 'HH24:MI:SS.FF DD.MM.YYYY' 'HH24:MI:SS DD.MM.YYYY TZR' 'HH24:MI:SS.FF DD.MM.YYYY TZR'
vi_VN 'DD/MM/YYYY' 'HH24:MI:SS' 'HH24:MI:SS DD/MM/YYYY' 'HH24:MI:SS.FF DD/MM/YYYY' 'HH24:MI:SS DD/MM/YYYY TZR' 'HH24:MI:SS.FF DD/MM/YYYY TZR'
zh_CN 'YYYY-MM-DD' 'HH24:MI:SS' 'HH24:MI:SS YYYY-MM-DD' 'HH24:MI:SS.FF YYYY-MM-DD' 'HH24:MI:SS YYYY-MM-DD TZR' 'HH24:MI:SS.FF YYYY-MM-DD TZR'
ro_RO 'DD.MM.YYYY' 'HH24:MI:SS' 'HH24:MI:SS DD.MM.YYYY' 'HH24:MI:SS.FF DD.MM.YYYY' 'HH24:MI:SS DD.MM.YYYY TZR' 'HH24:MI:SS.FF DD.MM.YYYY TZR'

Date/Time Format 1

Format Element Description
CC Century
YYYY , YY Year with 4 numbers, Year with 2 numbers
Q Quarter (1, 2, 3, 4; January - March = 1)
MM Month (01-12; January = 01) Note: MI represents the minute of hour.
MONTH Month in characters
MON Abbreviated month name
DD Day (1 - 31)
DAY Day of the week in characters
DY Abbreviated day of the week
D or d Day of the week in numbers (1 - 7)
AM or PM AM/PM
A.M. or P.M. AM/PM with periods
HH or HH12 Hour (1 -12)
HH24 Hour (0 - 23)
MI Minute (0 - 59)
SS Second (0 - 59)
FF Millisecond (0-999)
- / , . ; : "text" Punctuation and quotation marks are represented as they are in the result
TZD Daylight saving information. e.g. KST, KT, EET
TZH Timezone hour offset. e.g. +09, -09
TZM Timezone minute offset. e.g. +00, +30

Note

TZR, TZD, TZH, TZM can be used only in timezone types.

Note

A format to specify a number after "TZD"

A number can be added after "TZD". This format is from TZD2 to TZD11; When you use a general character as a separator of a string, this format can be used.

SELECT STR_TO_DATE('09:30:17 20140307XEESTXEurope/Bucharest','%h:%i:%s %Y%d%mX%TZD4X%TZR');
09:30:17.000 AM 07/03/2014 Europe/Bucharest EEST

When you use a general character, 'X', as a separator to separate each value, TZD value's string length is variable; therefore, it is confused to separate TZD value and a separator. In this case, TZD values' length should be specified.

Example of date_lang_string_literal

Format Element date_lang_string_literal
'en_US' 'ko_KR'
MONTH JANUARY 1월
MON JAN 1
DAY MONDAY 월요일
DY MON
Month January 1월
Mon Jan 1
Day Monday 월요일
Dy Mon
month january 1월
mon jan 1
day monday 월요일
Dy mon
AM AM 오전
Am Am 오전
am am 오전
A.M. A.M. 오후
A.m. A.m. 오전
a.m. a.m. 오전
PM PM 오후
Pm Pm 오후
pm pm 오후
P.M. P.M. 오후
P.m. P.m. 오후
p.m. p.m. 오후

Example of Format Digits of Return Value

Format Element en_US Digits | ko_KR Digits
MONTH(Month, month) 9 4
MON(Mon, mon) 3 2
DAY(Day, day) 9 6
DY(Dy, dy) 3 2
HH12, HH24 2 2
"text" The length of the text The length of the text
Other formats Same as the length of the format Same as the length of the format

The following example shows the query executed by setting the language and charset to "en_US.iso88591".

-- create database testdb en_US.iso88591

--creating a table having date/time type columns
CREATE TABLE datetime_tbl(a TIME, b DATE, c TIMESTAMP, d DATETIME);
INSERT INTO datetime_tbl VALUES(SYSTIME, SYSDATE, SYSTIMESTAMP, SYSDATETIME);

--selecting a VARCHAR type string from the data in the specified format
SELECT TO_CHAR(b, 'DD, DY , MON, YYYY') FROM datetime_tbl;
'20, TUE , AUG, 2013'
SELECT TO_CHAR(c, 'HH24:MI, DD, MONTH, YYYY') FROM datetime_tbl;
'17:00, 20, AUGUST   , 2013'
SELECT TO_CHAR(d, 'HH12:MI:SS:FF pm, YYYY-MM-DD-DAY') FROM datetime_tbl;
'05:00:58:358 pm, 2013-08-20-TUESDAY  '
SELECT TO_CHAR(TIMESTAMP'2009-10-04 22:23:00', 'Day Month yyyy');
'Sunday    October   2009'

The following example shows an additional language parameter given to the TO_CHAR function in the database created above. When the charset is ISO-8859-1, setting the language parameter of the TO_CHAR function to "tr_TR" or "ko_KR" is allowed, but the other languages are not allowed. To use all languages by setting the language parameter of TO_CHAR, the charset when creating DB should be UTF-8.

SELECT TO_CHAR(TIMESTAMP'2009-10-04 22:23:00', 'Day Month yyyy','ko_KR');
'Iryoil    10wol 2009'
SELECT TO_CHAR(TIMESTAMP'2009-10-04 22:23:00', 'Day Month yyyy','tr_TR');
'Pazar     Ekim    2009'

Note

  • In the function that interprets the month/day in characters and AM/PM differently by language, if the charset is ISO-8859-1, the language can be changed to "ko_KR" or "tr_TR" only by using the intl_date_lang except "en_US" (see the above example). If the charset is UTF-8, the language can be changed to any language supported by CUBRID. By setting the intl_date_lang system parameter or by specifying the language parameter of the TO_CHAR function, the language can be changed to one of all the languages supported by CUBRID (see date_lang_string_literal of "Syntax" above). For a list of functions that interpret the date/time differently by language, see the description of the intl_date_lang system parameter.

    -- change date locale as "de_DE" and run the below query.
    -- This case is failed because database locale, en_US's charset is ISO-8859-1
    -- and 'de_DE' only supports UTF-8 charset.
    
    SELECT TO_CHAR(TIMESTAMP'2009-10-04 22:23:00', 'Day Month yyyy','de_DE');
    
    ERROR: before ' , 'Day Month yyyy','de_DE'); '
    Locales for language 'de_DE' are not available with charset 'iso8859-1'.
    

    The following example shows how to set the language parameter of the TO_CHAR function to "de_DE" when you created DB with the locale "en_US.utf8".

    SELECT TO_CHAR(TIMESTAMP'2009-10-04 22:23:00', 'Day Month yyyy','de_DE');
    
    'Sonntag   Oktober 2009'
    
  • If the first argument is zerodate and the second argument has a literal like 'Month', 'Day', then TO_CHAR function returns NULL.

    SELECT TO_CHAR(timestamp '0000-00-00 00:00:00', 'Month Day YYYY');
    
    NULL
    

The following is an example to output date/time type with timezone in TO_CHAR function.

If you don't define a format, it outputs as the following format

SELECT TO_CHAR(datetimetz'2001-10-11 02:03:04 AM Europe/Bucharest EEST');
'02:03:04.000 AM 10/11/2001 Europe/Bucharest EEST'

If you define a format, it outputs as the defined format.

SELECT TO_CHAR(datetimetz'2001-10-11 02:03:04 AM Europe/Bucharest EEST', 'MM/DD/YYYY HH24:MI TZR TZD TZH TZM');
'10/11/2001 02:03 Europe/Bucharest EEST +03 +00'
TO_CHAR(number)
TO_CHAR(number[, format[, number_lang_string_literal]])

The TO_CHAR function converts a numeric data type to a character string according to Number Format and returns it. The type of the return value is VARCHAR .

Parameters:
  • number -- Specifies an expression that returns numeric data type string. If the input value is NULL, NULL is returned. If the input value is character type, the character itself is returned.
  • format -- Specifies a format of return value. If format is not specified, all significant figures are returned as character string by default. If the value is NULL, NULL is returned.
  • number_lang_string_literal -- Specifies the language to be applied to the input value.
Return type:

STRING

If format argument is specified, number is converted into a character string according to a specified language. At this time, the language is defined by the number_lang_string_literal argument. If number_lang_string_literal is omitted, the language specified by intl_number_lang system parameter is applied; if intl_number_lang is not set, the language specified when creating DB is applied.

For example, if the language is one of the European languages, such as "de_DE" or "fr_FR", "." is printed out as a thousands separator and "," is printed out as a decimal point. If the format argument does not correspond to the given string, the function returns an error.

If format argument is omitted, number is converted into a character string according to the default format of a specified language(see the table Default Output of Number for Each Language).

Number Format

Format Element Example Description
9 9999 The number of 9's represents the number of significant figures to be returned. If the number of significant figures specified in the format is not sufficient, only the decimal part is rounded. If it is less than the number of digits in an integer, # is outputted. If the number of significant figures specified in the format is sufficient, the part preceding the integer part is filled with space characters and the decimal part is filled with 0.
0 0999 If the number of significant figures specified in the format is sufficient, the part preceding the integer part is filled with 0, not space characters before the value is returned.
S S9999 Outputs the negative/positive sign in the specified position. These signs can be used only at the beginning of character string.
C C9999 Returns the ISO currency code at the specified position.
, (comma) 9,999 Returns a comma (",") at the specified position. Multiple commas are allowed in the format.
. (decimal point) 9.999 Returns a decimal point (".") which distinguishes between a decimal and an at the specified position. Only one decimal point is allowed in the format. see the table, Default Output of Number for Each Language
EEEE 9.99EEEE Returns a scientific notation number.

Default Output of Number for Each Language

Language Locale Number of Digits Decimal Symbol Example of Number Usage
English en_US ,(comma) .(period) 123,456,789.012
German de_DE .(period) ,(comma) 123.456.789,012
Spanish es_ES .(period) ,(comma) 123.456.789,012
French fr_FR .(period) ,(comma) 123.456.789,012
Italian it_IT .(period) ,(comma) 123.456.789,012
Japanese ja_JP ,(comma) .(period) 123,456,789.012
Cambodian km_KH .(period) ,(comma) 123.456.789,012
Korean ko_KR ,(comma) .(period) 123,456,789.012
Turkish tr_TR .(period) ,(comma) 123.456.789,012
Vietnamese vi_VN .(period) ,(comma) 123.456.789,012
Chinese zh_CN ,(comma) .(period) 123,456,789.012
Romanian ro_RO .(period) ,(comma) 123.456.789,012

The following example shows execution of the database by the locale specified when creating DB to "en_US.utf8".

--selecting a string casted from a number in the specified format
SELECT TO_CHAR(12345,'S999999'), TO_CHAR(12345,'S099999');
' +12345'             '+012345'
SELECT TO_CHAR(1234567,'9,999,999,999');
'    1,234,567'
SELECT TO_CHAR(1234567,'9.999.999.999');
'##############'
SELECT TO_CHAR(123.4567,'99'), TO_CHAR(123.4567,'999.99999'), TO_CHAR(123.4567,'99999.999');
'##'                  '123.45670'           '  123.457'

The following example shows command execution by setting the value of the intl_number_lang system parameter to "de_DE". In the number output format of most European countries such as Germany and France, "." is the cipher identifier and "," is the decimal point symbol.

SET SYSTEM PARAMETERS 'intl_number_lang="de_DE"';

--selecting a string casted from a number in the specified format
SELECT TO_CHAR(12345,'S999999'), TO_CHAR(12345,'S099999');
' +12345'             '+012345'
SELECT TO_CHAR(1234567,'9,999,999,999');
'##############'
SELECT TO_CHAR(1234567,'9.999.999.999');
'    1.234.567'
SELECT TO_CHAR(123.4567,'99'), TO_CHAR(123.4567,'999,99999'), TO_CHAR(123.4567,'99999,999');
'##'                  '123,45670'           '  123,457'
SELECT TO_CHAR(123.4567,'99','en_US'), TO_CHAR(123.4567,'999.99999','en_US'), TO_CHAR(123.4567,'99999.999','en_US');
'##'                  '123.45670'           '  123.457'
SELECT TO_CHAR(1.234567,'99.999EEEE','en_US'), TO_CHAR(1.234567,'99,999EEEE','de_DE'), to_char(123.4567);
'1.235E+00'           '1,235E+00'           '123,4567'
TO_DATE
TO_DATE(string[, format[, date_lang_string_literal]])

The TO_DATE function interprets a character string based on the date format given as an argument, converts it to a DATE type value, and returns it. For the format, see Date/Time Format 1.

Parameters:
  • string -- A character string
  • format -- Specifies a format of return value to be converted as DATE type. See Date/Time Format 1. If the value is NULL, NULL is returned.
  • date_lang_string_literal -- Specifies the language for the input value to be applied.
Return type:

DATE

When the format argument is specified, the string is interpreted according to the specified language. At this time, the language is set by date_lang_string_literal argument. If date_lang_string_literal argument is not set, the language is specified by the intl_date_lang system parameter; if the value of intl_date_lang is not set, the language is applied by the language specified when creating DB.

For example, when a language is "de_DE" and string is "12.mai.2012", and format is "DD.mon.YYYY", it is interpreted as May 12th, 2012.When the format parameter specified does not correspond to the given string, an error is returned.

When the format argument is omitted, string is interpreted as the CUBRID default format (refer to Recommended Format for Strings in Date/Time Type) and if it fails, string is interpreted as the language format (see the table Default Output Format of Language in the TO_CHAR()) by intl_date_lang. If the value of intl_date_lang is not set, the language is applied by the language specified when creating DB.

For example, when a language is "de_DE", the acceptable strings for DATE type are "MM/DD/YYYY", CUBRID default format and "DD.MM.YYYY", "de_DE" default format.

The following example shows the query executed by the locale specified when creating DB to "en_US.utf8".

--selecting a date type value casted from a string in the specified format

SELECT TO_DATE('12/25/2008');
12/25/2008
SELECT TO_DATE('25/12/2008', 'DD/MM/YYYY');
12/25/2008
SELECT TO_DATE('081225', 'YYMMDD');
12/25/2008
SELECT TO_DATE('2008-12-25', 'YYYY-MM-DD');
12/25/2008

The following example shows the query executed when the system parameter intl_date_lang is "de_DE".

SET SYSTEM PARAMETERS 'intl_date_lang="de_DE"';
SELECT TO_DATE('25.12.2012');
12/25/2012
SELECT TO_DATE('12/mai/2012','dd/mon/yyyy', 'de_DE');
05/12/2012

Note

When the charset is ISO-8859-1, the language that can be changed by the system parameter intl_date_lang is "ko_KR" and "tr_TR" except "en_US". If the charset is UTF-8, it can be changed to any language supported by CUBRID. For details, see Note in the TO_CHAR()).

TO_DATETIME
TO_DATETIME(string[, format[, date_lang_string_literal]])

The TO_DATETIME function interprets a character string based on the date-time format given as an argument, converts it to a DATETIME type value, and returns it. For the format, see Date/Time Format 1.

Parameters:
  • string -- A character string
  • format -- Specifies a format of return value to be converted as DATETIME type. See the table, Date/Time Format 1. If the value is NULL, NULL is returned.
  • date_lang_string_literal -- Specifies the language for the input value to be applied.
Return type:

DATETIME

When the format argument is specified, the string is interpreted according to the specified language.

For example, when a language is "de_DE" and string is "12/mai/2012 12:10:00 Nachm." and format is "DD/MON/YYYY HH:MI:SS AM", it is interpreted as May 12th, 2012 12:10:00 PM. At this time, the language is set by date_lang_string_literal argument. If date_lang_string_literal argument is not set, the language is specified by the intl_date_lang system parameter; if the value of intl_date_lang is not set, the language is specified by the language specified when creating DB. When the format parameter specified does not correspond to the given string, an error is returned.

When the format argument is omitted, string is interpreted as the CUBRID default format (refer to Recommended Format for Strings in Date/Time Type) and if it fails, string is interpreted as the language format (see the table Default Output Format of Language in the TO_CHAR()) by intl_date_lang. If the value of intl_date_lang is not set, the language is applied by the language specified when creating DB.

For example, when a language is "de_DE", the acceptable strings for DATETIME type are "HH:MI:SS.FF AM MM/DD/YYYY", CUBRID default format and "HH24:MI:SS.FF DD.MM.YYYY", "de_DE" default format.

Note

The CUBRID_DATE_LANG environment used in earlier version of CUBRID 9.0 is no longer supported.

The following example shows execution of the database by setting the environment variable CUBRID_CHARSET to "en_US".

--selecting a datetime type value casted from a string in the specified format

SELECT TO_DATETIME('13:10:30 12/25/2008');
01:10:30.000 PM 12/25/2008
SELECT TO_DATETIME('08-Dec-25 13:10:30.999', 'YY-Mon-DD HH24:MI:SS.FF');
01:10:30.999 PM 12/25/2008
SELECT TO_DATETIME('DATE: 12-25-2008 TIME: 13:10:30.999', '"DATE:" MM-DD-YYYY "TIME:" HH24:MI:SS.FF');
01:10:30.999 PM 12/25/2008

The following example shows the case when the system parameter intl_date_lang is "de_DE".

SET SYSTEM PARAMETERS 'intl_date_lang="de_DE"';
SELECT TO_DATETIME('13:10:30.999 25.12.2012');
01:10:30.999 PM 12/25/2012
SELECT TO_DATETIME('12/mai/2012 12:10:00 Nachm.','DD/MON/YYYY HH:MI:SS AM', 'de_DE');
12:10:00.000 PM 05/12/2012

Note

When the charset is ISO-8859-1, the language that can be changed in TO_DATETIME function is "ko_KR" and "tr_TR" except "en_US". If the charset is UTF-8, it can be changed to any language supported by CUBRID. For details, see Note in the TO_CHAR().

TO_DATETIME_TZ
TO_DATETIME_TZ(string[, format[, date_lang_string_literal]])

TO_DATETIME_TZ function is the same as TO_DATETIME() function except that this function can include a timezone information on this input string.

Return type:DATETIMETZ
SELECT TO_DATETIME_TZ('13:10:30 Asia/Seoul 12/25/2008', 'HH24:MI:SS TZR MM/DD/YYYY');
01:10:30.000 PM 12/25/2008 Asia/Seoul
TO_NUMBER
TO_NUMBER(string[, format])

The TO_NUMBER function interprets a character string based on the number format given as an argument, converts it to a NUMERIC type value, and returns it.

Parameters:
  • string -- Specifies an expression that returns character string. If the value is NULL, NULL is returned.
  • format -- Specifies a format of return value to be converted as NUMBER type. See Number Format. If it is omitted, NUMERIC(38,0) value is returned.
Return type:

NUMERIC

When the format argument is assigned, the string is interpreted according to the specified language. At this time, the language is specified by the intl_number_lang system parameter. If the value of intl_number_lang is not set, the language specified when creating DB is applied.

For example, when the language is one of the European languages, such as "de_DE" and "fr_FR", "." is interpreted as the cipher identifier and "," as the decimal point symbol. When the format parameter specified does not correspond to the given string, an error is returned.

If the format argument is omitted, string is interpreted according to the default output format set by intl_number_lang (see Default Output of Number for Each Language). When the intl_number_lang is not set, the language specified when creating DB is applied.

The following example shows execution of the database by setting the value of system parameter intl_number_lang as "en_US".

SET SYSTEM PARAMETERS 'intl_number_lang="en_US"';

--selecting a number casted from a string in the specified format
SELECT TO_NUMBER('-1234');
-1234
SELECT TO_NUMBER('12345','999999');
12345
SELECT TO_NUMBER('12,345.67','99,999.999');
12345.670
SELECT TO_NUMBER('12345.67','99999.999');
12345.670

The following example shows command execution on the database by setting the value of the intl_number_lang system parameter to "de_DE". In the number output format of most European countries, such as Germany and France, "." is the cipher identifier and "," is the decimal point symbol.

SET SYSTEM PARAMETERS 'intl_number_lang="de_DE"';
SELECT TO_NUMBER('12.345,67','99.999,999');
12345.670
TO_TIME
TO_TIME(string[, format[, date_lang_string_literal]])

The TO_TIME function interprets a character string based on the time format given as an argument, converts it to a TIME type value, and returns it. For the format, see Date/Time Format 1.

Parameters:
  • string -- Specifies an expression that returns character string. If the value is NULL, NULL is returned.
  • format -- Specifies a format of return value to be converted as TIME type. See Date/Time Format 1. If the value is NULL, NULL is returned.
  • date_lang_string_literal -- Specifies the language for the input value to be applied.
Return type:

TIME

When the format argument is specified, the string is interpreted according to the specified language. At this time, the language is set by date_lang_string_literal argument. If date_lang_string_literal argument is not set, the language is specified by the intl_date_lang system parameter; if the value of intl_date_lang is not set, the language specified when creating DB is applied. When the format parameter does not correspond to the given string, an error is returned.

For example, when a language is "de_DE" and string is "10:23:00 Nachm.", and format is "HH/MI/SS/AM, it is interpreted as 10:23:00 PM.

When the format argument is omitted, string is interpreted as the CUBRID default format (refer to Recommended Format for Strings in Date/Time Type) and if it fails, string is interpreted as the language format (see the table Default Output Format of Language in the TO_CHAR()) by intl_date_lang. If the value of intl_date_lang is not set, the language is applied by the language specified when creating DB.

For example, when a language is "de_DE", the acceptable strings for TIME type are "HH:MI:SS AM", CUBRID default format and "HH24:MI:SS", "de_DE" default format.

Note

The CUBRID_DATE_LANG environment used in earlier version of CUBRID 9.0 is no longer supported.

The following example shows execution of the database by setting the value of system parameter intl_date_lang as "en_US".

SET SYSTEM PARAMETERS 'intl_date_lang="en_US"';

--selecting a time type value casted from a string in the specified format

SELECT TO_TIME ('13:10:30');
01:10:30 PM
SELECT TO_TIME('HOUR: 13 MINUTE: 10 SECOND: 30', '"HOUR:" HH24 "MINUTE:" MI "SECOND:" SS');
01:10:30 PM
SELECT TO_TIME ('13:10:30', 'HH24:MI:SS');
01:10:30 PM
SELECT TO_TIME ('13:10:30', 'HH12:MI:SS');
ERROR: Conversion error in date format.

The following example shows the case when the system parameter intl_date_lang is "de_DE".

SET SYSTEM PARAMETERS 'intl_date_lang="de_DE"';
SELECT TO_TIME('13:10:30');
01:10:30 PM
SELECT TO_TIME('10:23:00 Nachm.', 'HH:MI:SS AM');
10:23:00 PM

Note

When the charset is ISO-8859-1, the language that can be changed by the system parameter intl_date_lang is "ko_KR" and "tr_TR" except "en_US". If the charset is UTF-8, it can be changed to any language supported by CUBRID. For details, see Note in the TO_CHAR()).

TO_TIMESTAMP
TO_TIMESTAMP(string[, format[, date_lang_string_literal]])

The TO_TIMESTAMP function interprets a character string based on the time format given as an argument, converts it to a TIMESTAMP type value, and returns it. For the format, see Date/Time Format 1.

Parameters:
  • string -- Specifies an expression that returns character string. If the value is NULL, NULL is returned.
  • format -- Specifies a format of return value to be converted as TIMESTAMP type. See Date/Time Format 1. If the value is NULL, NULL is returned.
  • date_lang_string_literal -- Specifies the language for the input value to be applied.
Return type:

TIMESTAMP

When the format argument is specified, the string is interpreted according to the specified language. The language is set by date_lang_string_literal argument. If date_lang_string_literal argument is not set, the language is specified by the intl_date_lang system parameter; if the value of intl_date_lang is not set, the language specified when creating DB is applied.

For example, when a language is "de_DE" and string is "12/mai/2012 12:10:00 Nachm.", and format is "DD/MON/YYYY HH:MI:SS AM", it is interpreted as May 12th, 2012, 12:10:00 AM. When the format parameter specified does not correspond to the given string, an error is returned.

When the format argument is omitted, string is interpreted as the CUBRID default format(refer to Recommended Format for Strings in Date/Time Type) and if it fails, string is interpreted as the language format (see the table Default Output Format of Language in the TO_CHAR()) by intl_date_lang. If the value of intl_date_lang is not set, the language is applied by the language specified when creating DB.

For example, when a language is "de_DE", the acceptable strings for TIMESTAMP type are "HH:MI:SS AM MM/DD/YYYY", CUBRID default format and "HH24:MI:SS DD.MM.YYYY", "de_DE" default format.

The following example shows execution of the database by setting the value of system parameter intl_date_lang as "en_US".

SET SYSTEM PARAMETERS 'intl_date_lang="en_US"';

--selecting a timestamp type value casted from a string in the specified format

SELECT TO_TIMESTAMP('13:10:30 12/25/2008');
01:10:30 PM 12/25/2008
SELECT TO_TIMESTAMP('08-Dec-25 13:10:30', 'YY-Mon-DD HH24:MI:SS');
01:10:30 PM 12/25/2008
SELECT TO_TIMESTAMP('YEAR: 2008 DATE: 12-25 TIME: 13:10:30', '"YEAR:" YYYY "DATE:" MM-DD "TIME:" HH24:MI:SS');
01:10:30 PM 12/25/2008

The following example shows the case when the system parameter intl_date_lang is "de_DE".

SET SYSTEM PARAMETERS 'intl_date_lang="de_DE"';
SELECT TO_TIMESTAMP('13:10:30 25.12.2008');
01:10:30 PM 12/25/2008
SELECT TO_TIMESTAMP('10:23:00 Nachm.', 'HH12:MI:SS AM');
10:23:00 PM 08/01/2012

Note

When the charset is ISO-8859-1, the language that can be changed by the system parameter intl_date_lang is "ko_KR" and "tr_TR" except "en_US". If the charset is UTF-8, it can be changed to any language supported by CUBRID. For details, see Note in the TO_CHAR()).

TO_TIMESTAMP_TZ
TO_TIMESTAMP_TZ(string[, format[, date_lang_string_literal]])

TO_TIMESTAMP_TZ function is the same as TO_TIMESTAMP() function except that this function can include a timezone information on this input string.

rtype:TIMESTAMPTZ
SELECT TO_TIMESTAMP_TZ('13:10:30 Asia/Seoul 12/25/2008', 'HH24:MI:SS TZR MM/DD/YYYY');
01:10:30 PM 12/25/2008 Asia/Seoul
Aggregate/Analytic Functions
Overview

Aggregate/Analytic function is used when you want to analyze data and extract some results.

  • Aggregate function returns the grouped results and it returns only the columns which are grouped.
  • Analytic function returns the grouped results, but it includes the ungrouped columns, so it can return multiple rows for one group.

For examples, aggregate/analytic function can be used to get the answers as follows.

  1. What is the total sales amount per year?
  2. How can you display the sales amount from the highest one's month by grouping each year?
  3. How can you display the accumulated sales amount as annual and monthly order by grouping each year?

You can answer for No. 1 with aggregate function. for No. 2 and No. 3, you can answer with analytic function. Above questions can be written as following SQL statements.

Below is the table which stores the sales amounts per month of each year.

CREATE TABLE sales_mon_tbl (
    yyyy INT,
    mm INT,
    sales_sum INT
);

INSERT INTO sales_mon_tbl VALUES
    (2000, 1, 1000), (2000, 2, 770), (2000, 3, 630), (2000, 4, 890),
    (2000, 5, 500), (2000, 6, 900), (2000, 7, 1300), (2000, 8, 1800),
    (2000, 9, 2100), (2000, 10, 1300), (2000, 11, 1500), (2000, 12, 1610),
    (2001, 1, 1010), (2001, 2, 700), (2001, 3, 600), (2001, 4, 900),
    (2001, 5, 1200), (2001, 6, 1400), (2001, 7, 1700), (2001, 8, 1110),
    (2001, 9, 970), (2001, 10, 690), (2001, 11, 710), (2001, 12, 880),
    (2002, 1, 980), (2002, 2, 750), (2002, 3, 730), (2002, 4, 980),
    (2002, 5, 1110), (2002, 6, 570), (2002, 7, 1630), (2002, 8, 1890),
    (2002, 9, 2120), (2002, 10, 970), (2002, 11, 420), (2002, 12, 1300);
  1. What is the total sales amount per year?
SELECT yyyy, sum(sales_sum)
FROM sales_mon_tbl
GROUP BY yyyy;
         yyyy  sum(sales_sum)
=============================
         2000           14300
         2001           11870
         2002           13450
  1. How can you display the sales amount from the highest one's month by grouping each year?
SELECT yyyy, mm, sales_sum, RANK() OVER (PARTITION BY yyyy ORDER BY sales_sum DESC) AS rnk
FROM sales_mon_tbl;
         yyyy           mm    sales_sum          rnk
====================================================
         2000            9         2100            1
         2000            8         1800            2
         2000           12         1610            3
         2000           11         1500            4
         2000            7         1300            5
         2000           10         1300            5
         2000            1         1000            7
         2000            6          900            8
         2000            4          890            9
         2000            2          770           10
         2000            3          630           11
         2000            5          500           12
         2001            7         1700            1
         2001            6         1400            2
         2001            5         1200            3
         2001            8         1110            4
         2001            1         1010            5
         2001            9          970            6
         2001            4          900            7
         2001           12          880            8
         2001           11          710            9
         2001            2          700           10
         2001           10          690           11
         2001            3          600           12
         2002            9         2120            1
         2002            8         1890            2
         2002            7         1630            3
         2002           12         1300            4
         2002            5         1110            5
         2002            1          980            6
         2002            4          980            6
         2002           10          970            8
         2002            2          750            9
         2002            3          730           10
         2002            6          570           11
         2002           11          420           12
  1. How can you display the accumulated sales amount as annual and monthly order by grouping each year?
SELECT yyyy, mm, sales_sum, SUM(sales_sum) OVER (PARTITION BY yyyy ORDER BY yyyy, mm) AS a_sum
FROM sales_mon_tbl;
         yyyy           mm    sales_sum        a_sum
====================================================
         2000            1         1000         1000
         2000            2          770         1770
         2000            3          630         2400
         2000            4          890         3290
         2000            5          500         3790
         2000            6          900         4690
         2000            7         1300         5990
         2000            8         1800         7790
         2000            9         2100         9890
         2000           10         1300        11190
         2000           11         1500        12690
         2000           12         1610        14300
         2001            1         1010         1010
         2001            2          700         1710
         2001            3          600         2310
         2001            4          900         3210
         2001            5         1200         4410
         2001            6         1400         5810
         2001            7         1700         7510
         2001            8         1110         8620
         2001            9          970         9590
         2001           10          690        10280
         2001           11          710        10990
         2001           12          880        11870
         2002            1          980          980
         2002            2          750         1730
         2002            3          730         2460
         2002            4          980         3440
         2002            5         1110         4550
         2002            6          570         5120
         2002            7         1630         6750
         2002            8         1890         8640
         2002            9         2120        10760
         2002           10          970        11730
         2002           11          420        12150
         2002           12         1300        13450
Aggregate vs. Analytic

Aggregate function returns one result based on the group of rows. When the GROUP BY clause is included, a one-row aggregate result per group is returned. When the GROUP BY clause is omitted, a one-row aggregate result for all rows is returned. The HAVING clause is used to add a condition to the query which contains the GROUP BY clause.

Most aggregate functions can use DISTINCT, UNIQUE constraints. For the GROUP BY ... HAVING clause, see GROUP BY ... HAVING Clause.

Analytic function calculates the aggregate value based on the result of rows. The analytic function is different from the aggregate function since it can return one or more rows based on the groups specified by the <partition_by_clause> after the OVER clause (when this clause is omitted, all rows are regarded as a group).

The analytic function is used along with a new analytic clause, OVER, for the existing aggregate functions to allow a variety of statistics for a group of specific rows.

function_name ([<argument_list>]) OVER (<analytic_clause>)

<analytic_clause>::=
     [<partition_by_clause>] [<order_by_clause>]

<partition_by_clause>::=
    PARTITION BY value_expr[, value_expr]...

<order_by_clause>::=
    ORDER BY { expression | position | column_alias } [ ASC | DESC ]
        [, { expression | position | column_alias } [ ASC | DESC ] ] ...
  • <partition_by_clause>: Groups based on one or more value_expr. It uses the PARTITION BY clause to partition the query result.
  • <order_by_clause>: defines the data sorting method in the partition made by <partition_by_clause>. The result can be sorted with several keys. When <partition_by_clause> is omitted, the data is sorted within the overall result sets. Based on the sorting order, the function is applied to the column values of accumulated records, including the previous values.

The behavior of a query with the expression of ORDER BY/PARTITION BY clause which is used together after the OVER clause is as follows.

  • ORDER BY/PARTITION BY <expression with non-constant> (ex: i, sin(i+1)): The expression is used to do ordering/partitioning.
  • ORDER BY/PARTITION BY <constant> (ex: 1): Constant is considered as the column position of SELECT list.
  • ORDER BY/PARTITION BY <constant expression> (ex: 1+0): Constant is ignored and it is not used to do ordering/partitioning.
Analytic functions which "ORDER BY" clause must be specified in OVER function

The below functions require ordering; therefore, "ORDER BY" clause must be specified inside OVER function. In the case of omitting "ORDER BY" clause, please note that an error occurs or proper ordering is not guaranteed.

AVG
AVG([ DISTINCT | DISTINCTROW | UNIQUE | ALL ] expression)
AVG([ DISTINCT | DISTINCTROW | UNIQUE | ALL ] expression) OVER (<analytic_clause>)

The AVG function is used as an aggregate function or an analytic function. It calculates the arithmetic average of the value of an expression representing all rows. Only one expression is specified as a parameter. You can get the average without duplicates by using the DISTINCT or UNIQUE keyword in front of the expression or the average of all values by omitting the keyword or by using ALL.

Parameters:
  • expression -- Specifies an expression that returns a numeric value. An expression that returns a collection-type data is not allowed.
  • ALL -- Calculates an average value for all data (default).
  • DISTINCT,DISTINCTROW,UNIQUE -- Calculates an average value without duplicates.
Return type:

DOUBLE

The following example shows how to retrieve the average number of gold medals that Korea won in Olympics in the demodb database.

SELECT AVG(gold)
FROM participant
WHERE nation_code = 'KOR';
                 avg(gold)
==========================
     9.600000000000000e+00

The following example shows how to output the number of gold medals by year and the average number of accumulated gold medals in history, acquired whose nation_code starts with 'AU'.

SELECT host_year, nation_code, gold,
    AVG(gold) OVER (PARTITION BY nation_code ORDER BY host_year) avg_gold
FROM participant WHERE nation_code like 'AU%';
    host_year  nation_code                  gold               avg_gold
=======================================================================
         1988  'AUS'                           3  3.000000000000000e+00
         1992  'AUS'                           7  5.000000000000000e+00
         1996  'AUS'                           9  6.333333333333333e+00
         2000  'AUS'                          16  8.750000000000000e+00
         2004  'AUS'                          17  1.040000000000000e+01
         1988  'AUT'                           1  1.000000000000000e+00
         1992  'AUT'                           0  5.000000000000000e-01
         1996  'AUT'                           0  3.333333333333333e-01
         2000  'AUT'                           2  7.500000000000000e-01
         2004  'AUT'                           2  1.000000000000000e+00

The following example is removing the "ORDER BY host_year" clause under the OVER analysis clause from the above example. The avg_gold value is the average of gold medals for all years, so the value is identical for every year by nation_code.

SELECT host_year, nation_code, gold, AVG(gold) OVER (PARTITION BY nation_code) avg_gold
FROM participant WHERE nation_code LIKE 'AU%';
    host_year  nation_code                  gold                  avg_gold
==========================================================================
         2004  'AUS'                          17     1.040000000000000e+01
         2000  'AUS'                          16     1.040000000000000e+01
         1996  'AUS'                           9     1.040000000000000e+01
         1992  'AUS'                           7     1.040000000000000e+01
         1988  'AUS'                           3     1.040000000000000e+01
         2004  'AUT'                           2     1.000000000000000e+00
         2000  'AUT'                           2     1.000000000000000e+00
         1996  'AUT'                           0     1.000000000000000e+00
         1992  'AUT'                           0     1.000000000000000e+00
         1988  'AUT'                           1     1.000000000000000e+00
COUNT
COUNT(*)
COUNT(*) OVER (<analytic_clause>)
COUNT([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression)
COUNT([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>)

The COUNT function is used as an aggregate function or an analytic function. It returns the number of rows returned by a query. If an asterisk (*) is specified, the number of all rows satisfying the condition (including the rows with the NULL value) is returned. If the DISTINCT or UNIQUE keyword is specified in front of the expression, only the number of rows that have a unique value (excluding the rows with the NULL value) is returned after duplicates have been removed. Therefore, the value returned is always an integer and NULL is never returned.

Parameters:
  • expression -- Specifies an expression.
  • ALL -- Gets the number of rows given in the expression (default).
  • DISTINCT,DISTINCTROW,UNIQUE -- Gets the number of rows without duplicates.
Return type:

INT

A column that has collection type and object domain (user-defined class) can also be specified in the expression.

The following example shows how to retrieve the number of Olympic Games that have a mascot in the demodb database.

SELECT COUNT(*)
FROM olympic
WHERE mascot IS NOT NULL;
     count(*)
=============
            9

The following example shows how to output the number of players whose nation_code is 'AUT' in demodb by accumulating the number of events when the event is changed. The last row shows the number of all players.

SELECT nation_code, event, name, COUNT(*) OVER (ORDER BY event) co
FROM athlete WHERE nation_code='AUT';
   nation_code           event                 name                           co
===============================================================================
  'AUT'                 'Athletics'           'Kiesl Theresia'                2
  'AUT'                 'Athletics'           'Graf Stephanie'                2
  'AUT'                 'Equestrian'          'Boor Boris'                    6
  'AUT'                 'Equestrian'          'Fruhmann Thomas'               6
  'AUT'                 'Equestrian'          'Munzner Joerg'                 6
  'AUT'                 'Equestrian'          'Simon Hugo'                    6
  'AUT'                 'Judo'                'Heill Claudia'                 9
  'AUT'                 'Judo'                'Seisenbacher Peter'            9
  'AUT'                 'Judo'                'Hartl Roswitha'                9
  'AUT'                 'Rowing'              'Jonke Arnold'                 11
  'AUT'                 'Rowing'              'Zerbst Christoph'             11
  'AUT'                 'Sailing'             'Hagara Roman'                 15
  'AUT'                 'Sailing'             'Steinacher Hans Peter'        15
  'AUT'                 'Sailing'             'Sieber Christoph'             15
  'AUT'                 'Sailing'             'Geritzer Andreas'             15
  'AUT'                 'Shooting'            'Waibel Wolfram Jr.'           17
  'AUT'                 'Shooting'            'Planer Christian'             17
  'AUT'                 'Swimming'            'Rogan Markus'                 18
CUME_DIST
CUME_DIST(expression[, expression] ...) WITHIN GROUP (<order_by_clause>)
CUME_DIST() OVER ([<partition_by_clause>] <order_by_clause>)

CUME_DIST function is used as an aggregate function or an analytic function. It returns the value of cumulated distribution about the specified value within the group. The range of a return value by CUME_DIST is 0> and 1<=. The return value of CUME_DIST about the same input argument is evaluated as the same cumulated distribution value.

Parameters:
  • expression -- an expression which returns the number or string. This should not be a column.
  • order_by_clause -- column names followed by ORDER BY clause should be matched to the number of expressions
Return type:

DOUBLE

If it is used as an aggregate function, CUME_DIST sorts the data by the order specified in ORDER BY clause; then it returns the relative position of a hypothetical row in the rows of aggregate group. At this time, the position is calculated as if a hypothetical row is newly inserted. That is, CUME_DIST returns ("cumulated RANK of a hypothetical row" + 1)/("the number of total rows in an aggregate group").

If it is used as an analytic function, CUME_DIST returns the relative position in the value of the group after sorting each row(ORDER BY) with each partitioned group(PARTITION BY). The relative position is that the number of rows which have values less than or equal to the input argument is divided by the number of total rows within the group(rows grouped by the partition_by_clause or the total rows). That is, it returns (cumulated RANK of a certain row)/(the number or rows within the group). For example, the number of rows which has the RANK 1 is 2, CUME_DUST values of the first and the second rows will be "2/10 = 0.2".

The following is a schema and data to use in the example of this function.

CREATE TABLE scores(id INT PRIMARY KEY AUTO_INCREMENT, math INT, english INT, pe CHAR, grade INT);

INSERT INTO scores(math, english, pe, grade)
       VALUES(60, 70, 'A', 1),
       (60, 70, 'A', 1),
       (60, 80, 'A', 1),
       (60, 70, 'B', 1),
       (70, 60, 'A', 1) ,
       (70, 70, 'A', 1) ,
       (80, 70, 'C', 1) ,
       (70, 80, 'C', 1),
       (85, 60, 'C', 1),
       (75, 90, 'B', 1);
INSERT INTO scores(math, english, pe, grade)
       VALUES(95, 90, 'A', 2),
       (85, 95, 'B', 2),
       (95, 90, 'A', 2),
       (85, 95, 'B', 2),
       (75, 80, 'D', 2),
       (75, 85, 'D', 2),
       (75, 70, 'C', 2),
       (65, 95, 'A', 2),
       (65, 95, 'A', 2),
       (65, 95, 'A', 2);

The following is an example to be used as an aggregate function; it returns the result that the sum of each cumulated distribution about each column - math, english and pe - is divided by 3.

SELECT CUME_DIST(60, 70, 'D')
WITHIN GROUP(ORDER BY math, english, pe) AS cume
FROM scores;
1.904761904761905e-01

The following is an example to be used as an analytic function; it returns the cumulated distributions of each row about the 3 columns - math, english and pe.

SELECT id, math, english, pe, grade, CUME_DIST() OVER(ORDER BY math, english, pe) AS cume_dist
FROM scores
ORDER BY cume_dist;
           id         math      english  pe                          grade                 cume_dist
====================================================================================================
            1           60           70  'A'                             1     1.000000000000000e-01
            2           60           70  'A'                             1     1.000000000000000e-01
            4           60           70  'B'                             1     1.500000000000000e-01
            3           60           80  'A'                             1     2.000000000000000e-01
           18           65           95  'A'                             2     3.500000000000000e-01
           19           65           95  'A'                             2     3.500000000000000e-01
           20           65           95  'A'                             2     3.500000000000000e-01
            5           70           60  'A'                             1     4.000000000000000e-01
            6           70           70  'A'                             1     4.500000000000000e-01
            8           70           80  'C'                             1     5.000000000000000e-01
           17           75           70  'C'                             2     5.500000000000000e-01
           15           75           80  'D'                             2     6.000000000000000e-01
           16           75           85  'D'                             2     6.500000000000000e-01
           10           75           90  'B'                             1     7.000000000000000e-01
            7           80           70  'C'                             1     7.500000000000000e-01
            9           85           60  'C'                             1     8.000000000000000e-01
           12           85           95  'B'                             2     9.000000000000000e-01
           14           85           95  'B'                             2     9.000000000000000e-01
           11           95           90  'A'                             2     1.000000000000000e+00
           13           95           90  'A'                             2     1.000000000000000e+00

The following is an example to be used as an analytic function; it returns the cumulated distributions of each row about the 3 columns - math, english and pe - by grouping as grade column.

SELECT id, math, english, pe, grade, CUME_DIST() OVER(PARTITION BY grade ORDER BY math, english, pe) AS cume_dist
FROM scores
ORDER BY grade, cume_dist;
   id         math      english  pe                          grade                 cume_dist
============================================================================================
    1           60           70  'A'                             1     2.000000000000000e-01
    2           60           70  'A'                             1     2.000000000000000e-01
    4           60           70  'B'                             1     3.000000000000000e-01
    3           60           80  'A'                             1     4.000000000000000e-01
    5           70           60  'A'                             1     5.000000000000000e-01
    6           70           70  'A'                             1     6.000000000000000e-01
    8           70           80  'C'                             1     7.000000000000000e-01
   10           75           90  'B'                             1     8.000000000000000e-01
    7           80           70  'C'                             1     9.000000000000000e-01
    9           85           60  'C'                             1     1.000000000000000e+00
   18           65           95  'A'                             2     3.000000000000000e-01
   19           65           95  'A'                             2     3.000000000000000e-01
   20           65           95  'A'                             2     3.000000000000000e-01
   17           75           70  'C'                             2     4.000000000000000e-01
   15           75           80  'D'                             2     5.000000000000000e-01
   16           75           85  'D'                             2     6.000000000000000e-01
   12           85           95  'B'                             2     8.000000000000000e-01
   14           85           95  'B'                             2     8.000000000000000e-01
   11           95           90  'A'                             2     1.000000000000000e+00
   13           95           90  'A'                             2     1.000000000000000e+00

In the above result, the row that id is 1, is located at the first and the second on the total 10 rows, and the value of CUME_DUST is 2/10, that is, 0.2.

The row that id is 5, is located at the fifth on the total 10 rows, and the value of CUME_DUST is 5/10, that is, 0.5.

DENSE_RANK
DENSE_RANK() OVER ([<partition_by_clause>] <order_by_clause>)

DENSE_RANK function is used as an analytic function only. The rank of the value in the column value group made by the PARTITION BY clause is calculated and output as INTEGER. Even when there is the same rank, 1 is added to the next rank value. For example, when there are three rows of Rank 13, the next rank is 14, not 16. On the contrary, the RANK() function calculates the next rank by adding the number of same ranks.

Return type:INT

The following example shows output of the number of Olympic gold medals of each country and the rank of the countries by year: The number of the same rank is ignored and the next rank is calculated by adding 1 to the rank.

SELECT host_year, nation_code, gold,
DENSE_RANK() OVER (PARTITION BY host_year ORDER BY gold DESC) AS d_rank
FROM participant;
host_year  nation_code                  gold       d_rank
=============================================================
     1988  'URS'                          55            1
     1988  'GDR'                          37            2
     1988  'USA'                          36            3
     1988  'KOR'                          12            4
     1988  'HUN'                          11            5
     1988  'FRG'                          11            5
     1988  'BUL'                          10            6
     1988  'ROU'                           7            7
     1988  'ITA'                           6            8
     1988  'FRA'                           6            8
     1988  'KEN'                           5            9
     1988  'GBR'                           5            9
     1988  'CHN'                           5            9
...
     1988  'CHI'                           0           14
     1988  'ARG'                           0           14
     1988  'JAM'                           0           14
     1988  'SUI'                           0           14
     1988  'SWE'                           0           14
     1992  'EUN'                          45            1
     1992  'USA'                          37            2
     1992  'GER'                          33            3
...
     2000  'RSA'                           0           15
     2000  'NGR'                           0           15
     2000  'JAM'                           0           15
     2000  'BRA'                           0           15
     2004  'USA'                          36            1
     2004  'CHN'                          32            2
     2004  'RUS'                          27            3
     2004  'AUS'                          17            4
     2004  'JPN'                          16            5
     2004  'GER'                          13            6
     2004  'FRA'                          11            7
     2004  'ITA'                          10            8
     2004  'UKR'                           9            9
     2004  'CUB'                           9            9
     2004  'GBR'                           9            9
     2004  'KOR'                           9            9
...
     2004  'EST'                           0           17
     2004  'SLO'                           0           17
     2004  'SCG'                           0           17
     2004  'FIN'                           0           17
     2004  'POR'                           0           17
     2004  'MEX'                           0           17
     2004  'LAT'                           0           17
     2004  'PRK'                           0           17
FIRST_VALUE
FIRST_VALUE(expression) [{RESPECT|IGNORE} NULLS] OVER (<analytic_clause>)

FIRST_VALUE function is used as an analytic function only. It returns NULL if the first value in the set is null. But, if you specify IGNORE NULLS, the first value will be returned as excluding null or NULL will be returned if all values are null.

Parameters:expression -- a column or an expression which returns a number or a string. FIRST_VALUE function or other analytic function cannot be included.
Return type:a type of an expression

The following is schema and data to run the example.

CREATE TABLE test_tbl(groupid int,itemno int);
INSERT INTO test_tbl VALUES(1,null);
INSERT INTO test_tbl VALUES(1,null);
INSERT INTO test_tbl VALUES(1,1);
INSERT INTO test_tbl VALUES(1,null);
INSERT INTO test_tbl VALUES(1,2);
INSERT INTO test_tbl VALUES(1,3);
INSERT INTO test_tbl VALUES(1,4);
INSERT INTO test_tbl VALUES(1,5);
INSERT INTO test_tbl VALUES(2,null);
INSERT INTO test_tbl VALUES(2,null);
INSERT INTO test_tbl VALUES(2,null);
INSERT INTO test_tbl VALUES(2,6);
INSERT INTO test_tbl VALUES(2,7);

The following is a query and a result to run FIRST_VALUE function.

SELECT groupid, itemno, FIRST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val
FROM test_tbl;
      groupid       itemno      ret_val
=======================================
            1         NULL         NULL
            1         NULL         NULL
            1         NULL         NULL
            1            1         NULL
            1            2         NULL
            1            3         NULL
            1            4         NULL
            1            5         NULL
            2         NULL         NULL
            2         NULL         NULL
            2         NULL         NULL
            2            6         NULL
            2            7         NULL

Note

CUBRID sorts NULL value as first order than other values. The below SQL1 is interpreted as SQL2 which includes NULLS FIRST in ORDER BY clause.

SQL1: FIRST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val
SQL2: FIRST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno NULLS FIRST) AS ret_val

The following is an example to specify IGNORE NULLS.

SELECT groupid, itemno, FIRST_VALUE(itemno) IGNORE NULLS OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val
FROM test_tbl;
      groupid       itemno      ret_val
=======================================
            1         NULL         NULL
            1         NULL         NULL
            1         NULL         NULL
            1            1            1
            1            2            1
            1            3            1
            1            4            1
            1            5            1
            2         NULL         NULL
            2         NULL         NULL
            2         NULL         NULL
            2            6            6
            2            7            6
GROUP_CONCAT
GROUP_CONCAT([DISTINCT] expression [ORDER BY {column | unsigned_int} [ASC | DESC]] [SEPARATOR str_val])

The GROUP_CONCAT function is used as an aggregate function only. It connects the values that are not NULL in the group and returns the character string in the VARCHAR type. If there are no rows of query result or there are only NULL values, NULL will be returned.

Parameters:
  • expression -- Column or expression returning numerical values or character strings
  • str_val -- Character string to use as a separator
  • DISTINCT -- Removes duplicate values from the result.
  • ORDERBY -- Specifies the order of result values.
  • SEPARATOR -- Specifies the separator to divide the result values. If it is omitted, the default character, comma (,) will be used as a separator.
Return type:

STRING

The maximum size of the return value follows the configuration of the system parameter, group_concat_max_len. The default is 1024 bytes, the minimum value is 4 bytes and the maximum value is 33,554,432 bytes.

This function is affected by string_max_size_bytes parameter; if the value of group_concat_max_len is larger than the value string_max_size_bytes and the result size of GROUP_CONCAT exceeds the value of string_max_size_bytes, an error occurs.

To remove the duplicate values, use the DISTINCT clause. The default separator for the group result values is comma (,). To represent the separator explicitly, add the character string to use as a separator in the SEPARATOR clause and after that. If you want to remove separators, enter empty strings after the SEPARATOR clause.

If the non-character string type is passed to the result character string, an error will be returned.

To use the GROUP_CONCAT function, you must meet the following conditions.

  • Only one expression (or a column) is allowed for an input parameter.
  • Sorting with ORDER BY is available only in the expression used as a parameter.
  • The character string used as a separator allows not only character string type but also allows other types.
SELECT GROUP_CONCAT(s_name) FROM code;
  group_concat(s_name)
======================
  'X,W,M,B,S,G'
SELECT GROUP_CONCAT(s_name ORDER BY s_name SEPARATOR ':') FROM code;
  group_concat(s_name order by s_name separator ':')
======================
  'B:G:M:S:W:X'
CREATE TABLE t(i int);
INSERT INTO t VALUES (4),(2),(3),(6),(1),(5);

SELECT GROUP_CONCAT(i*2+1 ORDER BY 1 SEPARATOR '') FROM t;
  group_concat(i*2+1 order by 1 separator '')
======================
  '35791113'
LAG
LAG(expression[, offset[, default]]) OVER ([<partition_by_clause>] <order_by_clause>)

LAG is an analytic function that returns the expression value from a previous row, before offset that comes before the current row. It can be used to access several rows simultaneously without making any self join.

Parameters:
  • expression -- a column or an expression that returns a number or a string
  • offset -- an integer which indicates the offset position. If not specified, the default is 1
  • default -- a value to return when an expression value before offset is NULL. If a default value is not specified, NULL is returned
Return type:

NUMBER or STRING

The following example shows how to sort employee numbers and output the previous employee number on the same row:

CREATE TABLE t_emp (name VARCHAR(10), empno INT);
INSERT INTO t_emp VALUES
    ('Amie', 11011),
    ('Jane', 13077),
    ('Lora', 12045),
    ('James', 12006),
    ('Peter', 14006),
    ('Tom', 12786),
    ('Ralph', 23518),
    ('David', 55);

SELECT name, empno, LAG (empno, 1) OVER (ORDER BY empno) prev_empno
FROM t_emp;
  name                        empno   prev_empno
================================================
  'David'                        55         NULL
  'Amie'                      11011           55
  'James'                     12006        11011
  'Lora'                      12045        12006
  'Tom'                       12786        12045
  'Jane'                      13077        12786
  'Peter'                     14006        13077
  'Ralph'                     23518        14006

On the contrary, LEAD() function returns the expression value from a subsequent row, after offset that follows the current row.

LAST_VALUE
LAST_VALUE(expression) [{RESPECT|IGNORE} NULLS] OVER (<analytic_clause>)

LAST_VALUE function is used as an analytic function only. It returns NULL if the last value in the set is null. But, if you specify IGNORE NULLS, the last value will be returned as excluding null or NULL will be returned if all values are null.

Parameters:expression -- a column or an expression which returns a number or a string. LAST_VALUE function or other analytic function cannot be included.
Return type:a type of an expression

The following is schema and data to run the example.

CREATE TABLE test_tbl(groupid int,itemno int);
INSERT INTO test_tbl VALUES(1,null);
INSERT INTO test_tbl VALUES(1,null);
INSERT INTO test_tbl VALUES(1,1);
INSERT INTO test_tbl VALUES(1,null);
INSERT INTO test_tbl VALUES(1,2);
INSERT INTO test_tbl VALUES(1,3);
INSERT INTO test_tbl VALUES(1,4);
INSERT INTO test_tbl VALUES(1,5);
INSERT INTO test_tbl VALUES(2,null);
INSERT INTO test_tbl VALUES(2,null);
INSERT INTO test_tbl VALUES(2,null);
INSERT INTO test_tbl VALUES(2,6);
INSERT INTO test_tbl VALUES(2,7);

The following is a query and a result to run LAST_VALUE function.

SELECT groupid, itemno, LAST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val
FROM test_tbl;
      groupid       itemno      ret_val
=======================================
            1         NULL         NULL
            1         NULL         NULL
            1         NULL         NULL
            1            1            1
            1            2            2
            1            3            3
            1            4            4
            1            5            5
            2         NULL         NULL
            2         NULL         NULL
            2         NULL         NULL
            2            6            6
            2            7            7

LAST_VALUE function is calculated by the current row. That is, values which are not binded are not included on the calculation. For example, on the above result, the value of LAST_VALUE is 1 when "(groupid, itemno) = (1, 1)"; 2 when "(groupid, itemno) = (1, 2)

Note

CUBRID sorts NULL value as first order than other values. The below SQL1 is interpreted as SQL2 which includes NULLS FIRST in ORDER BY clause.

SQL1: LAST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val
SQL2: LAST_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno NULLS FIRST) AS ret_val
LEAD
LEAD(expression, offset[, default]) OVER ([<partition_by_clause>] <order_by_clause>)

LEAD is an analytic function that returns the expression value from a subsequent row, after offset that follows the current row. It can be used to access several rows simultaneously without making any self join.

Parameters:
  • expression -- a column or an expression which returns a number or a string.
  • offset -- the number which indicates the offset location. If it's omitted, the default is 1.
  • default -- the output value when the expression value located before offset is NULL. The default is NULL.
Return type:

NUMBER or STRING

The following example shows how to sort employee numbers and output the next employee number on the same row:

CREATE TABLE t_emp (name VARCHAR(10), empno INT);
INSERT INTO t_emp VALUES
('Amie', 11011), ('Jane', 13077), ('Lora', 12045), ('James', 12006),
('Peter', 14006), ('Tom', 12786), ('Ralph', 23518), ('David', 55);

SELECT name, empno, LEAD (empno, 1) OVER (ORDER BY empno) next_empno
FROM t_emp;
  name                        empno   next_empno
================================================
  'David'                        55        11011
  'Amie'                      11011        12006
  'James'                     12006        12045
  'Lora'                      12045        12786
  'Tom'                       12786        13077
  'Jane'                      13077        14006
  'Peter'                     14006        23518
  'Ralph'                     23518         NULL

The following example shows how to output the title of the previous row and the title of the next row along with the title of the current row on the tbl_board table:

CREATE TABLE tbl_board (num INT, title VARCHAR(50));
INSERT INTO tbl_board VALUES
(1, 'title 1'), (2, 'title 2'), (3, 'title 3'), (4, 'title 4'), (5, 'title 5'), (6, 'title 6'), (7, 'title 7');

SELECT num, title,
    LEAD (title,1,'no next page') OVER (ORDER BY num) next_title,
    LAG (title,1,'no previous page') OVER (ORDER BY num) prev_title
FROM tbl_board;
  num  title                 next_title            prev_title
===============================================================================
    1  'title 1'             'title 2'             NULL
    2  'title 2'             'title 3'             'title 1'
    3  'title 3'             'title 4'             'title 2'
    4  'title 4'             'title 5'             'title 3'
    5  'title 5'             'title 6'             'title 4'
    6  'title 6'             'title 7'             'title 5'
    7  'title 7'             NULL                  'title 6'

The following example shows how to output the title of the previous row and the title of the next row along with the title of a specified row on the tbl_board table. If a WHERE condition is enclosed in parentheses, the values of next_title and prev_title are NULL as only one row is selected but the previous row and the subsequent row.

SELECT * FROM
(
    SELECT num, title,
        LEAD(title,1,'no next page') OVER (ORDER BY num) next_title,
        LAG(title,1,'no previous page') OVER (ORDER BY num) prev_title
    FROM tbl_board
)
WHERE num=5;
  num  title                 next_title            prev_title
===============================================================================
    5  'title 5'             'title 6'             'title 4'
MAX
MAX([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression)
MAX([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>)

The MAX function is used as an aggregate function or an analytic function. It gets the greatest value of expressions of all rows. Only one expression is specified. For expressions that return character strings, the string that appears later in alphabetical order becomes the maximum value; for those that return numbers, the greatest value becomes the maximum value.

Parameters:
  • expression -- Specifies an expression that returns a numeric or string value. An expression that returns a collection-type data is not allowed.
  • ALL -- Gets the maximum value for all data (default).
  • DISTINCT,DISTINCTROW,UNIQUE -- Gets the maximum value without duplicates.
Return type:

same type as that the expression

The following example shows how to retrieve the maximum number of gold (gold) medals that Korea won in the Olympics in the demodb database.

SELECT MAX(gold) FROM participant WHERE nation_code = 'KOR';
    max(gold)
=============
           12

The following example shows how to output the number of gold medals by year and the maximum number of gold medals in history, acquired by the country whose nation_code code starts with 'AU'.

SELECT host_year, nation_code, gold,
    MAX(gold) OVER (PARTITION BY nation_code) mx_gold
FROM participant
WHERE nation_code LIKE 'AU%'
ORDER BY nation_code, host_year;
    host_year  nation_code                  gold      mx_gold
=============================================================
         1988  'AUS'                           3           17
         1992  'AUS'                           7           17
         1996  'AUS'                           9           17
         2000  'AUS'                          16           17
         2004  'AUS'                          17           17
         1988  'AUT'                           1            2
         1992  'AUT'                           0            2
         1996  'AUT'                           0            2
         2000  'AUT'                           2            2
         2004  'AUT'                           2            2
MEDIAN
MEDIAN(expression)
MEDIAN(expression) OVER ([<partition_by_clause>])

MEDIAN function is used as an aggregate function or an analytic function. It returns the median value. The median value is the value which is located on the middle between the minimum value and the maximum value.

Parameters:expression -- column with value or expression which can be converted as number or date
Return type:DOUBLE or DATETIME

The following is a schema and data to run examples.

CREATE TABLE tbl (col1 int, col2 double);
INSERT INTO tbl VALUES(1,2), (1,1.5), (1,1.7), (1,1.8), (2,3), (2,4), (3,5);

The following is an example to be used as an aggregate function. It returns the median values of aggregated col2 by each group of col1.

SELECT col1, MEDIAN(col2)
FROM tbl GROUP BY col1;
         col1  median(col2)
===================================
            1  1.750000000000000e+00
            2  3.500000000000000e+00
            3  5.000000000000000e+00

The following is an example to be used as an analytic function. It returns the median values of col2 by each group of col1.

SELECT col1, MEDIAN(col2) OVER (PARTITION BY col1)
FROM tbl;
     col1  median(col2) over (partition by col1)
===================================
        1  1.750000000000000e+00
        1  1.750000000000000e+00
        1  1.750000000000000e+00
        1  1.750000000000000e+00
        2  3.500000000000000e+00
        2  3.500000000000000e+00
        3  5.000000000000000e+00
MIN
MIN([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression)
MIN([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>)

The MIN function is used as an aggregate function or an analytic function. It gets the smallest value of expressions of all rows. Only one expression is specified. For expressions that return character strings, the string that appears earlier in alphabetical order becomes the minimum value; for those that return numbers, the smallest value becomes the minimum value.

Parameters:
  • expression -- Specifies an expression that returns a numeric or string value. A collection expression cannot be specified.
  • ALL -- Gets the minimum value for all data (default).
  • DISTINCT,DISTINCTROW,UNIQUE -- Gets the maximum value without duplicates.
Return type:

same type as the expression

The following example shows how to retrieve the minimum number of gold (gold) medals that Korea won in the Olympics in the demodb database.

SELECT MIN(gold) FROM participant WHERE nation_code = 'KOR';
    min(gold)
=============
            7

The following example shows how to output the number of gold medals by year and the maximum number of gold medals in history, acquired by the country whose nation_code code starts with 'AU'.

SELECT host_year, nation_code, gold,
MIN(gold) OVER (PARTITION BY nation_code) mn_gold
FROM participant WHERE nation_code like 'AU%' ORDER BY nation_code, host_year;
    host_year  nation_code                  gold      mn_gold
=============================================================
         1988  'AUS'                           3            3
         1992  'AUS'                           7            3
         1996  'AUS'                           9            3
         2000  'AUS'                          16            3
         2004  'AUS'                          17            3
         1988  'AUT'                           1            0
         1992  'AUT'                           0            0
         1996  'AUT'                           0            0
         2000  'AUT'                           2            0
         2004  'AUT'                           2            0
NTH_VALUE
NTH_VALUE(expression, N) [{RESPECT|IGNORE} NULLS] OVER (<analytic_clause>)

NTH_VALUE is used as an analytic function only. It returns an expression value of N-th row in the set of sorted values.

Parameters:
  • expression -- a column or an expression which returns a number or a string
  • N -- a constant, a binding variable, a column or an expression which can be interpreted as a positive integer
Return type:

a type of an expression

{RESPECT|IGNORE} NULLS syntax decides if null value of expression is included in the calculation or not. The default is RESPECT NULLS.

The following is a schema and data to run examples.

CREATE TABLE test_tbl(groupid int,itemno int);
INSERT INTO test_tbl VALUES(1,null);
INSERT INTO test_tbl VALUES(1,null);
INSERT INTO test_tbl VALUES(1,1);
INSERT INTO test_tbl VALUES(1,null);
INSERT INTO test_tbl VALUES(1,2);
INSERT INTO test_tbl VALUES(1,3);
INSERT INTO test_tbl VALUES(1,4);
INSERT INTO test_tbl VALUES(1,5);
INSERT INTO test_tbl VALUES(2,null);
INSERT INTO test_tbl VALUES(2,null);
INSERT INTO test_tbl VALUES(2,null);
INSERT INTO test_tbl VALUES(2,6);
INSERT INTO test_tbl VALUES(2,7);

The following is a query and results to run NTH_VALUE function by the value of N as 2.

SELECT groupid, itemno, NTH_VALUE(itemno, 2) IGNORE NULLS OVER(PARTITION BY groupid ORDER BY itemno NULLS FIRST) AS ret_val
FROM test_tbl;
      groupid       itemno      ret_val
=======================================
            1         NULL         NULL
            1         NULL         NULL
            1         NULL         NULL
            1            1         NULL
            1            2            2
            1            3            2
            1            4            2
            1            5            2
            2         NULL         NULL
            2         NULL         NULL
            2         NULL         NULL
            2            6         NULL
            2            7            7

Note

CUBRID sorts NULL value as first order than other values. The below SQL1 is interpreted as SQL2 which includes NULLS FIRST in ORDER BY clause.

SQL1: NTH_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno) AS ret_val
SQL2: NTH_VALUE(itemno) OVER(PARTITION BY groupid ORDER BY itemno NULLS FIRST) AS ret_val
NTILE
NTILE(expression) OVER ([<partition_by_clause>] <order_by_clause>)

NTILE is an analytic function. It divides an ordered data set into a number of buckets indicated by the input parameter value and assigns the appropriate bucket number from 1 to each row.

Parameters:expression -- the number of buckets. It specifies a certain expression which returns a number value.
Return type:INT

NTILE function equally divides the number of rows by the given number of buckets and assigns the bucket number to each bucket. That is, NTILE function creates an equi-height histogram. The number of rows in the buckets can differ by at most 1. The remainder values (the remainder number of rows divided by buckets number) are distributed one for each bucket, starting with #1 Bucket.

On the contrary, WIDTH_BUCKET() function equally divides the range by the given number of buckets and assigns the bucket number to each bucket. That is, every interval (bucket) has the identical size.

The following example divides rows into five buckets of eight customers based on their dates of birth. Because the total number of rows is not divisible by the number of buckets, the first three buckets have two rows and the remaining groups have one row each.

CREATE TABLE t_customer(name VARCHAR(10), birthdate DATE);
INSERT INTO t_customer VALUES
    ('Amie', date'1978-03-18'),
    ('Jane', date'1983-05-12'),
    ('Lora', date'1987-03-26'),
    ('James', date'1948-12-28'),
    ('Peter', date'1988-10-25'),
    ('Tom', date'1980-07-28'),
    ('Ralph', date'1995-03-17'),
    ('David', date'1986-07-28');

SELECT name, birthdate, NTILE(5) OVER (ORDER BY birthdate) age_group
FROM t_customer;
  name                  birthdate     age_group
===============================================
  'James'               12/28/1948            1
  'Amie'                03/18/1978            1
  'Tom'                 07/28/1980            2
  'Jane'                05/12/1983            2
  'David'               07/28/1986            3
  'Lora'                03/26/1987            3
  'Peter'               10/25/1988            4
  'Ralph'               03/17/1995            5

The following example divides eight students into five buckets that have the identical number of rows in the order of score and outputs in the order of the name. As the score column of the t_score table has eight rows, the remaining three rows are assigned to buckets from #1 Bucket. The first three buckets have one more row than the remaining groups. The NTILE function equally divides the grade based on the number of rows, regardless the range of the score.

CREATE TABLE t_score(name VARCHAR(10), score INT);
INSERT INTO t_score VALUES
    ('Amie', 60),
    ('Jane', 80),
    ('Lora', 60),
    ('James', 75),
    ('Peter', 70),
    ('Tom', 30),
    ('Ralph', 99),
    ('David', 55);

SELECT name, score, NTILE(5) OVER (ORDER BY score DESC) grade
FROM t_score
ORDER BY name;
  name                        score        grade
================================================
  'Ralph'                        99            1
  'Jane'                         80            1
  'James'                        75            2
  'Peter'                        70            2
  'Amie'                         60            3
  'Lora'                         60            3
  'David'                        55            4
  'Tom'                          30            5
PERCENT_RANK
PERCENT_RANK(expression[, expression] ...) WITHIN GROUP (<order_by_clause>)
PERCENT_RANK() OVER ([<partition_by_clause>] <order_by_clause>)

PERCENT_RANK function is used as an aggregate function or an analytic function. It returns the relative position of the row in the group as a ranking percent. It is similar to CUME_DIST function(returns cumulated distribution value). The range of this function is from 0 to 1. The first value of PERCENT_RANK is always 0.

Parameters:expression -- an expression which returns a number or a string. It should not be a column.
Return type:DOUBLE

See also

CUME_DIST(), RANK()

If it is an aggregate function, it returns the value that the RANK minus 1 of a hypothetical row selected in the whole aggregated rows is divided by the number of rows in the aggregated group. That is, ("RANK of a hypothetical row" - 1)/(the number or rows in the aggregated group).

If it is an analytic function, it returns ("RANK per group" -1)/("the number of rows in the group" - 1) when each row with the group divided by PARTITION BY is sorted by the specified order by the ORDER BY clause. For example, if the number of rows appeared as the first rank(RANK=1) in the total 10 rows is 2, PERCENT_RANK values of the first and second rows are (1-1)/(10-1)=0.

The following is a table which compares the return values of CUME_DIST and PERCENT_RANK which are used as aggregate functions when there are input arguments VAL.

VAL RANK() DENSE_RANK() CUME_DIST(VAL) PERCENT_RANK(VAL)
100 1 1 0.33 => (1+1)/(5+1) 0 => (1-1)/5
200 2 2 0.67 => (2+1)/(5+1) 0.2 => (2-1)/5
200 2 2 0.67 => (2+1)/(5+1) 0.2 => (2-1)/5
300 4 3 0.83 => (4+1)/(5+1) 0.6 => (4-1)/5
400 5 4 1 => (5+1)/(5+1) 0.8 => (5-1)/5

The following is a table which compares the return values of CUME_DIST and PERCENT_RANK which are used as analytic functions when there are input arguments VAL.

VAL RANK() DENSE_RANK() CUME_DIST() PERCENT_RANK()
100 1 1 0.2 => 1/5 0 => (1-1)/(5-1)
200 2 2 0.6 => 3/5 0.25 => (2-1)/(5-1)
200 2 2 0.6 => 3/5 0.25 => (2-1)/(5-1)
300 4 3 0.8 => 4/5 0.75 => (4-1)/(5-1)
400 5 4 1 => 5/5 1 => (5-1)/(5-1)

The following is a schema and examples of queries which are related to the above tables.

CREATE TABLE test_tbl(VAL INT);
INSERT INTO test_tbl VALUES (100), (200), (200), (300), (400);


SELECT CUME_DIST(100) WITHIN GROUP (ORDER BY val) AS cume FROM test_tbl;
SELECT PERCENT_RANK(100) WITHIN GROUP (ORDER BY val) AS pct_rnk FROM test_tbl;

SELECT CUME_DIST() OVER (ORDER BY val) AS cume FROM test_tbl;
SELECT PERCENT_RANK() OVER (ORDER BY val) AS pct_rnk FROM test_tbl;

The following is a schema and data which will be used in the below.

CREATE TABLE scores(id INT PRIMARY KEY AUTO_INCREMENT, math INT, english INT, pe CHAR, grade INT);

INSERT INTO scores(math, english, pe, grade)
       VALUES(60, 70, 'A', 1),
       (60, 70, 'A', 1),
       (60, 80, 'A', 1),
       (60, 70, 'B', 1),
       (70, 60, 'A', 1) ,
       (70, 70, 'A', 1) ,
       (80, 70, 'C', 1) ,
       (70, 80, 'C', 1),
       (85, 60, 'C', 1),
       (75, 90, 'B', 1);
INSERT INTO scores(math, english, pe, grade)
       VALUES(95, 90, 'A', 2),
       (85, 95, 'B', 2),
       (95, 90, 'A', 2),
       (85, 95, 'B', 2),
       (75, 80, 'D', 2),
       (75, 85, 'D', 2),
       (75, 70, 'C', 2),
       (65, 95, 'A', 2),
       (65, 95, 'A', 2),
       (65, 95, 'A', 2);

The following is an example of aggregate function. It displays the result that each PERCENT_RANK about three columns, math, english and pe are added and divided by 3.

SELECT PERCENT_RANK(60, 70, 'D')
WITHIN GROUP(ORDER BY math, english, pe) AS percent_rank
FROM scores;
1.500000000000000e-01

The following is an example of analytic function. It returns the PERCENT_RANK values of the entire rows based on three columns, math, english and pe.

SELECT id, math, english, pe, grade, PERCENT_RANK() OVER(ORDER BY math, english, pe) AS percent_rank
FROM scores
ORDER BY percent_rank;
           id         math      english  pe                          grade              percent_rank
====================================================================================================
            1           60           70  'A'                             1     0.000000000000000e+00
            2           60           70  'A'                             1     0.000000000000000e+00
            4           60           70  'B'                             1     1.052631578947368e-01
            3           60           80  'A'                             1     1.578947368421053e-01
           18           65           95  'A'                             2     2.105263157894737e-01
           19           65           95  'A'                             2     2.105263157894737e-01
           20           65           95  'A'                             2     2.105263157894737e-01
            5           70           60  'A'                             1     3.684210526315789e-01
            6           70           70  'A'                             1     4.210526315789473e-01
            8           70           80  'C'                             1     4.736842105263158e-01
           17           75           70  'C'                             2     5.263157894736842e-01
           15           75           80  'D'                             2     5.789473684210527e-01
           16           75           85  'D'                             2     6.315789473684210e-01
           10           75           90  'B'                             1     6.842105263157895e-01
            7           80           70  'C'                             1     7.368421052631579e-01
            9           85           60  'C'                             1     7.894736842105263e-01
           12           85           95  'B'                             2     8.421052631578947e-01
           14           85           95  'B'                             2     8.421052631578947e-01
           11           95           90  'A'                             2     9.473684210526315e-01
           13           95           90  'A'                             2     9.473684210526315e-01

The following is an example of analytic function. It returns the PERCENT_RANK values grouped by grade column, based on three columns, math, english and pe.

SELECT id, math, english, pe, grade, RANK(), PERCENT_RANK() OVER(PARTITION BY grade ORDER BY math, english, pe) AS percent_rank
FROM scores
ORDER BY grade, percent_rank;
           id         math      english  pe                          grade              percent_rank
====================================================================================================
            1           60           70  'A'                             1     0.000000000000000e+00
            2           60           70  'A'                             1     0.000000000000000e+00
            4           60           70  'B'                             1     2.222222222222222e-01
            3           60           80  'A'                             1     3.333333333333333e-01
            5           70           60  'A'                             1     4.444444444444444e-01
            6           70           70  'A'                             1     5.555555555555556e-01
            8           70           80  'C'                             1     6.666666666666666e-01
           10           75           90  'B'                             1     7.777777777777778e-01
            7           80           70  'C'                             1     8.888888888888888e-01
            9           85           60  'C'                             1     1.000000000000000e+00
           18           65           95  'A'                             2     0.000000000000000e+00
           19           65           95  'A'                             2     0.000000000000000e+00
           20           65           95  'A'                             2     0.000000000000000e+00
           17           75           70  'C'                             2     3.333333333333333e-01
           15           75           80  'D'                             2     4.444444444444444e-01
           16           75           85  'D'                             2     5.555555555555556e-01
           12           85           95  'B'                             2     6.666666666666666e-01
           14           85           95  'B'                             2     6.666666666666666e-01
           11           95           90  'A'                             2     8.888888888888888e-01
           13           95           90  'A'                             2     8.888888888888888e-01

In the above result, the rows with id 1 are located at the first and the second in the 10 rows whose grade is 1, and the values of PERCENT_RANK will be (1-1)/(10-1)=0. A row whose id is 5 is located at the fifth in the 10 rows whose grade is 1, and the value of PERCENT_RANK will be (5-1)/(10-1)=0.44.

PERCENTILE_CONT
PERCENTILE_CONT(expression1) WITHIN GROUP (ORDER BY expression2 [ASC | DESC]) [OVER (<partition_by_clause>)]

PERCENTILE_CONT is used as an aggregate or analytic function, and is a reverse distribution function to assume a continuous distribution model. This takes a percentile value and returns a interpolated value within a set of sorted values. NULLs are ignored when calculating.

This function's input value is a number or a string which can be converted into a number, and the type of returned value is DOUBLE.

Parameters:
  • expression1 -- Percentile value. This must be between 0 and 1.
  • expression2 -- The column names followed by an ORDER BY clause. The number of columns should be the same with the number of columns in expression1.
Return type:

DOUBLE

When this is an aggregate function, this sorts results by the order specified by the ORDER BY clause; then this returns an interpolation value belongs to the percentile value from the rows in the aggregate group.

When this is an analytic function, this sorts each row divided by PARTITION BY clause, by the order specified by the ORDER BY clause; then this returns an interpolation value belongs to the percentile value from the rows in the group.

Note

Difference between PERCENTILE_CONT and PERCENTILE_DISC

PERCENTILE_CONT and PERCENTILE_DISC can return different results.

PERCENTILE_CONT operates continuous interpolation; then it returns the calculated result.

PERCENTILE_DISC returns a value from the set of aggregated values.

In the below examples, when a percentile value is 0.5 and the group has even items, PERCENTILE_CONT returns the average of the two values from the medium position; however, PERCENTILE_DISC returns the first value between the two values from the medium position. If the group has odd items, both of them returns the value of a centered item.

In fact, the MEDIAN function is a particular case of PERCENTILE_CONT with the default of percentile value(0.5). Please also see MEDIAN() for more details.

The below shows the schema and the data on the next examples.

CREATE TABLE scores([id] INT PRIMARY KEY AUTO_INCREMENT, [math] INT, english INT, [class] CHAR);

INSERT INTO scores VALUES
       (1, 30, 70, 'A'),
       (2, 40, 70, 'A'),
       (3, 60, 80, 'A'),
       (4, 70, 70, 'A'),
       (5, 72, 60, 'A') ,
       (6, 77, 70, 'A') ,
       (7, 80, 70, 'C') ,
       (8, 70, 80, 'C'),
       (9, 85, 60, 'C'),
       (10, 78, 90, 'B'),
       (11, 95, 90, 'D'),
       (12, 85, 95, 'B'),
       (13, 95, 90, 'B'),
       (14, 85, 95, 'B'),
       (15, 75, 80, 'D'),
       (16, 75, 85, 'D'),
       (17, 75, 70, 'C'),
       (18, 65, 95, 'C'),
       (19, 65, 95, 'D'),
       (20, 65, 95, 'D');

The below is an example of an aggregate function; it returns a median value for the math column.

SELECT PERCENTILE_CONT(0.5)
WITHIN GROUP(ORDER BY math) AS pcont
FROM scores;
  pcont
======================
  7.500000000000000e+01

The below is an example of an analytic function; it returns a median value for the math column within the set grouped by which the values of class column are the same.

SELECT math, [class], PERCENTILE_CONT(0.5)
WITHIN GROUP(ORDER BY math)
OVER (PARTITION BY [class]) AS pcont
FROM scores;
     math  class                 pcont
=====================================================
       30  'A'                   6.500000000000000e+01
       40  'A'                   6.500000000000000e+01
       60  'A'                   6.500000000000000e+01
       70  'A'                   6.500000000000000e+01
       72  'A'                   6.500000000000000e+01
       77  'A'                   6.500000000000000e+01
       78  'B'                   8.500000000000000e+01
       85  'B'                   8.500000000000000e+01
       85  'B'                   8.500000000000000e+01
       95  'B'                   8.500000000000000e+01
       65  'C'                   7.500000000000000e+01
       70  'C'                   7.500000000000000e+01
       75  'C'                   7.500000000000000e+01
       80  'C'                   7.500000000000000e+01
       85  'C'                   7.500000000000000e+01
       65  'D'                   7.500000000000000e+01
       65  'D'                   7.500000000000000e+01
       75  'D'                   7.500000000000000e+01
       75  'D'                   7.500000000000000e+01
       95  'D'                   7.500000000000000e+01

In class 'A', the number of 'math' is totally 6; PERCENTILE_CONT assumes that continuous values exist from the discrete values; therefore, the median value is 65, an average of the 3rd value (60) and the 4th value (70).

PERCENTILE_CONT assumes the continuous value; therefore, it returns DOUBLE type value which can show the continuous representation.

PERCENTILE_DISC
PERCENTILE_DISC(expression1) WITHIN GROUP (ORDER BY expression2 [ASC | DESC]) [OVER (<partition_by_clause>)]

PERCENTILE_DISC is used as an aggregate or analytic function, and is a reverse distribution function to assume a discrete distribution model. This takes a percentile value and returns a discrete value within a set of sorted values. NULLs are ignored when calculating.

This function's input value is a number or a string which can be converted into a number, and the type of returned value is the same as the type of input value.

Parameters:
  • expression1 -- Percentile value. This must be between 0 and 1.
  • expression2 -- The column names followed by an ORDER BY clause. The number of columns should be the same with the number of columns in expression1.
Return type:

the same with the expression2's type.

When this is an aggregate function, this sorts results by the order specified by the ORDER BY clause; then this returns an interpolation value located to the percentile value from the rows in the aggregate group.

When this is an analytic function, this sorts each row divided by PARTITION BY clause, by the order specified by the ORDER BY clause; then this returns an interpolation value located to the percentile value from the rows in the group.

The schema and the data used in this function's example are the same with them in PERCENTILE_CONT().

The below is an example of an aggregate function; it returns a median value for the math column.

SELECT PERCENTILE_DISC(0.5)
WITHIN GROUP(ORDER BY math) AS pdisc
FROM scores;
  pdisc
======================
  75

The below is an example of an analytic function; it returns a median value for the math column within the set grouped by which the values of class column are the same.

SELECT math, [class], PERCENTILE_DISC(0.5)
WITHIN GROUP(ORDER BY math)
OVER (PARTITION BY [class]) AS pdisc
FROM scores;
 math  class                 pdisc
=========================================================
   30  'A'                   60
   40  'A'                   60
   60  'A'                   60
   70  'A'                   60
   72  'A'                   60
   77  'A'                   60
   78  'B'                   85
   85  'B'                   85
   85  'B'                   85
   95  'B'                   85
   65  'C'                   75
   70  'C'                   75
   75  'C'                   75
   80  'C'                   75
   85  'C'                   75
   65  'D'                   75
   65  'D'                   75
   75  'D'                   75
   75  'D'                   75
   95  'D'                   75

In class 'A', the number of 'math' is totally 6; PERCENTILE_DISC outputs the first one if the medium values are the two; therefore, the median value is 60, between the 3rd value (60) and the 4th value (70).

RANK
RANK() OVER ([<partition_by_clause>] <order_by_clause>)

RANK function is used as an analytic function only. The rank of the value in the column value group made by the PARTITION BY clause is calculated and output as INTEGER. When there is another identical rank, the next rank is the number adding the number of the same ranks. For example, when there are three rows of Rank 13, the next rank is 16, not 14. On the contrary, the DENSE_RANK() function calculates the next rank by adding 1 to the rank.

rtype:INT

The following example shows output of the number of Olympic gold medals of each country and the rank of the countries by year. The next rank of the same rank is calculated by adding the number of the same ranks.

SELECT host_year, nation_code, gold,
RANK() OVER (PARTITION BY host_year ORDER BY gold DESC) AS g_rank
FROM participant;
    host_year  nation_code                  gold       g_rank
=============================================================
         1988  'URS'                          55            1
         1988  'GDR'                          37            2
         1988  'USA'                          36            3
         1988  'KOR'                          12            4
         1988  'HUN'                          11            5
         1988  'FRG'                          11            5
         1988  'BUL'                          10            7
         1988  'ROU'                           7            8
         1988  'ITA'                           6            9
         1988  'FRA'                           6            9
         1988  'KEN'                           5           11
         1988  'GBR'                           5           11
         1988  'CHN'                           5           11
...
         1988  'CHI'                           0           32
         1988  'ARG'                           0           32
         1988  'JAM'                           0           32
         1988  'SUI'                           0           32
         1988  'SWE'                           0           32
         1992  'EUN'                          45            1
         1992  'USA'                          37            2
         1992  'GER'                          33            3
...
         2000  'RSA'                           0           52
         2000  'NGR'                           0           52
         2000  'JAM'                           0           52
         2000  'BRA'                           0           52
         2004  'USA'                          36            1
         2004  'CHN'                          32            2
         2004  'RUS'                          27            3
         2004  'AUS'                          17            4
         2004  'JPN'                          16            5
         2004  'GER'                          13            6
         2004  'FRA'                          11            7
         2004  'ITA'                          10            8
         2004  'UKR'                           9            9
         2004  'CUB'                           9            9
         2004  'GBR'                           9            9
         2004  'KOR'                           9            9
...
         2004  'EST'                           0           57
         2004  'SLO'                           0           57
         2004  'SCG'                           0           57
         2004  'FIN'                           0           57
         2004  'POR'                           0           57
         2004  'MEX'                           0           57
         2004  'LAT'                           0           57
         2004  'PRK'                           0           57
ROW_NUMBER
ROW_NUMBER() OVER ([<partition_by_clause>] <order_by_clause>)

ROW_NUMBER function is used as an analytic function only. The rank of a row is one plus the number of distinct ranks that come before the row in question by using the PARTITION BY clause and outputs as INTEGER.

Return type:INT

The following example shows output of the serial number according to the number of Olympic gold medals of each country by year. If the number of gold medals is the same, the sorting follows the alphabetic order of the nation_code.

SELECT host_year, nation_code, gold,
ROW_NUMBER() OVER (PARTITION BY host_year ORDER BY gold DESC) AS r_num
FROM participant;
    host_year  nation_code                  gold       r_num
=============================================================
         1988  'URS'                          55            1
         1988  'GDR'                          37            2
         1988  'USA'                          36            3
         1988  'KOR'                          12            4
         1988  'FRG'                          11            5
         1988  'HUN'                          11            6
         1988  'BUL'                          10            7
         1988  'ROU'                           7            8
         1988  'FRA'                           6            9
         1988  'ITA'                           6           10
         1988  'CHN'                           5           11
...
         1988  'YEM'                           0          152
         1988  'YMD'                           0          153
         1988  'ZAI'                           0          154
         1988  'ZAM'                           0          155
         1988  'ZIM'                           0          156
         1992  'EUN'                          45            1
         1992  'USA'                          37            2
         1992  'GER'                          33            3
...
         2000  'VIN'                           0          194
         2000  'YEM'                           0          195
         2000  'ZAM'                           0          196
         2000  'ZIM'                           0          197
         2004  'USA'                          36            1
         2004  'CHN'                          32            2
         2004  'RUS'                          27            3
         2004  'AUS'                          17            4
         2004  'JPN'                          16            5
         2004  'GER'                          13            6
         2004  'FRA'                          11            7
         2004  'ITA'                          10            8
         2004  'CUB'                           9            9
         2004  'GBR'                           9           10
         2004  'KOR'                           9           11
...
         2004  'UGA'                           0          195
         2004  'URU'                           0          196
         2004  'VAN'                           0          197
         2004  'VEN'                           0          198
         2004  'VIE'                           0          199
         2004  'VIN'                           0          200
         2004  'YEM'                           0          201
         2004  'ZAM'                           0          202
STDDEV, STDDEV_POP
STDDEV([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression)
STDDEV_POP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression)
STDDEV([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>)
STDDEV_POP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>)

The functions STDDEV and STDDEV_POP are used interchangeably and they are used as an aggregate function or an analytic function. They return a standard variance of the values calculated for all rows. The STDDEV_POP function is a standard of the SQL:1999. Only one expression is specified as a parameter. If the DISTINCT or UNIQUE keyword is inserted before the expression, they calculate the sample standard variance after deleting duplicates; if keyword is omitted or ALL, they it calculate the sample standard variance for all values.

Parameters:
  • expression -- Specifies an expression that returns a numeric value.
  • ALL -- Calculates the standard variance for all data (default).
  • DISTINCT,DISTINCTROW,UNIQUE -- Calculates the standard variance without duplicates.
Return type:

DOUBLE

The return value is the same with the square root of its variance (the return value of VAR_POP() and it is a DOUBLE type. If there are no rows that can be used for calculating a result, NULL is returned.

The following is a formula that is applied to the function.

_images/stddev_pop.jpg

Note

In CUBRID 2008 R3.1 or earlier, the STDDEV function worked the same as the STDDEV_SAMP().

The following example shows how to output the population standard variance of all students for all subjects.

CREATE TABLE student (name VARCHAR(32), subjects_id INT, score DOUBLE);
INSERT INTO student VALUES
('Jane',1, 78), ('Jane',2, 50), ('Jane',3, 60),
('Bruce', 1, 63), ('Bruce', 2, 50), ('Bruce', 3, 80),
('Lee', 1, 85), ('Lee', 2, 88), ('Lee', 3, 93),
('Wane', 1, 32), ('Wane', 2, 42), ('Wane', 3, 99),
('Sara', 1, 17), ('Sara', 2, 55), ('Sara', 3, 43);

SELECT STDDEV_POP (score) FROM student;
         stddev_pop(score)
==========================
     2.329711474744362e+01

The following example shows how to output the score and population standard variance of all students by subject (subjects_id).

SELECT subjects_id, name, score,
STDDEV_POP(score) OVER(PARTITION BY subjects_id) std_pop
FROM student
ORDER BY subjects_id, name;
  subjects_id  name                                     score                   std_pop
=======================================================================================
            1  'Bruce'                  6.300000000000000e+01     2.632869157402243e+01
            1  'Jane'                   7.800000000000000e+01     2.632869157402243e+01
            1  'Lee'                    8.500000000000000e+01     2.632869157402243e+01
            1  'Sara'                   1.700000000000000e+01     2.632869157402243e+01
            1  'Wane'                   3.200000000000000e+01     2.632869157402243e+01
            2  'Bruce'                  5.000000000000000e+01     1.604992211819110e+01
            2  'Jane'                   5.000000000000000e+01     1.604992211819110e+01
            2  'Lee'                    8.800000000000000e+01     1.604992211819110e+01
            2  'Sara'                   5.500000000000000e+01     1.604992211819110e+01
            2  'Wane'                   4.200000000000000e+01     1.604992211819110e+01
            3  'Bruce'                  8.000000000000000e+01     2.085185843036539e+01
            3  'Jane'                   6.000000000000000e+01     2.085185843036539e+01
            3  'Lee'                    9.300000000000000e+01     2.085185843036539e+01
            3  'Sara'                   4.300000000000000e+01     2.085185843036539e+01
            3  'Wane'                   9.900000000000000e+01     2.085185843036539e+01
STDDEV_SAMP
STDDEV_SAMP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression)
STDDEV_SAMP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>)

The STDDEV_SAMP function is used as an aggregate function or an analytic function. It calculates the sample standard variance. Only one expression is specified as a parameter. If the DISTINCT or UNIQUE keyword is inserted before the expression, it calculates the sample standard variance after deleting duplicates; if a keyword is omitted or ALL, it calculates the sample standard variance for all values.

Parameters:
  • expression -- An expression that returns a numeric value
  • ALL -- Used to calculate the standard variance for all values. It is the default value.
  • DISTINCT,DISTINCTROW,UNIQUE -- Used to calculate the standard variance for the unique values without duplicates.
Return type:

DOUBLE

The return value is the same as the square root of its sample variance (VAR_SAMP()) and it is a DOUBLE type. If there are no rows that can be used for calculating a result, NULL is returned.

The following are the formulas applied to the function.

_images/stddev_samp.jpg

The following example shows how to output the sample standard variance of all students for all subjects.

CREATE TABLE student (name VARCHAR(32), subjects_id INT, score DOUBLE);
INSERT INTO student VALUES
('Jane',1, 78), ('Jane',2, 50), ('Jane',3, 60),
('Bruce', 1, 63), ('Bruce', 2, 50), ('Bruce', 3, 80),
('Lee', 1, 85), ('Lee', 2, 88), ('Lee', 3, 93),
('Wane', 1, 32), ('Wane', 2, 42), ('Wane', 3, 99),
('Sara', 1, 17), ('Sara', 2, 55), ('Sara', 3, 43);

SELECT STDDEV_SAMP (score) FROM student;
        stddev_samp(score)
==========================
     2.411480477888654e+01

The following example shows how to output the sample standard variance of all students for all subjects.

SELECT subjects_id, name, score,
STDDEV_SAMP(score) OVER(PARTITION BY subjects_id) std_samp
FROM student
ORDER BY subjects_id, name;
  subjects_id  name                                     score                  std_samp
=======================================================================================
            1  'Bruce'                  6.300000000000000e+01     2.943637205907005e+01
            1  'Jane'                   7.800000000000000e+01     2.943637205907005e+01
            1  'Lee'                    8.500000000000000e+01     2.943637205907005e+01
            1  'Sara'                   1.700000000000000e+01     2.943637205907005e+01
            1  'Wane'                   3.200000000000000e+01     2.943637205907005e+01
            2  'Bruce'                  5.000000000000000e+01     1.794435844492636e+01
            2  'Jane'                   5.000000000000000e+01     1.794435844492636e+01
            2  'Lee'                    8.800000000000000e+01     1.794435844492636e+01
            2  'Sara'                   5.500000000000000e+01     1.794435844492636e+01
            2  'Wane'                   4.200000000000000e+01     1.794435844492636e+01
            3  'Bruce'                  8.000000000000000e+01     2.331308645374953e+01
            3  'Jane'                   6.000000000000000e+01     2.331308645374953e+01
            3  'Lee'                    9.300000000000000e+01     2.331308645374953e+01
            3  'Sara'                   4.300000000000000e+01     2.331308645374953e+01
            3  'Wane'                   9.900000000000000e+01     2.331308645374953e+01
SUM
SUM( [ DISTINCT | DISTINCTROW | UNIQUE | ALL ] expression )
SUM( [ DISTINCT | DISTINCTROW | UNIQUE | ALL ] expression ) OVER (<analytic_clause>)

The SUM function is used as an aggregate function or an analytic function. It returns the sum of expressions of all rows. Only one expression is specified as a parameter. You can get the sum without duplicates by inserting the DISTINCT or UNIQUE keyword in front of the expression, or get the sum of all values by omitting the keyword or by using ALL.

Parameters:
  • expression -- Specifies an expression that returns a numeric value.
  • ALL -- Gets the sum for all data (default).
  • DISTINCT,DISTINCTROW,UNIQUE -- Gets the sum of unique values without duplicates
Return type:

same type as that the expression

The following is an example that outputs the top 10 countries and the total number of gold medals based on the sum of gold medals won in the Olympic Games in demodb.

SELECT nation_code, SUM(gold)
FROM participant
GROUP BY nation_code
ORDER BY SUM(gold) DESC
LIMIT 10;
  nation_code             sum(gold)
===================================
  'USA'                         190
  'CHN'                          97
  'RUS'                          85
  'GER'                          79
  'URS'                          55
  'FRA'                          53
  'AUS'                          52
  'ITA'                          48
  'KOR'                          48
  'EUN'                          45

The following example shows how to output the number of gold medals by year and the average sum of the accumulated gold medals to the year acquired by the country whose nation_code code starts with 'AU' in demodb.

SELECT host_year, nation_code, gold,
    SUM(gold) OVER (PARTITION BY nation_code ORDER BY host_year) sum_gold
FROM participant
WHERE nation_code LIKE 'AU%';
    host_year  nation_code                  gold     sum_gold
=============================================================
         1988  'AUS'                           3            3
         1992  'AUS'                           7           10
         1996  'AUS'                           9           19
         2000  'AUS'                          16           35
         2004  'AUS'                          17           52
         1988  'AUT'                           1            1
         1992  'AUT'                           0            1
         1996  'AUT'                           0            1
         2000  'AUT'                           2            3
         2004  'AUT'                           2            5

The following example is removing the "ORDER BY host_year" clause under the OVER analysis clause from the above example. The avg_gold value is the average of gold medals for all years, so the value is identical for every year by nation_code.

SELECT host_year, nation_code, gold, SUM(gold) OVER (PARTITION BY nation_code) sum_gold
FROM participant
WHERE nation_code LIKE 'AU%';
    host_year  nation_code                  gold     sum_gold
=============================================================
         2004  'AUS'                          17           52
         2000  'AUS'                          16           52
         1996  'AUS'                           9           52
         1992  'AUS'                           7           52
         1988  'AUS'                           3           52
         2004  'AUT'                           2            5
         2000  'AUT'                           2            5
         1996  'AUT'                           0            5
         1992  'AUT'                           0            5
         1988  'AUT'                           1            5
VARIANCE, VAR_POP
VARIANCE([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression)
VAR_POP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression)
VARIANCE([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>)
VAR_POP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>)

The functions VARPOP and VARIANCE are used interchangeably and they are used as an aggregate function or an analytic function. They return a variance of expression values for all rows. Only one expression is specified as a parameter. If the DISTINCT or UNIQUE keyword is inserted before the expression, they calculate the population variance after deleting duplicates; if the keyword is omitted or ALL, they calculate the sample population variance for all values.

Parameters:
  • expression -- Specifies an expression that returns a numeric value.
  • ALL -- Gets the variance for all values (default).
  • DISTINCT,DISTINCTROW,UNIQUE -- Gets the variance of unique values without duplicates.
Return type:

DOUBLE

The return value is a DOUBLE type. If there are no rows that can be used for calculating a result, NULL will be returned.

The following is a formula that is applied to the function.

_images/var_pop.jpg

Note

In CUBRID 2008 R3.1 or earlier, the VARIANCE function worked the same as the VAR_SAMP().

The following example shows how to output the population variance of all students for all subjects

CREATE TABLE student (name VARCHAR(32), subjects_id INT, score DOUBLE);
INSERT INTO student VALUES
('Jane',1, 78), ('Jane',2, 50), ('Jane',3, 60),
('Bruce', 1, 63), ('Bruce', 2, 50), ('Bruce', 3, 80),
('Lee', 1, 85), ('Lee', 2, 88), ('Lee', 3, 93),
('Wane', 1, 32), ('Wane', 2, 42), ('Wane', 3, 99),
('Sara', 1, 17), ('Sara', 2, 55), ('Sara', 3, 43);

SELECT VAR_POP(score) FROM student;
            var_pop(score)
==========================
     5.427555555555550e+02

The following example shows how to output the score and population variance of all students by subject (subjects_id).

SELECT subjects_id, name, score, VAR_POP(score) OVER(PARTITION BY subjects_id) v_pop
FROM student
ORDER BY subjects_id, name;
  subjects_id  name                                     score                     v_pop
=======================================================================================
            1  'Bruce'                  6.300000000000000e+01     6.931999999999998e+02
            1  'Jane'                   7.800000000000000e+01     6.931999999999998e+02
            1  'Lee'                    8.500000000000000e+01     6.931999999999998e+02
            1  'Sara'                   1.700000000000000e+01     6.931999999999998e+02
            1  'Wane'                   3.200000000000000e+01     6.931999999999998e+02
            2  'Bruce'                  5.000000000000000e+01     2.575999999999999e+02
            2  'Jane'                   5.000000000000000e+01     2.575999999999999e+02
            2  'Lee'                    8.800000000000000e+01     2.575999999999999e+02
            2  'Sara'                   5.500000000000000e+01     2.575999999999999e+02
            2  'Wane'                   4.200000000000000e+01     2.575999999999999e+02
            3  'Bruce'                  8.000000000000000e+01     4.348000000000002e+02
            3  'Jane'                   6.000000000000000e+01     4.348000000000002e+02
            3  'Lee'                    9.300000000000000e+01     4.348000000000002e+02
            3  'Sara'                   4.300000000000000e+01     4.348000000000002e+02
            3  'Wane'                   9.900000000000000e+01     4.348000000000002e+02
VAR_SAMP
VAR_SAMP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression)
VAR_SAMP([DISTINCT | DISTINCTROW | UNIQUE | ALL] expression) OVER (<analytic_clause>)

The VAR_SAMP function is used as an aggregate function or an analytic function. It returns the sample variance. The denominator is the number of all rows - 1. Only one expression is specified as a parameter. If the DISTINCT or UNIQUE keyword is inserted before the expression, it calculates the sample variance after deleting duplicates and if the keyword is omitted or ALL, it calculates the sample variance for all values.

Parameters:
  • expression -- Specifies one expression to return the numeric.
  • ALL -- Is used to calculate the sample variance of unique values without duplicates. It is the default value.
  • DISTINCT,DISTINCTROW,UNIQUE -- Is used to calculate the sample variance for the unique values without duplicates.
Return type:

DOUBLE

The return value is a DOUBLE type. If there are no rows that can be used for calculating a result, NULL is returned.

The following are the formulas applied to the function.

_images/var_samp.jpg

The following example shows how to output the sample variance of all students for all subjects.

CREATE TABLE student (name VARCHAR(32), subjects_id INT, score DOUBLE);
INSERT INTO student VALUES
('Jane',1, 78), ('Jane',2, 50), ('Jane',3, 60),
('Bruce', 1, 63), ('Bruce', 2, 50), ('Bruce', 3, 80),
('Lee', 1, 85), ('Lee', 2, 88), ('Lee', 3, 93),
('Wane', 1, 32), ('Wane', 2, 42), ('Wane', 3, 99),
('Sara', 1, 17), ('Sara', 2, 55), ('Sara', 3, 43);

SELECT VAR_SAMP(score) FROM student;
           var_samp(score)
==========================
     5.815238095238092e+02

The following example shows how to output the score and sample variance of all students by subject (subjects_id).

SELECT subjects_id, name, score, VAR_SAMP(score) OVER(PARTITION BY subjects_id) v_samp
FROM student
ORDER BY subjects_id, name;
  subjects_id  name                                     score                    v_samp
=======================================================================================
            1  'Bruce'                  6.300000000000000e+01     8.665000000000000e+02
            1  'Jane'                   7.800000000000000e+01     8.665000000000000e+02
            1  'Lee'                    8.500000000000000e+01     8.665000000000000e+02
            1  'Sara'                   1.700000000000000e+01     8.665000000000000e+02
            1  'Wane'                   3.200000000000000e+01     8.665000000000000e+02
            2  'Bruce'                  5.000000000000000e+01     3.220000000000000e+02
            2  'Jane'                   5.000000000000000e+01     3.220000000000000e+02
            2  'Lee'                    8.800000000000000e+01     3.220000000000000e+02
            2  'Sara'                   5.500000000000000e+01     3.220000000000000e+02
            2  'Wane'                   4.200000000000000e+01     3.220000000000000e+02
            3  'Bruce'                  8.000000000000000e+01     5.435000000000000e+02
            3  'Jane'                   6.000000000000000e+01     5.435000000000000e+02
            3  'Lee'                    9.300000000000000e+01     5.435000000000000e+02
            3  'Sara'                   4.300000000000000e+01     5.435000000000000e+02
            3  'Wane'                   9.900000000000000e+01     5.435000000000000e+02
Click Counter Functions
INCR, DECR
INCR(column_name)
DECR(column_name)

The INCR function increases the column's value given as a parameter of the SELECT statement by 1. The DECR function decreases the value of the column by 1.

Parameters:column -- the name of column defined with SMALLINT, INT or BIGINT type
Return type:SMALLINT, INT or BIGINT

The INCR and DECR functions are called "click counters" and can be effectively used to increase the number of post views for a Bulletin Board System (BBS) type of web service. In a scenario where you want to SELECT a post and immediately increase the number of views by 1 using an UPDATE statement, you can view the post and increment the number at once by using the INCR function in a single SELECT statement.

The INCR function increments the column value specified as an argument. Only integer type numbers can be used as arguments. If the value is NULL, the INCR function returns the NULL. That is, a value must be valid in order to be incremented by the INCR function. The DECR function decrements the column value specified as a parameter.

If an INCR function is specified in the SELECT statement, the COUNTER value is incremented by 1 and the query result is displayed with the values before the increment. Furthermore, the INCR function does not increment the value of the row(tuple) affected by the query process but rather the one affected by the final result.

If you want to increase or decrease the click counter without specifying INCR or DECR on the SELECT list, specify WITH INCREMENT FOR column or WITH INCREMENT FOR column after the WHERE clause.

CREATE TABLE board (id INT, cnt INT, content VARCHAR(8096));
SELECT content FROM board WHERE id=1 WITH INCREMENT FOR cnt;

Note

  • The INCR/DECR functions execute independent of user-defined transactions and is applied automatically to the database by the top operation internally used in the system, apart from the transaction's COMMIT/ROLLBACK.

  • When multiple INCR/DECR functions are specified in a single SELECT statement, the failure of any of the INCR/DECR functions leads to the failure of all of them.

  • The INCR/DECR functions apply only to top-level SELECT statements. SUB SELECT statements such as INSERT ... SELECT ... statement and UPDATE table SET col = SELECT ... statement are not supported. The following example shows where the INCR function is not allowed.

    SELECT b.content, INCR(b.read_count) FROM (SELECT * FROM board WHERE id = 1) AS b
    
  • If the SELECT statement with INCR/DECR functions returns more than one row as a result, it is treated as an error. The final result where only one row exists is valid.

  • The INCR/DECR function can be used only in numerical type. Applicable domains are limited to integer data types such as SMALLINT, INTEGER and BIGINT. They cannot be used in other types.

  • When the INCR function is called, the value to be returned will be the current value, while the value to be stored will be the current value + 1. Execute the following statement to select the value to be stored as a result :

    SELECT content, INCR(read_count) + 1 FROM board WHERE id = 1;
    
  • If the defined maximum value of the type is exceeded, the INCR function initializes the column value to 0. Likewise, the column value is also initialized to 0 when the DECR function applies to the minimum value.

  • Data inconsistency can occur because the INCR/DECR functions are executed regardless of UPDATE trigger. The following example shows the database inconsistency in that situation.

    CREATE TRIGGER event_tr BEFORE UPDATE ON event EXECUTE REJECT;
    SELECT INCR(players) FROM event WHERE gender='M';
    
  • The INCR / DECR functions returns an error in the write-protected broker mode such as slave mode of HA configuration, CSQL Interpreter (csql -r) of read-only, Read Only or Standby Only mode(ACCESS_MODE=RO or SO in cubrid_broker.conf).

Example

Suppose that the following three rows of data are inserted into the 'board' table.

CREATE TABLE board (
  id  INT,
  title  VARCHAR(100),
  content  VARCHAR(4000),
  read_count  INT
);
INSERT INTO board VALUES (1, 'aaa', 'text...', 0);
INSERT INTO board VALUES (2, 'bbb', 'text...', 0);
INSERT INTO board VALUES (3, 'ccc', 'text...', 0);

The following example shows how to increment the value of the 'read_count' column in data whose 'id' value is 1 by using the INCR function.

SELECT content, INCR(read_count) FROM board WHERE id = 1;
  content                read_count
===================================
  'text...'                       0

In the example, the column value becomes read_count + 1 as a result of the INCR function in the SELECT statement. You can check the result using the following SELECT statement.

SELECT content, read_count FROM board WHERE id = 1;
  content                read_count
===================================
  'text...'                       1
ROWNUM Functions
ROWNUM, INST_NUM
ROWNUM
INST_NUM()

The ROWNUM function returns the number representing the order of the records that will be generated by the query result. The first result record is assigned 1, and the second result record is assigned 2.

Return type:INT

ROWNUM and INST_NUM() can be used in the SELECT statement; ORDERBY_NUM() can be used in the SELECT statement with ORDER BY clauses, and GROUPBY_NUM() can be used in the SELECT statement with GROUP BY clauses. The ROWNUM function can be used to limit the number of result records of the query in several ways. For example, it can be used to search only the first 10 records or to return even or odd number records.

The ROWNUM function has a result value as an integer, and can be used wherever an expression is valid such as the SELECT or WHERE clause. However, it is not allowed to compare the result of the ROWNUM function with the attribute or the correlated subquery.

Note

  • The ROWNUM function specified in the WHERE clause works the same as the INST_NUM() function.
  • The ROWNUM function belongs to each SELECT statement. That is, if a ROWNUM function is used in a subquery, it returns the sequence of the subquery result while it is being executed. Internally, the result of the ROWNUM function is generated right before the searched record is written to the query result set. At this moment, the counter value that generates the serial number of the result set records increases.
  • If you want to add a sequence on the SELECT result; use ROWNUM when there is no sorting process; use ORDERBY_NUM() when there is an ORDER BY clause; use GROUPBY_NUM() function when there is a GROUP BY clause.
  • If an ORDER BY clause is included in the SELECT statement, the value of the ORDERBY_NUM() function specified in the WHERE clause is generated after sorting for the ORDER BY clause.
  • If a GROUP BY clause is included in the SELECT statement, the value of the GROUPBY_NUM() function specified in the HAVING clause is calculated after the query results are grouped.
  • For the purpose of limiting the sorted result rows, instead of FOR ORDERBY_NUM() or HAVING GROUPBY_NUM(), LIMIT clause can be used.
  • The ROWNUM function can also be used in SQL statements such as INSERT, DELETE and UPDATE in addition to the SELECT statement. For example, as in the query INSERT INTO table_name SELECT ... FROM ... WHERE ..., you can search for part of the row from one table and then insert it into another by using the ROWNUM function in the WHERE clause.

The following example shows how to retrieve country names ranked first to fourth based on the number of gold (gold) medals in the 1988 Olympics in the demodb database.

--Limiting 4 rows using ROWNUM in the WHERE condition
SELECT  * FROM
(SELECT nation_code FROM participant WHERE host_year = 1988
     ORDER BY gold DESC) AS T
WHERE ROWNUM <5;
  nation_code
======================
  'URS'
  'GDR'
  'USA'
  'KOR'

LIMIT clause limits the sorted result rows; therefore, the below result is the same as the above.

--Limiting 4 rows using LIMIT
SELECT ROWNUM, nation_code FROM participant WHERE host_year = 1988
ORDER BY gold DESC
LIMIT 4;
       rownum  nation_code
===================================
          156  'URS'
          155  'GDR'
          154  'USA'
          153  'KOR'

ROWNUM condition in the below limits before sorting; therefore, the result is different from the above.

--Unexpected results : ROWNUM operated before ORDER BY
SELECT ROWNUM, nation_code FROM participant
WHERE host_year = 1988 AND ROWNUM < 5
ORDER BY gold DESC;
       rownum  nation_code
===================================
            1  'ZIM'
            2  'ZAM'
            3  'ZAI'
            4  'YMD'
ORDERBY_NUM
ORDERBY_NUM()

The ORDERBY_NUM() function is used with the ROWNUM() or INST_NUM() function to limit the number of result rows. The difference is that the ORDERBY_NUM() function is combined after the ORDER BY clause to give order to a result that has been already sorted. That is, when retrieving only some of the result rows by using ROWNUM in a condition clause of the SELECT statement that includes the ORDER BY clause, ROWNUM is applied first and then group sorting by ORDER BY is performed. On the other hand, when retrieving only some of the result rows by using the ORDER_NUM() function, ROWNUM is applied to the result of sorting by ORDER BY.

Return type:INT

The following example shows how to retrieve athlete names ranked 3rd to 5th and their records in the history table in the demodb database.

--Ordering first and then limiting rows using FOR ORDERBY_NUM()
SELECT ORDERBY_NUM(), athlete, score FROM history
ORDER BY score FOR ORDERBY_NUM() BETWEEN 3 AND 5;
    orderby_num()  athlete               score
==============================================================
                3  'Luo Xuejuan'         '01:07.0'
                4  'Rodal Vebjorn'       '01:43.0'
                5  'Thorpe Ian'          '01:45.0'

The following query using a LIMIT clause outputs the same result with the above query.

SELECT ORDERBY_NUM(), athlete, score FROM history
ORDER BY score LIMIT 2, 3;

The following query using ROWNUM limits the result rows before sorting; then ORDER BY sorting is operated.

--Limiting rows first and then Ordering using ROWNUM
SELECT athlete, score FROM history
WHERE ROWNUM BETWEEN 3 AND 5 ORDER BY score;
  athlete               score
============================================
  'Thorpe Ian'          '01:45.0'
  'Thorpe Ian'          '03:41.0'
  'Hackett Grant'       '14:43.0'
GROUPBY_NUM
GROUPBY_NUM()

The GROUPBY_NUM() function is used with the ROWNUM or INST_NUM() function to limit the number of result rows. The difference is that the GROUPBY_NUM() function is combined after the GROUP BY ... HAVING clause to give order to a result that has been already sorted. In addition, while the INST_NUM() function is a scalar function, the GROUPBY_NUM() function is kind of an aggregate function.

That is, when retrieving only some of the result rows by using ROWNUM in a condition clause of the SELECT statement that includes the GROUP BY clause, ROWNUM is applied first and then group sorting by GROUP BY is performed. On the other hand, when retrieving only some of the result rows by using the GROUPBY_NUM() function, ROWNUM is applied to the result of group sorting by GROUP BY.

Return type:INT

The following example shows how to retrieve the fastest record in the previous five Olympic Games from the history table in the demodb database.

--Group-ordering first and then limiting rows using GROUPBY_NUM()
SELECT  GROUPBY_NUM(), host_year, MIN(score) FROM history
GROUP BY host_year HAVING GROUPBY_NUM() BETWEEN 1 AND 5;
    groupby_num()    host_year  min(score)
=====================================================
                1         1968  '8.9'
                2         1980  '01:53.0'
                3         1984  '13:06.0'
                4         1988  '01:58.0'
                5         1992  '02:07.0'

The following query using a LIMIT clause outputs the same result with the above query.

SELECT  GROUPBY_NUM(), host_year, MIN(score) FROM history
GROUP BY host_year LIMIT 5;

The following query using ROWNUM limits the result rows before grouping; then GROUP BY operation is performed.

--Limiting rows first and then Group-ordering using ROWNUM
SELECT host_year, MIN(score) FROM history
WHERE ROWNUM BETWEEN 1 AND 5 GROUP BY host_year;
    host_year  min(score)
===================================
         2000  '03:41.0'
         2004  '01:45.0'
Information Functions
CHARSET
CHARSET(expr)

This function returns the character set of expr.

Parameters:expr -- Target expression to get the character set.
Return type:STRING
SELECT CHARSET('abc');
'iso88591'
SELECT CHARSET(_utf8'abc');
'utf8'
SET NAMES utf8;
SELECT CHARSET('abc');
'utf8'
COERCIBILITY
COERCIBILITY(expr)

This function returns the collation coercibility level of expr. The collation coercibility level determines which collation or charset should be used when each column(expression) has different collation or charset. For more details, please see Collation Coercibility.

Parameters:expr -- Target expression to get the collation coercibility level.
Return type:INT
SELECT COERCIBILITY(USER());
7
SELECT COERCIBILITY(_utf8'abc');
10
COLLATION
COLLATION(expr)

This function returns the collation of expr.

Parameters:expr -- Target expression to get the collation.
Return type:STRING
SELECT COLLATION('abc');
'iso88591_bin'
SELECT COLLATION(_utf8'abc');
'utf8_bin'
CURRENT_USER, USER
CURRENT_USER
USER

CURRENT_USER and USER are pseudo-columns and can be used interchangeably. They return the user name that is currently logged in to the database as a string.

Please note that SYSTEM_USER() and USER() functions return the user name with a host name.

Return type:STRING
--selecting the current user on the session
SELECT USER;
   CURRENT_USER
======================
  'PUBLIC'
SELECT USER(), CURRENT_USER;
   user()                CURRENT_USER
============================================
  'PUBLIC@cdbs006.cub'  'PUBLIC'
--selecting all users of the current database from the system table
SELECT name, id, password FROM db_user;
  name                           id  password
=========================================================
  'DBA'                        NULL  NULL
  'PUBLIC'                     NULL  NULL
  'SELECT_ONLY_USER'           NULL  db_password
  'ALMOST_DBA_USER'            NULL  db_password
  'SELECT_ONLY_USER2'          NULL  NULL
DATABASE, SCHEMA
DATABASE()
SCHEMA()

The functions DATABASE and SCHEMA are used interchangeably. They return the name of currently-connected database as a VARCHAR type.

Return type:STRING
SELECT DATABASE(), SCHEMA();
   database()            schema()
============================================
  'demodb'              'demodb'
DBTIMEZONE
DBTIMEZONE()

Prints out a timezone of database server (offset or region name) as a string. (e.g. '-05:00', or 'Europe/Vienna').

SELECT DBTIMEZONE();
  dbtimezone
======================
  'Asia/Seoul'
DEFAULT
DEFAULT(column_name)
DEFAULT

The DEFAULT and the DEFAULT function returns a default value defined for a column. If a default value is not specified for the column, NULL or an error is output. DEFAULT has no parameter, however, the DEFAULT function uses the column name as the input parameter. DEFAULT can be used for the input data of the INSERT statement and the SET clause of the UPDATE statement and the DEFAULT function can be used anywhere.

If any of constraints is not defined or the UNIQUE constraint is defined for the column where a default value is not defined, NULL is returned. If NOT NULL or PRIMARY KEY constraint is defined, an error is returned.

CREATE TABLE info_tbl(id INT DEFAULT 0, name VARCHAR);
INSERT INTO info_tbl VALUES (1,'a'),(2,'b'),(NULL,'c');

SELECT id, DEFAULT(id) FROM info_tbl;
           id   default(id)
=============================
            1             0
            2             0
         NULL             0
UPDATE info_tbl SET id = DEFAULT WHERE id IS NULL;
DELETE FROM info_tbl WHERE id = DEFAULT(id);
INSERT INTO info_tbl VALUES (DEFAULT,'d');

Note

In version lower than CUBRID 9.0, the value at the time of CREATE TABLE has been saved when the value of the DATE, DATETIME, TIME, TIMESTAMP column has been specified as SYS_DATE, SYS_DATETIME, SYS_TIME, SYS_TIMESTAMP while creating a table. Therefore, to enter the value at the time of data INSERT in version lower than CUBRID 9.0, the function should be entered to the VALUES clause of the INSERT syntax.

INDEX_CARDINALITY
INDEX_CARDINALITY(table, index, key_pos)

The INDEX_CARDINALITY function returns the index cardinality in a table. The index cardinality is the number of unique values defining the index. The index cardinality can be applied even to the partial key of the multiple column index and displays the number of the unique value for the partial key by specifying the column location with the third parameter. Note that this value is an approximate value.

If you want the updated result from this function, you should run UPDATE STATISTICS statement.

Parameters:
  • table -- Table name
  • index -- Index name that exists in the table
  • key_pos --

    Partial key location. It key_pos starts from 0 and has a range that is smaller than the number of columns consisting of keys; that is, the key_pos of the first column is 0. For the single column index, it is 0. It can be one of the following types.

    • Character string that can be converted to a numeric type.
    • Numeric type that can be converted to an integer type. The FLOAT or the DOUBLE types will be the value converted by the ROUND function.
Return type:

INT

The return value is 0 or a positive integer and if any of the input parameters is NULL, NULL is returned. If tables or indexes that are input parameters are not found, or key_pos is out of range, NULL is returned.

CREATE TABLE t1( i1 INTEGER ,
i2 INTEGER not null,
i3 INTEGER unique,
s1 VARCHAR(10),
s2 VARCHAR(10),
s3 VARCHAR(10) UNIQUE);

CREATE INDEX i_t1_i1 ON t1(i1 DESC);
CREATE INDEX i_t1_s1 ON t1(s1(7));
CREATE INDEX i_t1_i1_s1 on t1(i1,s1);
CREATE UNIQUE INDEX i_t1_i2_s2 ON t1(i2,s2);

INSERT INTO t1 VALUES (1,1,1,'abc','abc','abc');
INSERT INTO t1 VALUES (2,2,2,'zabc','zabc','zabc');
INSERT INTO t1 VALUES (2,3,3,'+abc','+abc','+abc');

UPDATE STATISTICS ON t1;
SELECT INDEX_CARDINALITY('t1','i_t1_i1_s1',0);
   index_cardinality('t1', 'i_t1_i1_s1', 0)
===========================================
                                          2
SELECT INDEX_CARDINALITY('t1','i_t1_i1_s1',1);
   index_cardinality('t1', 'i_t1_i1_s1', 1)
===========================================
                                          3
SELECT INDEX_CARDINALITY('t1','i_t1_i1_s1',2);
   index_cardinality('t1', 'i_t1_i1_s1', 2)
===========================================
                                       NULL
SELECT INDEX_CARDINALITY('t123','i_t1_i1_s1',1);
  index_cardinality('t123', 'i_t1_i1_s1', 1)
============================================
                                       NULL
INET_ATON
INET_ATON(ip_string)

The INET_ATON function receives the string of an IPv4 address and returns a number. When an IP address string such as 'a.b.c.d' is entered, the function returns "a * 256 ^ 3 + b * 256 ^ 2 + c * 256 + d". The return type is BIGINT.

Parameters:ip_string -- IPv4 address string
Return type:BIGINT

In the following example, 192.168.0.10 is calculated as "192 * 256 ^ 3 + 168 * 256 ^ 2 + 0 * 256 + 10".

SELECT INET_ATON('192.168.0.10');
   inet_aton('192.168.0.10')
============================
                  3232235530
INET_NTOA
INET_NTOA(expr)

The INET_NTOA function receives a number and returns an IPv4 address string. The return type is VARCHAR.

Parameters:expr -- Numeric expression
Return type:STRING
SELECT INET_NTOA(3232235530);
   inet_ntoa(3232235530)
======================
  '192.168.0.10'
LAST_INSERT_ID
LAST_INSERT_ID()

The LAST_INSERT_ID function returns the value that has been most recently inserted to the AUTO_INCREMENT column by a single INSERT statement.

Return type:BIGINT

The value returned by the LAST_INSERT_ID function has the following characteristics.

  • The latest LAST_INSERT_ID value which was INSERTed successfully will be maintained. If it fails to INSERT, there is no change for LAST_INSERT_ID() value, but AUTO_INCREMENT value is internally increased. Therefore, LAST_INSERT_ID() value after the next INSERT statement's success reflects the internally increased AUTO_INCREMENT value.

    CREATE TABLE tbl(a INT PRIMARY KEY AUTO_INCREMENT, b INT UNIQUE);
    INSERT INTO tbl VALUES (null, 1);
    INSERT INTO tbl VALUES (null, 1);
    
    ERROR: Operation would have caused one or more unique constraint violations.
    
    INSERT INTO tbl VALUES (null, 1);
    
    ERROR: Operation would have caused one or more unique constraint violations.
    
    SELECT LAST_INSERT_ID();
    
    1
    
    -- In 2008 R4.x or before, above value is 3.
    
    INSERT INTO tbl VALUES (null, 2);
    SELECT LAST_INSERT_ID();
    
    4
    
  • In the Multiple-rows INSERT statement(INSERT INTO tbl VALUES (), (), ..., ()), LAST_INSERT_ID() returns the firstly inserted AUTO_INCREMENT value. In other words, from the second row, there is no change on LAST_INSERT_ID() value even if the next rows are inserted.

    INSERT INTO tbl VALUES (null, 11), (null, 12), (null, 13);
    SELECT LAST_INSERT_ID();
    
    5
    
    INSERT INTO tbl VALUES (null, 21);
    SELECT LAST_INSERT_ID();
    
    8
    
  • If INSERT statement succeeds to execute, LAST_INSERT_ID () value is not recovered to its previous value even if the transaction is rolled back.

    -- csql> ;autocommit off
    CREATE TABLE tbl2(a INT PRIMARY KEY AUTO_INCREMENT, b INT UNIQUE);
    INSERT INTO tbl2 VALUES (null, 1);
    COMMIT;
    
    SELECT LAST_INSERT_ID();
    
    1
    
    INSERT INTO tbl2 VALUES (null, 2);
    INSERT INTO tbl2 VALUES (null, 3);
    
    ROLLBACK;
    
    SELECT LAST_INSERT_ID();
    
    3
    
  • LAST_INSERT_ID() value used from the inside of a trigger cannot be identified from the outside of the trigger.

  • LAST_INSERT_IDis independently kept by a session of each application.

CREATE TABLE ss (id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, text VARCHAR(32));
INSERT INTO ss VALUES (NULL, 'cubrid');
SELECT LAST_INSERT_ID ();
     last_insert_id()
=======================
                     1
INSERT INTO ss VALUES (NULL, 'database'), (NULL, 'manager');
SELECT LAST_INSERT_ID ();
     last_insert_id()
=======================
                     2
CREATE TABLE tbl (id INT AUTO_INCREMENT);
INSERT INTO tbl values (500), (NULL), (NULL);
SELECT LAST_INSERT_ID();
     last_insert_id()
=======================
                     1
INSERT INTO tbl VALUES (500), (NULL), (NULL);
SELECT LAST_INSERT_ID();
     last_insert_id()
=======================
                     3
SELECT * FROM tbl;
                    id
=======================
                   500
                     1
                     2
                   500
                     3
                     4
LIST_DBS
LIST_DBS()

The LIST_DBS function outputs the list of all databases in the directory file($CUBRID_DATABASES/databases.txt), separated by blanks.

Return type:STRING
SELECT LIST_DBS();
  list_dbs()
======================
  'testdb demodb'
ROW_COUNT
ROW_COUNT()

The ROW_COUNT function returns the number of rows updated (UPDATE, INSERT, DELETE, REPLACE) by the previous statement.

ROW_COUNT returns 1 for each inserted row and 2 for each updated row for INSERT ON DUPLICATE KEY UPDATE statement. It returns the sum of number of deleted and inserted rows for REPLACE statement.

Statements triggered by trigger will not affect the ROW_COUNT for the statement.

Return type:INT
CREATE TABLE rc (i int);
INSERT INTO rc VALUES (1),(2),(3),(4),(5),(6),(7);
SELECT ROW_COUNT();
   row_count()
===============
              7
UPDATE rc SET i = 0 WHERE i >  3;
SELECT ROW_COUNT();
   row_count()
===============
              4
DELETE FROM rc WHERE i = 0;
SELECT ROW_COUNT();
   row_count()
===============
              4
SESSIONTIMEZONE
SESSIONTIMEZONE()

Prints out a timezone of session (offset or region name) as a string. (e.g. '-05:00', or 'Europe/Vienna').

SELECT SESSIONTIMEZONE();
  sessiontimezone
======================
  'Asia/Seoul'
USER, SYSTEM_USER
USER()
SYSTEM_USER()

The functions USER and SYSTEM_USER are identical and they return the user name together with the host name.

The USER and CURRENT_USER pseudo-columns return the user names who has logged on to the current database as character strings.

Return type:STRING
--selecting the current user on the session
SELECT SYSTEM_USER ();
   user()
======================
  'PUBLIC@cubrid_host'
SELECT USER(), CURRENT_USER;
   user()                CURRENT_USER
============================================
  'PUBLIC@cubrid_host'  'PUBLIC'
--selecting all users of the current database from the system table
SELECT name, id, password FROM db_user;
  name                           id  password
=========================================================
  'DBA'                        NULL  NULL
  'PUBLIC'                     NULL  NULL
  'SELECT_ONLY_USER'           NULL  db_password
  'ALMOST_DBA_USER'            NULL  db_password
  'SELECT_ONLY_USER2'          NULL  NULL
VERSION
VERSION()

The VERSION function returns the version character string representing the CUBRID server version.

Return type:STRING
SELECT VERSION();
   version()
=====================
  '9.1.0.0203'
Encryption Function
MD5
MD5(string)

The MD5 function returns the MD5 128-bit checksum for the input character string. The result value is displayed as a character string that is expressed in 32 hexadecimals, which you can use to create hash keys, for example.

Parameters:string -- Input string. If a value that is not a VARCHAR type is entered, it will be converted to VARCHAR.
Return type:STRING

The return value is a VARCHAR (32) type and if an input parameter is NULL, NULL will be returned.

SELECT MD5('cubrid');
   md5('cubrid')
======================
  '685c62385ce717a04f909047d0a55a16'
SELECT MD5(255);
   md5(255)
======================
  'fe131d7f5a6b38b23cc967316c13dae2'
SELECT MD5('01/01/2010');
   md5('01/01/2010')
======================
  '4a2f373c30426a1b8e9cf002ef0d4a58'
SELECT MD5(CAST('2010-01-01' as DATE));
   md5( cast('2010-01-01' as date))
======================
  '4a2f373c30426a1b8e9cf002ef0d4a58'
SHA1
SHA1(string)

The SHA1 function calculates an SHA-1 160-bit checksum for the string, as described in RFC 3174 (Secure Hash Algorithm).

Parameters:string -- target string to be encrypted
Return type:STRING

The value is returned as a string of 40 hex digits, or NULL if the argument is NULL.

SELECT SHA1('cubrid');
      sha1('cubrid')
======================
  '0562A8E9C814E660F5FFEB0DAC739ABFBBB1CB69'
SHA2
SHA2(string, hash_length)

The SHA2 function calculates the SHA-2 family of hash functions (SHA-224, SHA-256, SHA-384, and SHA-512). The first argument is the cleartext string to be hashed. The second argument indicates the desired bit length of the result, which must have a value of 224, 256, 384, 512, or 0 (which is equivalent to 256).

Parameters:string -- target string to be encrypted
Return type:STRING

If either argument is NULL or the hash length is not one of the permitted values, the return value is NULL. Otherwise, the function result is a hash value containing the desired number of bits.

SELECT SHA2('cubrid', 256);
   sha2('cubrid', 256)
======================
  'D14DA17F2C492114F4A57D9F7BED908FD3A351B40CD59F0F79413687E4CA85A5'
SELECT SHA2('cubrid', 224);
   sha2('cubrid', 224)
======================
  '8E5E18B5B47646C31CCEA98A87B19CBEF084036716FBD13D723AC9B2'
Comparison Expression
Simple Comparison Expression

A comparison expression is an expression that is included in the WHERE clause of the SELECT, UPDATE and DELETE statements, and in the HAVING clause of the SELECT statement. There are simple comparison, ANY / SOME / ALL, BETWEEN, EXISTS, IN / NOT IN, LIKE and IS NULL comparison expressions, depending on the kinds of the operators combined.

A simple comparison expression compares two comparable data values. Expressions or subqueries are specified as operands, and the comparison expression always returns NULL if one of the operands is NULL. The following table shows operators that can be used in the simple comparison expressions. For details, see Comparison Operators.

Comparison Operators

Comparison Operator Description Comparison Expression Return Value
= A value of left operand is the same as that of right operand. 1=2 0
<> , != A value of left operand is not the same as that of right operand. 1<>2 1
> A value of left operand is greater than that of right operand. 1>2 0
< A value of left operand is less than that of right operand. 1<2 1
>= A value of left operand is equal to or greater than that of right operand. 1>=2 0
<= A value of left operand is equal to or less than that of right operand. 1<=2 1
ANY/SOME/ALL quantifiers

A comparison expression that includes quantifiers such as ANY/SOME/ALL performs comparison operation on one data value and on some or all values included in the list. A comparison expression that includes ANY or SOME returns TRUE if the value of the data on the left satisfies simple comparison with at least one of the values in the list specified as an operand on the right. A comparison expression that includes ALL returns TRUE if the value of the data on the left satisfies simple comparison with all values in the list on the right.

When a comparison operation is performed on NULL in a comparison expression that includes ANY or SOME, UNKNOWN or TRUE is returned as a result; when a comparison operation is performed on NULL in a comparison expression that includes ALL, UNKNOWN or FALSE is returned.

expression comp_op SOME expression
expression comp_op ANY expression
expression comp_op ALL expression
  • comp_op : A comparison operator >, = or <= can be used.
  • expression (left): A single-value column, path expression (ex.: tbl_name.col_name), constant value or arithmetic function that produces a single value can be used.
  • expression (right): A column name, path expression, list (set) of constant values or subquery can be used. A list is a set represented within braces ({}). If a subquery is used, expression (left) and comparison operation on all results of the subquery execution is performed.
--creating a table

CREATE TABLE condition_tbl (id int primary key, name char(10), dept_name VARCHAR, salary INT);
INSERT INTO condition_tbl VALUES(1, 'Kim', 'devel', 4000000);
INSERT INTO condition_tbl VALUES(2, 'Moy', 'sales', 3000000);
INSERT INTO condition_tbl VALUES(3, 'Jones', 'sales', 5400000);
INSERT INTO condition_tbl VALUES(4, 'Smith', 'devel', 5500000);
INSERT INTO condition_tbl VALUES(5, 'Kim', 'account', 3800000);
INSERT INTO condition_tbl VALUES(6, 'Smith', 'devel', 2400000);
INSERT INTO condition_tbl VALUES(7, 'Brown', 'account', NULL);

--selecting rows where department is sales or devel
SELECT * FROM condition_tbl WHERE dept_name = ANY{'devel','sales'};
           id  name                  dept_name                  salary
======================================================================
            1  'Kim       '          'devel'                   4000000
            2  'Moy       '          'sales'                   3000000
            3  'Jones     '          'sales'                   5400000
            4  'Smith     '          'devel'                   5500000
            6  'Smith     '          'devel'                   2400000
--selecting rows comparing NULL value in the ALL group conditions
SELECT * FROM condition_tbl WHERE salary > ALL{3000000, 4000000, NULL};
There are no results.
--selecting rows comparing NULL value in the ANY group conditions
SELECT * FROM condition_tbl WHERE salary > ANY{3000000, 4000000, NULL};
           id  name                  dept_name                  salary
======================================================================
            1  'Kim       '          'devel'                   4000000
            3  'Jones     '          'sales'                   5400000
            4  'Smith     '          'devel'                   5500000
            5  'Kim       '          'account'                 3800000
--selecting rows where salary*0.9 is less than those salary in devel department
SELECT * FROM condition_tbl WHERE (
  (0.9 * salary) < ALL (SELECT salary FROM condition_tbl
  WHERE dept_name = 'devel')
);
           id  name                  dept_name                  salary
======================================================================
            6  'Smith     '          'devel'                   2400000
BETWEEN

The BETWEEN makes a comparison to determine whether the data value on the left exists between two data values specified on the right. It returns TRUE even when the data value on the left is the same as a boundary value of the comparison target range. If NOT comes before the BETWEEN keyword, the result of a NOT operation on the result of the BETWEEN operation is returned.

i BETWEEN g AND m and the compound condition i >= g AND i <= m have the same effect.

expression [ NOT ] BETWEEN expression AND expression
  • expression : A column name, path expression (ex.: tbl_name.col_name), constant value, arithmetic expression or aggregate function can be used. For a character string expression, the conditions are evaluated in alphabetical order. If NULL is specified for at least one of the expressions, the BETWEEN predicate returns UNKNOWN as a result.
--selecting rows where 3000000 <= salary <= 4000000
SELECT * FROM condition_tbl WHERE salary BETWEEN 3000000 AND 4000000;
SELECT * FROM condition_tbl WHERE (salary >= 3000000) AND (salary <= 4000000);
           id  name                  dept_name                  salary
======================================================================
            1  'Kim       '          'devel'                   4000000
            2  'Moy       '          'sales'                   3000000
            5  'Kim       '          'account'                 3800000
--selecting rows where salary < 3000000 or salary > 4000000
SELECT * FROM condition_tbl WHERE salary NOT BETWEEN 3000000 AND 4000000;
           id  name                  dept_name                  salary
======================================================================
            3  'Jones     '          'sales'                   5400000
            4  'Smith     '          'devel'                   5500000
            6  'Smith     '          'devel'                   2400000
--selecting rows where name starts from A to E
SELECT * FROM condition_tbl WHERE name BETWEEN 'A' AND 'E';
           id  name                  dept_name                  salary
======================================================================
            7  'Brown     '          'account'                    NULL
EXISTS

The EXISTS returns TRUE if one or more results of the execution of the subquery specified on the right exist, and returns FALSE if the result of the operation is an empty set.

EXISTS expression
  • expression : Specifies a subquery and compares to determine whether the result of the subquery execution exists. If the subquery does not produce any result, the result of the conditional expression is FALSE.
--selecting rows using EXISTS and subquery
SELECT 'raise' FROM db_root WHERE EXISTS(
SELECT * FROM condition_tbl WHERE salary < 2500000);
  'raise'
======================
  'raise'
--selecting rows using NOT EXISTS and subquery
SELECT 'raise' FROM db_root WHERE NOT EXISTS(
SELECT * FROM condition_tbl WHERE salary < 2500000);
There are no results.
IN

The IN compares to determine whether the single data value on the left is included in the list specified on the right. That is, the predicate returns TRUE if the single data value on the left is an element of the expression specified on the right. If NOT comes before the IN keyword, the result of a NOT operation on the result of the IN operation is returned.

expression [ NOT ] IN expression
  • expression (left): A single-value column, path expression (ex.: tbl_name.col_name), constant value or arithmetic function that produces a single value can be used.
  • expression (right): A column name, path expression, list (set) of constant values or subquery can be used. A list is a set represented within parentheses (()) or braces ({}). If a subquery is used, comparison with expression(left) is performed for all results of the subquery execution.
--selecting rows where department is sales or devel
SELECT * FROM condition_tbl WHERE dept_name IN {'devel','sales'};
SELECT * FROM condition_tbl WHERE dept_name = ANY{'devel','sales'};
           id  name                  dept_name                  salary
======================================================================
            1  'Kim       '          'devel'                   4000000
            2  'Moy       '          'sales'                   3000000
            3  'Jones     '          'sales'                   5400000
            4  'Smith     '          'devel'                   5500000
            6  'Smith     '          'devel'                   2400000
--selecting rows where department is neither sales nor devel
SELECT * FROM condition_tbl WHERE dept_name NOT IN {'devel','sales'};
           id  name                  dept_name                  salary
======================================================================
            5  'Kim       '          'account'                 3800000
            7  'Brown     '          'account'                    NULL
IS NULL

The IS NULL compares to determine whether the expression specified on the left is NULL, and if it is NULL, returns TRUE and it can be used in the conditional expression. If NOT comes before the NULL keyword, the result of a NOT operation on the result of the IS NULL operation is returned.

expression IS [ NOT ] NULL
  • expression : A single-value column, path expression (ex.: tbl_name.col_name), constant value or arithmetic function that produces a single value can be used.
--selecting rows where salary is NULL
SELECT * FROM condition_tbl WHERE salary IS NULL;
           id  name                  dept_name                  salary
======================================================================
            7  'Brown     '          'account'                    NULL
--selecting rows where salary is NOT NULL
SELECT * FROM condition_tbl WHERE salary IS NOT NULL;
           id  name                  dept_name                  salary
======================================================================
            1  'Kim       '          'devel'                   4000000
            2  'Moy       '          'sales'                   3000000
            3  'Jones     '          'sales'                   5400000
            4  'Smith     '          'devel'                   5500000
            5  'Kim       '          'account'                 3800000
            6  'Smith     '          'devel'                   2400000
--simple comparison operation returns NULL when operand is NULL
SELECT * FROM condition_tbl WHERE salary = NULL;
There are no results.
LIKE

The LIKE compares patterns between character string data, and returns TRUE if a character string whose pattern matches the search word is found. Pattern comparison target types are CHAR, VARCHAR and STRING. The LIKE search cannot be performed on an BIT type. If NOT comes before the LIKE keyword, the result of a NOT operation on the result of the LIKE operation is returned.

A wild card string corresponding to any character or character string can be included in the search word on the right of the LIKE operator. % (percent) and _ (underscore) can be used. .% corresponds to any character string whose length is 0 or greater, and _ corresponds to one character. An escape character is a character that is used to search for a wild card character itself, and can be specified by the user as another character (NULL, alphabet, or number whose length is 1. See below for an example of using a character string that includes wild card or escape characters.

expression [ NOT ] LIKE pattern [ ESCAPE char ]
  • expression: Specifies the data type column of the character string. Pattern comparison, which is case-sensitive, starts from the first character of the column.
  • pattern: Enters the search word. A character string with a length of 0 or greater is required. Wild card characters (% or _) can be included as the pattern of the search word. The length of the character string is 0 or greater.
  • ESCAPE char : NULL, alphabet, or number is allowed for char. If the string pattern of the search word includes "_" or "%" itself, an ESCAPE character must be specified. For example, if you want to search for the character string "10%" after specifying backslash (\) as the ESCAPE character, you must specify "10%" for pattern. If you want to search for the character string "C:\", you can specify "C:\" for pattern.

For details about character sets supported in CUBRID, see Character Strings.

Whether to detect the escape characters of the LIKE conditional expression is determined depending on the configuration of no_backslash_escapes and require_like_escape_character in the cubrid.conf file. For details, see Statement/Type-Related Parameters.

Note

  • To execute string comparison operation for data entered in the multibyte charset environment such as UTF-8, the parameter setting (single_byte_compare = yes) which compares strings by 1 byte should be added to the cubrid.conf file for a successful search result.
  • Versions after CUBRID 9.0 support Unicode charset, so the single_byte_compare parameter is no longer used.
--selection rows where name contains lower case 's', not upper case
SELECT * FROM condition_tbl WHERE name LIKE '%s%';
           id  name                  dept_name                  salary
======================================================================
            3  'Jones     '          'sales'                   5400000
--selection rows where second letter is 'O' or 'o'
SELECT * FROM condition_tbl WHERE UPPER(name) LIKE '_O%';
           id  name                  dept_name                  salary
======================================================================
            2  'Moy       '          'sales'                   3000000
            3  'Jones     '          'sales'                   5400000
--selection rows where name is 3 characters
SELECT * FROM condition_tbl WHERE name LIKE '___';
           id  name                  dept_name                  salary
======================================================================
            1  'Kim       '          'devel'                   4000000
            2  'Moy       '          'sales'                   3000000
            5  'Kim       '          'account'                 3800000
REGEXP, RLIKE

The REGEXP and RLIKE are used interchangeably; a regular expressions is a powerful way to specify a pattern for a complex search. CUBRID uses Henry Spencer's implementation of regular expressions, which conforms the POSIX 1003.2 standards. The details on regular expressions are not described in this page. For more information on regular expressions, see Henry Spencer's regex(7).

The following list describes basic characteristics of regular expressions.

  • "." matches any single character(including new-line and carriage-return).
  • "[...]" matches one of characters within square brackets. For example, "[abc]" matches "a", "b", or "c". To represent a range of characters, use a dash (-). "[a-z]" matches any alphabet letter whereas "[0-9]" matches any single number.
  • "*" matches 0 or more instances of the thing proceeding it. For example, "xabc*" matches "xab", "xabc", "xabcc", and "xabcxabc" etc. "[0-9][0-9]*" matches any numbers, and ".*" matches every string.
  • To match special characters such as "\n", "\t", "\r", and "\", some must be escaped with the backslash (\) by specifying the value of no_backslash_escapes (default: yes) to no. For details on no_backslash_escapes, see Escape Special Characters.

The difference between REGEXP and LIKE are as follows:

  • The LIKE operator succeeds only if the pattern matches the entire value.
  • The REGEXP operator succeeds if the pattern matches anywhere in the value. To match the entire value, you should use "^" at the beginning and "$" at the end.
  • The LIKE operator is case sensitive, but patterns of regular expressions in REGEXP is not case sensitive. To enable case sensitive, you should use REGEXP BINARY statement.
  • REGEXP, REGEXP BINARY works as ASCII encoding without considering the collation of operands.
SELECT ('a' collate utf8_en_ci REGEXP BINARY 'A' collate utf8_en_ci);
0
SELECT ('a' collate utf8_en_cs REGEXP BINARY 'A' collate utf8_en_cs);
0
SELECT ('a' COLLATE iso88591_bin REGEXP 'A' COLLATE iso88591_bin);
1
SELECT ('a' COLLATE iso88591_bin REGEXP BINARY 'A' COLLATE iso88591_bin);
0

In the below syntax, if expression matches pattern, 1 is returned; otherwise, 0 is returned. If either expression or pattern is NULL, NULL is returned.

The second syntax has the same meaning as the third syntax, which both syntaxes are using NOT.

expression REGEXP | RLIKE [BINARY] pattern
expression NOT REGEXP | RLIKE pattern
NOT (expression REGEXP | RLIKE pattern)
  • expression : Column or input expression
  • pattern : Pattern used in regular expressions; not case sensitive
-- When REGEXP is used in SELECT list, enclosing this with parentheses is required.
-- But used in WHERE clause, no need parentheses.
-- case insensitive, except when used with BINARY.
SELECT name FROM athlete where name REGEXP '^[a-d]';
name
======================
'Dziouba Irina'
'Dzieciol Iwona'
'Dzamalutdinov Kamil'
'Crucq Maurits'
'Crosta Daniele'
'Bukovec Brigita'
'Bukic Perica'
'Abdullayev Namik'
-- \n : match a special character, when no_backslash_escapes=no
SELECT ('new\nline' REGEXP 'new
line');
('new
line' regexp 'new
line')
=====================================
1
-- ^ : match the beginning of a string
SELECT ('cubrid dbms' REGEXP '^cub');
('cubrid dbms' regexp '^cub')
===============================
1
-- $ : match the end of a string
SELECT ('this is cubrid dbms' REGEXP 'dbms$');
('this is cubrid dbms' regexp 'dbms$')
========================================
1
--.: match any character
SELECT ('cubrid dbms' REGEXP '^c.*$');
('cubrid dbms' regexp '^c.*$')
================================
1
-- a+ : match any sequence of one or more a characters. case insensitive.
SELECT ('Aaaapricot' REGEXP '^A+pricot');
('Aaaapricot' regexp '^A+pricot')
================================
1
-- a? : match either zero or one a character.
SELECT ('Apricot' REGEXP '^Aa?pricot');
('Apricot' regexp '^Aa?pricot')
==========================
1
SELECT ('Aapricot' REGEXP '^Aa?pricot');
('Aapricot' regexp '^Aa?pricot')
===========================
1
SELECT ('Aaapricot' REGEXP '^Aa?pricot');
('Aaapricot' regexp '^Aa?pricot')
============================
0
-- (cub)* : match zero or more instances of the sequence abc.
SELECT ('cubcub' REGEXP '^(cub)*$');
('cubcub' regexp '^(cub)*$')
==========================
1
-- [a-dX], [^a-dX] : matches any character that is (or is not, if ^ is used) either a, b, c, d or X.
SELECT ('aXbc' REGEXP '^[a-dXYZ]+');
('aXbc' regexp '^[a-dXYZ]+')
==============================
1
SELECT ('strike' REGEXP '^[^a-dXYZ]+$');
('strike' regexp '^[^a-dXYZ]+$')
================================
1

Note

The following shows RegEx-Specer's license, which is library used to implement the REGEXP conditional expression.

Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved.
This software is not subject to any license of the American Telephone
and Telegraph Company or of the Regents of the University of California.

Permission is granted to anyone to use this software for any purpose on
any computer system, and to alter it and redistribute it, subject
to the following restrictions:

1. The author is not responsible for the consequences of use of this
software, no matter how awful, even if they arise from flaws in it.

2. The origin of this software must not be misrepresented, either by
explicit claim or by omission. Since few users ever read sources,
credits must appear in the documentation.

3. Altered versions must be plainly marked as such, and must not be
misrepresented as being the original software. Since few users
ever read sources, credits must appear in the documentation.

4. This notice may not be removed or altered.
CASE

The CASE expression uses the SQL statement to perform an IF ... THEN statement. When a result of comparison expression specified in a WHEN clause is true, a value specified in THEN clause is returned. A value specified in an ELSE clause is returned otherwise. If no ELSE clause exists, NULL is returned.

CASE control_expression simple_when_list
[ else_clause ]
END

CASE searched_when_list
[ else_clause ]
END

simple_when :
WHEN expression THEN result

searched_when :
WHEN search_condition THEN result

else_clause :
ELSE result

result :
expression | NULL

The CASE expression must end with the END keyword. A control_expression argument and an expression argument in simple_when expression should be comparable data types. The data types of result specified in the THEN ... ELSE statement should all same, or they can be convertible to common data type.

The data type for a value returned by the CASE expression is determined based on the following rules.

  • If data types for result specified in the THEN statement are all same, a value with the data type is returned.
  • If data types can be convertible to common data type even though they are not all same, a value with the data type is returned.
  • If any of values for result is a variable length string, a value data type is a variable length string. If values for result are all a fixed length string, the longest character string or bit string is returned.
  • If any of values for result is an approximate numeric data type, a value with a numeric data type is returned. The number of digits after the decimal point is determined to display all significant figures.
--creating a table
CREATE TABLE case_tbl( a INT);
INSERT INTO case_tbl VALUES (1);
INSERT INTO case_tbl VALUES (2);
INSERT INTO case_tbl VALUES (3);
INSERT INTO case_tbl VALUES (NULL);

--case operation with a search when clause
SELECT a,
       CASE WHEN a=1 THEN 'one'
            WHEN a=2 THEN 'two'
            ELSE 'other'
       END
FROM case_tbl;
            a  case when a=1 then 'one' when a=2 then 'two' else 'other' end
===================================
            1  'one'
            2  'two'
            3  'other'
         NULL  'other'
--case operation with a simple when clause
SELECT a,
       CASE a WHEN 1 THEN 'one'
              WHEN 2 THEN 'two'
              ELSE 'other'
       END
FROM case_tbl;
            a  case a when 1 then 'one' when 2 then 'two' else 'other' end
===================================
            1  'one'
            2  'two'
            3  'other'
         NULL  'other'
--result types are converted to a single type containing all of significant figures
SELECT a,
       CASE WHEN a=1 THEN 1
            WHEN a=2 THEN 1.2345
            ELSE 1.234567890
       END
FROM case_tbl;
            a  case when a=1 then 1 when a=2 then 1.2345 else 1.234567890 end
===================================
            1  1.000000000
            2  1.234500000
            3  1.234567890
         NULL  1.234567890
--an error occurs when result types are not convertible
SELECT a,
       CASE WHEN a=1 THEN 'one'
            WHEN a=2 THEN 'two'
            ELSE 1.2345
       END
FROM case_tbl;
ERROR: Cannot coerce 'one' to type double.
Comparison Functions
COALESCE
COALESCE(expression [, expression ] ...)

The COALESCE function has more than one expression as an argument. If the first argument is non-NULL, the corresponding value is returned if it is NULL, the second argument is returned. If all expressions which have an argument are NULL, NULL is returned. Therefore, this function is generally used to replace NULL with other default value.

Parameters:expression -- Specifies more than one expression. Their types must be comparable each other.
Return type:determined with the type of the arguments

Operation is performed by converting the type of every argument into that with the highest priority. If there is an argument whose type cannot be converted, the type of every argument is converted into a VARCHAR type. The following list shows priority of conversion based on input argument type.

  • CHAR < VARCHAR
  • BIT < VARBIT
  • SHORT < INT < BIGINT < NUMERIC < FLOAT < DOUBLE
  • DATE < TIMESTAMP < DATETIME

For example, if a type of a is INT, b, BIGINT, c, SHORT, and d, FLOAT, then COALESCE (a, b, c, d) returns a FLOAT type. If a type of a is INTEGER, b, DOULBE , c, FLOAT, and d, TIMESTAMP, then COALESCE (a, b, c, d) returns a VARCHAR type.

COALESCE (a, b) works the same as the CASE expression as follows:

CASE WHEN a IS NOT NULL
THEN a
ELSE b
END
SELECT * FROM case_tbl;
            a
=============
            1
            2
            3
         NULL
--substituting a default value 10.0000 for a NULL value
SELECT a, COALESCE(a, 10.0000) FROM case_tbl;
            a  coalesce(a, 10.0000)
===================================
            1  1.0000
            2  2.0000
            3  3.0000
         NULL  10.0000
DECODE
DECODE(expression, search, result [, search, result]* [, default])

As well as a CASE expression, the DECODE function performs the same functionality as the IF ... THEN ... ELSE statement. It compares the expression argument with search argument, and returns the result corresponding to search that has the same value. It returns default if there is no search with the same value, and returns NULL if default is omitted. An expression argument and a search argument to be comparable should be same or convertible each other. The number of digits after the decimal point is determined to display all significant figures including valid number of all result.

Parameters:
  • expression,search -- expressions that are comparable with each other
  • result -- the value to be returned when matched
  • default -- the value to be retuned when no match is found
Return type:

determined with the type of result and default

DECODE(a, b, c, d, e, f) has the same meaning as the CASE expression below.

CASE WHEN a = b THEN c
WHEN a = d THEN e
ELSE f
END
SELECT * FROM case_tbl;
            a
=============
            1
            2
            3
         NULL
--Using DECODE function to compare expression and search values one by one
SELECT a, DECODE(a, 1, 'one', 2, 'two', 'other') FROM case_tbl;
            a  decode(a, 1, 'one', 2, 'two', 'other')
===================================
            1  'one'
            2  'two'
            3  'other'
         NULL  'other'
--result types are converted to a single type containing all of significant figures
SELECT a, DECODE(a, 1, 1, 2, 1.2345, 1.234567890) FROM case_tbl;
            a  decode(a, 1, 1, 2, 1.2345, 1.234567890)
===================================
            1  1.000000000
            2  1.234500000
            3  1.234567890
         NULL  1.234567890
--an error occurs when result types are not convertible
SELECT a, DECODE(a, 1, 'one', 2, 'two', 1.2345) FROM case_tbl;
ERROR: Cannot coerce 'one' to type double.
GREATEST
GREATEST(expression [, expression] ...)

The GREATEST function compares more than one expression specified as parameters and returns the greatest value. If only one expression has been specified, the expression is returned because there is no expression to be compared with.

Therefore, more than one expression that is specified as parameters must be of the type that can be compared with each other. If the types of the specified parameters are identical, so are the types of the return values; if they are different, the type of the return value becomes a convertible common data type.

That is, the GREATEST function compares the values of column 1, column 2 and column 3 in the same row and returns the greatest value while the MAX function compares the values of column in all result rows and returns the greatest value.

Parameters:expression -- Specifies more than one expression. Their types must be comparable each other. One of the arguments is NULL, NULL is returned.
Return type:same as that of the argument

The following example shows how to retrieve the number of every medals and the highest number that Korea won in the demodb database.

SELECT gold, silver , bronze, GREATEST (gold, silver, bronze)
FROM participant
WHERE nation_code = 'KOR';
         gold       silver       bronze  greatest(gold, silver, bronze)
=======================================================================
            9           12            9                              12
            8           10           10                              10
            7           15            5                              15
           12            5           12                              12
           12           10           11                              12
IF
IF(expression1, expression2, expression3)

The IF function returns expression2 if the value of the arithmetic expression specified as the first parameter is TRUE, or expression3 if the value is FALSE or NULL. expression2 and expression3 which are returned as a result must be the same or of a convertible common type. If one is explicitly NULL, the result of the function follows the type of the non-NULL parameter.

Parameters:
  • expression1 -- comparison expression
  • expression2 -- the value to be returned when expression1 is true
  • expression3 -- the value to be returned when expression1 is not true
Return type:

type of expression2 or expression3

IF(a, b, c) has the same meaning as the CASE expression in the following example:

CASE WHEN a IS TRUE THEN b
ELSE c
END
SELECT * FROM case_tbl;
            a
=============
            1
            2
            3
         NULL
--IF function returns the second expression when the first is TRUE
SELECT a, IF(a=1, 'one', 'other') FROM case_tbl;
            a   if(a=1, 'one', 'other')
===================================
            1  'one'
            2  'other'
            3  'other'
         NULL  'other'
--If function in WHERE clause
SELECT * FROM case_tbl WHERE IF(a=1, 1, 2) = 1;
            a
=============
            1
IFNULL, NVL
IFNULL(expr1, expr2)
NVL(expr1, expr2)

The IFNULL function is working like the NVL function; however, only the NVL function supports collection type as well. The IFNULL function (which has two arguments) returns expr1 if the value of the first expression is not NULL or returns expr2, otherwise.

Parameters:
  • expr1 -- expression
  • expr2 -- the value to be returned when expr1 is NULL
Return type:

determined with the type of expr1 and expr2

Operation is performed by converting the type of every argument into that with the highest priority. If there is an argument whose type cannot be converted, the type of every argument is converted into a VARCHAR type. The following list shows priority of conversion based on input argument type.

  • CHAR < VARCHAR
  • BIT < VARBIT
  • SHORT < INT < BIGINT < NUMERIC < FLOAT < DOUBLE
  • DATE < TIMESTAMP < DATETIME

For example, if a type of a is INT and b is BIGINT, then IFNULL (a, b) returns a BIGINT type. If a type of a is INTEGER and b is TIMESTAMP, then IFNULL (a, b) returns a VARCHAR type.

IFNULL(a, b) or NVL(a, b) has the same meaning as the CASE expression below.

CASE WHEN a IS NULL THEN b
ELSE a
END
SELECT * FROM case_tbl;
            a
=============
            1
            2
            3
         NULL
--returning a specific value when a is NULL
SELECT a, NVL(a, 10.0000) FROM case_tbl;
            a  nvl(a, 10.0000)
===================================
            1  1.0000
            2  2.0000
            3  3.0000
         NULL  10.0000
--IFNULL can be used instead of NVL and return values are converted to the string type
SELECT a, IFNULL(a, 'UNKNOWN') FROM case_tbl;
            a   ifnull(a, 'UNKNOWN')
===================================
            1  '1'
            2  '2'
            3  '3'
         NULL  'UNKNOWN'
ISNULL
ISNULL(expression)

The ISNULL function performs a comparison to determine if the result of the expression specified as an argument is NULL. The function returns 1 if it is NULL or 0 otherwise. You can check if a certain value is NULL. This function is working like the ISNULL expression.

Parameters:expression -- An arithmetic function that has a single-value column, path expression (ex.: tbl_name.col_name), constant value is specified.
Return type:INT
--Using ISNULL function to select rows with NULL value
SELECT * FROM condition_tbl WHERE ISNULL(salary);
           id  name                  dept_name                  salary
======================================================================
            7  'Brown     '          'account'                    NULL
LEAST
LEAST(expression [, expression] ...)

The LEAST function compares more than one expression specified as parameters and returns the smallest value. If only one expression has been specified, the expression is returned because there is no expression to be compared with.

Therefore, more than one expression that is specified as parameters must be of the type that can be compared with each other. If the types of the specified parameters are identical, so are the types of the return values; if they are different, the type of the return value becomes a convertible common data type.

That is, the LEAST function compares the values of column 1, column 2 and column 3 in the same row and returns the smallest value while the MIN() compares the values of column in all result rows and returns the smallest value.

Parameters:expression -- Specifies more than one expression. Their types must be comparable each other. One of the arguments is NULL, NULL is returned.
Return type:same as that of the argument

The following example shows how to retrieve the number of every medals and the lowest number that Korea won in the demodb database.

SELECT gold, silver , bronze, LEAST(gold, silver, bronze) FROM participant
WHERE nation_code = 'KOR';
         gold       silver       bronze  least(gold, silver, bronze)
====================================================================
            9           12            9                            9
            8           10           10                            8
            7           15            5                            5
           12            5           12                            5
           12           10           11                           10
NULLIF
NULLIF(expr1, expr2)

The NULLIF function returns NULL if the two expressions specified as the parameters are identical, and returns the first parameter value otherwise.

Parameters:
  • expr1 -- expression to be compared with expr2
  • expr2 -- expression to be compared with expr1
Return type:

type of expr1

NULLIF (a, b) is the same of the CASE expression.

CASE
WHEN a = b THEN NULL
ELSE a
END
SELECT * FROM case_tbl;
            a
=============
            1
            2
            3
         NULL
--returning NULL value when a is 1
SELECT a, NULLIF(a, 1) FROM case_tbl;
            a  nullif(a, 1)
===========================
            1          NULL
            2             2
            3             3
         NULL          NULL
--returning NULL value when arguments are same
SELECT NULLIF (1, 1.000)  FROM db_root;
  nullif(1, 1.000)
======================
  NULL
--returning the first value when arguments are not same
SELECT NULLIF ('A', 'a')  FROM db_root;
  nullif('A', 'a')
======================
  'A'
NVL2
NVL2(expr1, expr2, expr3)

Three parameters are specified for the NVL2 function. The second expression (expr2) is returned if the first expression (expr1) is not NULL; the third expression (expr3) is returned if it is NULL.

Parameters:
  • expr1 -- expression
  • expr2 -- the value to be returned when expr1 is not NULL
  • expr3 -- the value to be returned when expr1 is NULL
Return type:

determined with the type of expr1, expr2 and expr3

Operation is performed by converting the type of every argument into that with the highest priority. If there is an argument whose type cannot be converted, the type of every argument is converted into a VARCHAR type. The following list shows priority of conversion based on input argument type.

  • CHAR < VARCHAR
  • BIT < VARBIT
  • SHORT < INT < BIGINT < NUMERIC < FLOAT < DOUBLE
  • DATE < TIMESTAMP < DATETIME

For example, if a type of a is INT, b, BIGINT, and c, SHORT, then NVL2 (a, b, c) returns a BIGINT type. If a type of a is INTEGER, b, DOUBLE, and c, TIMESTAMP, then NVL2 (a, b, c) returns a VARCHAR type.

SELECT * FROM case_tbl;
            a
=============
            1
            2
            3
         NULL
--returning a specific value of INT type
SELECT a, NVL2(a, a+1, 10.5678) FROM case_tbl;
            a  nvl2(a, a+1, 10.5678)
====================================
            1                      2
            2                      3
            3                      4
         NULL                     11
Other functions
SLEEP
SLEEP(sec)

This function pauses for the specified time then resumes the operations.

Parameters:sec -- sleep time. The unit is second and inputs double type value.
Return type:INT
SELECT SLEEP(3);

It pauses for 3 seconds.

SYS_GUID
SYS_GUID()

It returns the unique hexadecimal string of 32 characters randomly.

SELECT SYS_GUID();
sys_guid()
==================================
'938210043A7B4455927A8697FB2571FF'

Data Manipulation Statements

SELECT

The SELECT statement specifies columns that you want to retrieve from a table.

SELECT [ <qualifier> ] <select_expressions>
    [{TO | INTO} <variable_comma_list>]
    [FROM <extended_table_specification_comma_list>]
    [WHERE <search_condition>]
    [GROUP BY {col_name | expr} [ASC | DESC], ...[WITH ROLLUP]]
    [HAVING  <search_condition> ]
    [ORDER BY {col_name | expr} [ASC | DESC], ... [NULLS {FIRST | LAST}]
    [LIMIT [offset,] row_count]
    [USING INDEX { index_name [,index_name, ...] | NONE }]
    [FOR UPDATE [OF <spec_name_comma_list>]]

    <qualifier> ::= ALL | DISTINCT | DISTINCTROW | UNIQUE

    <select_expressions> ::= * | <expression_comma_list> | *, <expression_comma_list>

    <variable_comma_list> ::= [:] identifier, [:] identifier, ...

    <extended_table_specification_comma_list> ::=
        <table_specification>   [
                                    {, <table_specification> } ... |
                                    <join_table_specification> ... |
                                    <join_table_specification2> ...
                                ]

<table_specification> ::=
    <single_table_spec> [<correlation>] |
    <metaclass_specification> [ <correlation> ] |
    <subquery> <correlation> |
    TABLE ( <expression> ) <correlation>

<correlation> ::= [AS] <identifier> [(<identifier_comma_list>)]

<single_table_spec> ::= [ONLY] <table_name> |
                      ALL <table_name> [ EXCEPT <table_name> ]

<metaclass_specification> ::= CLASS <class_name>

<join_table_specification> ::=
    {
        [INNER | {LEFT | RIGHT} [OUTER]] JOIN |
        STRAIGHT_JOIN
    } <table_specification> ON <search_condition>

<join_table_specification2> ::=
    {
        CROSS JOIN |
        NATURAL [ LEFT | RIGHT ] JOIN
    } <table_specification>
  • qualifier: A qualifier. When omitted, it is set to ALL.

    • ALL: Retrieves all records of the table.
    • DISTINCT: Retrieves only records with unique values without allowing duplicates. DISTINCT, DISTINCTROW, and UNIQUE are used interchangeably.
  • <select_expressions>

    • *: By using SELECT * statement, you can retrieve all columns from the table specified in the FROM clause.

    • expression_comma_list: expression can be a path expression (ex.: tbl_name.col_name), variable or table name. All general expressions including arithmetic operations can also be used. Use a comma (,) to separate each expression in the list. You can specify aliases by using the AS keyword for columns or expressions to be queried. Specified aliases are used as column names in GROUP BY, HAVING and ORDER BY clauses. The position index of a column is assigned based on the order in which the column was specified. The starting value is 1.

      As AVG, COUNT, MAX, MIN, or SUM, an aggregate function that manipulates the retrieved data can also be used in the expression.

  • table_name.*: Specifies the table name and using * has the same effect as specifying all columns for the given table.

  • variable_comma_list: The data retrieved by the select_expressions can be stored in more than one variable.

  • [:]identifier: By using the :identifier after TO (or INTO), you can store the data to be retrieved in the ':identifier' variable.

  • <single_table_spec>

    • If a superclass name is specified after the ONLY keyword, only the superclass, not the subclass inheriting from it, is selected.
    • If a superclass name is specified after the ALL keyword, the superclass as well as the subclass inheriting from it are both selected.
    • You can define the list of subclass not to be selected after the EXCEPT keyword.

The following example shows how to retrieve host countries of the Olympic Games without any duplicates. This example is performed on the olympic table of demodb. The DISTINCT or UNIQUE keyword makes the query result unique. For example, when there are multiple olympic records of which each host_nation value is 'Greece', you can use such keywords to display only one value in the query result.

SELECT DISTINCT host_nation
FROM olympic;
  host_nation
======================
  'Australia'
  'Belgium'
  'Canada'
  'Finland'
  'France'
...

The following example shows how to define an alias to a column to be queried and sort the result record by using the column alias in the ORDER BY clause. At this time, the number of the result records is limited to 5 by using the LIMIT clause.

SELECT host_year as col1, host_nation as col2
FROM olympic
ORDER BY col2 LIMIT 5;
         col1  col2
===================================
         2000  'Australia'
         1956  'Australia'
         1920  'Belgium'
         1976  'Canada'
         1948  'England'
SELECT CONCAT(host_nation, ', ', host_city) AS host_place
FROM olympic
ORDER BY host_place LIMIT 5;
  host_place
======================
  'Australia,  Melbourne'
  'Australia,  Sydney'
  'Belgium,  Antwerp'
  'Canada,  Montreal'
  'England,  London'
FROM Clause

The FROM clause specifies the table in which data is to be retrieved in the query. If no table is referenced, the FROM clause can be omitted. Retrieval paths are as follows:

  • Single table
  • Subquery
  • Derived table
SELECT [<qualifier>] <select_expressions>
[
    FROM <table_specification> [ {, <table_specification> | <join_table_specification> }... ]
]

<select_expressions> ::= * | <expression_comma_list> | *, <expression_comma_list>

<table_specification> ::=
    <single_table_spec> [<correlation>] |
    <metaclass_specification> [<correlation>] |
    <subquery> <correlation> |
    TABLE (<expression>) <correlation>

<correlation> ::= [AS] <identifier> [(<identifier_comma_list>)]

<single_table_spec> ::= [ONLY] <table_name> |
                      ALL <table_name> [EXCEPT <table_name>]

<metaclass_specification> ::= CLASS <class_name>
  • <select_expressions>: One or more columns or expressions to query is specified. Use * to query all columns in the table. You can also specify an alias for a column or an expression to be queried by using the AS keyword. This keyword can be used in GROUP BY, HAVING and ORDER BY clauses. The position index of the column is given according to the order in which the column was specified. The starting value is 1.
  • <table_specification>: At least one table name is specified after the FROM clause. Subqueries and derived tables can also be used in the FROM clause. For details on subquery derived tables, see Subquery Derived Table.
--FROM clause can be omitted in the statement
SELECT 1+1 AS sum_value;
    sum_value
=============
            2
SELECT CONCAT('CUBRID', '2008' , 'R3.0') AS db_version;
  db_version
======================
  'CUBRID2008R3.0'
Derived Table

In the query statement, subqueries can be used in the table specification of the FROM clause. Such subqueries create derived tables where subquery results are treated as tables. A correlation specification must be used when a subquery that creates a derived table is used.

Derived tables are also used to access the individual element of an attribute that has a set value. In this case, an element of the set value is created as an instance in the derived table.

Subquery Derived Table

Each instance in the derived table is created from the result of the subquery in the FROM clause. A derived table created form a subquery can have any number of columns and records.

FROM (subquery) [AS] [derived_table_name [(column_name [{, column_name } ... ])]]
  • The number of column_name and the number of columns created by the subquery must be identical.
  • derived_table_name can be omitted.

The following example shows how to retrieve the sum of the number of gold (gold) medals won by Korea and that of silver medals won by Japan. This example shows a way of getting an intermediate result of the subquery and processing it as a single result, by using a derived table. The query returns the sum of the gold values whose nation_code is 'KOR' and the silver values whose nation_code column is 'JPN'.

SELECT SUM (n)
FROM (SELECT gold FROM participant WHERE nation_code = 'KOR'
      UNION ALL
      SELECT silver FROM participant WHERE nation_code = 'JPN') AS t(n);

Subquery derived tables can be useful when combined with outer queries. For example, a derived table can be used in the FROM clause of the subquery used in the WHERE clause. The following example shows nation_code, host_year and gold records whose number of gold medals is greater than average sum of the number of silver and bronze medals when one or more silver or bronze medals were won. In this example, the query (the outer SELECT clause) and the subquery (the inner SELECT clause) share the nation_code attribute.

SELECT nation_code, host_year, gold
FROM participant p
WHERE gold > (SELECT AVG(s)
              FROM (SELECT silver + bronze
                    FROM participant
                    WHERE nation_code = p.nation_code
                    AND silver > 0
                    AND bronze > 0)
                   AS t(s));
  nation_code      host_year      gold
=========================================
  'JPN'                2004         16
  'CHN'                2004         32
  'DEN'                1996          4
  'ESP'                1992         13
WHERE Clause

In a query, a column can be processed based on conditions. The WHERE clause specifies a search condition for data.

WHERE <search_condition>

    <search_condition> ::=
        <comparison_predicate>
        <between_predicate>
        <exists_predicate>
        <in_predicate>
        <null_predicate>
        <like_predicate>
        <quantified_predicate>
        <set_predicate>

The WHERE clause specifies a condition that determines the data to be retrieved by search_condition or a query. Only data for which the condition is true is retrieved for the query results. (NULL value is not retrieved for the query results because it is evaluated as unknown value.)

The logical operator AND or OR can be used for multiple conditions. If AND is specified, all conditions must be true. If OR is specified, only one needs to be true. If the keyword NOT is preceded by a condition, the meaning of the condition is reserved. The following table shows the order in which logical operators are evaluated.

Priority Operator Function
1 () Logical expressions in parentheses are evaluated first.
2 NOT Negates the result of the logical expression.
3 AND All conditions in the logical expression must be true.
4 OR One of the conditions in the logical expression must be true.
GROUP BY ... HAVING Clause

The GROUP BY clause is used to group the result retrieved by the SELECT statement based on a specific column. This clause is used to sort by group or to get the aggregation by group using the aggregation function. Herein, a group consists of records that have the same value for the column specified in the GROUP BY clause.

You can also set a condition for group selection by including the HAVING clause after the GROUP BY clause. That is, only groups satisfying the condition specified by the HAVING clause are queried out of all groups that are grouped by the GROUP BY clause.

By SQL standard, you cannot specify a column (hidden column) not defined in the GROUP BY clause to the SELECT column list. However, by using extended CUBRID grammars, you can specify the hidden column to the SELECT column list. If you do not use the extended CUBRID grammars, the only_full_group_by parameter should be set to yes. For details, see Statement/Type-Related Parameters.

SELECT ...
GROUP BY {col_name | expr | position} [ASC | DESC], ...
          [WITH ROLLUP] [HAVING <search_condition>]
  • col_name | expr | position: Specifies one or more column names, expressions, aliases or column location. Items are separated by commas. Columns are sorted on this basis.

  • [ASC | DESC]: Specifies the ASC or DESC sorting option after the columns specified in the GROUP BY clause. If the sorting option is not specified, the default value is ASC.

  • <search_condition>: Specifies the search condition in the HAVING clause. In the HAVING clause, you can refer to columns and aliases specified in the GROUP BY clause, or columns used in aggregate functions.

    Note

    Even the hidden columns not specified in the GROUP BY clause can be referred to, if the value of the only_full_group_by parameter is set to yes. At this time, the HAVING condition does not affect to the query result.

  • WITH ROLLUP: If you specify the WITH ROLLUP modifier in the GROUP BY clause, the aggregate information of the result value of each GROUPed BY column is displayed for each group, and the total of all result rows is displayed at the last row. When a WITH ROLLUP modifier is defined in the GROUP BY clause, the result value for all rows of the group is additionally displayed. In other words, total aggregation is made for the value aggregated by group. When there are two columns for Group By, the former is considered as a large unit and the latter is considered as a small unit, so the total aggregation row for the small unit and the total aggregation row for the large unit are added. For example, you can check the aggregation of the sales result per department and salesperson through one query.

-- creating a new table
CREATE TABLE sales_tbl
(dept_no INT, name VARCHAR(20), sales_month INT, sales_amount INT DEFAULT 100, PRIMARY KEY (dept_no, name, sales_month));

INSERT INTO sales_tbl VALUES
(201, 'George' , 1, 450), (201, 'George' , 2, 250), (201, 'Laura'  , 1, 100), (201, 'Laura'  , 2, 500),
(301, 'Max'    , 1, 300), (301, 'Max'    , 2, 300),
(501, 'Stephan', 1, 300), (501, 'Stephan', 2, DEFAULT), (501, 'Chang'  , 1, 150),(501, 'Chang'  , 2, 150),
(501, 'Sue'    , 1, 150), (501, 'Sue'    , 2, 200);

-- selecting rows grouped by dept_no
SELECT dept_no, avg(sales_amount)
FROM sales_tbl
GROUP BY dept_no;
      dept_no         avg(sales_amount)
=======================================
          201     3.250000000000000e+02
          301     3.000000000000000e+02
          501     1.750000000000000e+02
-- conditions in WHERE clause operate first before GROUP BY
SELECT dept_no, avg(sales_amount)
FROM sales_tbl
WHERE sales_amount > 100
GROUP BY dept_no;
      dept_no         avg(sales_amount)
=======================================
          201     4.000000000000000e+02
          301     3.000000000000000e+02
          501     1.900000000000000e+02
-- conditions in HAVING clause operate last after GROUP BY
SELECT dept_no, avg(sales_amount)
FROM sales_tbl
WHERE sales_amount > 100
GROUP BY dept_no HAVING avg(sales_amount) > 200;
      dept_no         avg(sales_amount)
=======================================
          201     4.000000000000000e+02
          301     3.000000000000000e+02
-- selecting and sorting rows with using column alias
SELECT dept_no AS a1, avg(sales_amount) AS a2
FROM sales_tbl
WHERE sales_amount > 200 GROUP
BY a1 HAVING a2 > 200
ORDER BY a2;
           a1                        a2
=======================================
          301     3.000000000000000e+02
          501     3.000000000000000e+02
          201     4.000000000000000e+02
-- selecting rows grouped by dept_no, name with WITH ROLLUP modifier
SELECT dept_no AS a1, name AS a2, avg(sales_amount) AS a3
FROM sales_tbl
WHERE sales_amount > 100
GROUP BY a1, a2 WITH ROLLUP;
           a1  a2                                          a3
=============================================================
          201  'George'                 3.500000000000000e+02
          201  'Laura'                  5.000000000000000e+02
          201  NULL                     4.000000000000000e+02
          301  'Max'                    3.000000000000000e+02
          301  NULL                     3.000000000000000e+02
          501  'Chang'                  1.500000000000000e+02
          501  'Stephan'                3.000000000000000e+02
          501  'Sue'                    1.750000000000000e+02
          501  NULL                     1.900000000000000e+02
         NULL  NULL                     2.750000000000000e+02
ORDER BY Clause

The ORDER BY clause sorts the query result set in ascending or descending order. If you do not specify a sorting option such as ASC or DESC, the result set in ascending order by default. If you do not specify the ORDER BY clause, the order of records to be queried may vary depending on query.

SELECT ...
ORDER BY {col_name | expr | position} [ASC | DESC], ...] [NULLS {FIRST | LAST}]
  • col_name | expr | position: Specifies a column name, expression, alias, or column location. One or more column names, expressions or aliases can be specified. Items are separated by commas. A column that is not specified in the list of SELECT columns can be specified.
  • [ASC | DESC]: ASC means sorting in ascending order, and DESC is sorting in descending order. If the sorting option is not specified, the default value is ASC.
  • [NULLS {FIRST | LAST}]: NULLS FIRST sorts NULL at first, NULLS LAST sorts NULL at last. If this syntax is omitted, ASC sorts NULL at first, DESC sorts NULL at last.
-- selecting rows sorted by ORDER BY clause
SELECT *
FROM sales_tbl
ORDER BY dept_no DESC, name ASC;
      dept_no  name                  sales_month  sales_amount
==============================================================
          501  'Chang'                         1           150
          501  'Chang'                         2           150
          501  'Stephan'                       1           300
          501  'Stephan'                       2           100
          501  'Sue'                           1           150
          501  'Sue'                           2           200
          301  'Max'                           1           300
          301  'Max'                           2           300
          201  'George'                        1           450
          201  'George'                        2           250
          201  'Laura'                         1           100
          201  'Laura'                         2           500
-- sorting reversely and limiting result rows by LIMIT clause
SELECT dept_no AS a1, avg(sales_amount) AS a2
FROM sales_tbl
GROUP BY a1
ORDER BY a2 DESC
LIMIT 3;
           a1           a2
=======================================
          201     3.250000000000000e+02
          301     3.000000000000000e+02
          501     1.750000000000000e+02

The following is an example how to specify the NULLS FIRST or NULLS LAST after ORDER BY clause.

CREATE TABLE tbl (a INT, b VARCHAR);

INSERT INTO tbl VALUES
(1,NULL), (2,NULL), (3,'AB'), (4,NULL), (5,'AB'),
(6,NULL), (7,'ABCD'), (8,NULL), (9,'ABCD'), (10,NULL);
SELECT * FROM tbl ORDER BY b NULLS FIRST;
            a  b
===================================
            1  NULL
            2  NULL
            4  NULL
            6  NULL
            8  NULL
           10  NULL
            3  'ab'
            5  'ab'
            7  'abcd'
            9  'abcd'
SELECT * FROM tbl ORDER BY b NULLS LAST;
            a  b
===================================
            3  'ab'
            5  'ab'
            7  'abcd'
            9  'abcd'
            1  NULL
            2  NULL
            4  NULL
            6  NULL
            8  NULL
           10  NULL

Note

Translation of GROUP BY alias

CREATE TABLE t1(a INT, b INT, c INT);
INSERT INTO t1 VALUES(1,1,1);
INSERT INTO t1 VALUES(2,NULL,2);
INSERT INTO t1 VALUES(2,2,2);

SELECT a, NVL(b,2) AS b
FROM t1
GROUP BY a, b;  -- Q1

When you run the above SELECT query, "GROUP BY a, b" is translated as:

  • "GROUP BY a, NVL(b, 2)"(alias name b) in 9.2 or before. The result is the same as Q2's result as below.

    SELECT a, NVL(b,2) AS bxxx
    FROM t1
    GROUP BY a, bxxx;  -- Q2
    
            a            b
    ======================
            1            1
            2            2
    
    • "GROUP BY a, b"(column name b) in 9.3 or higher. The result is the same as Q3's result as below.
    SELECT a, NVL(b,2) AS bxxx
    FROM t1
    GROUP BY a, b;  -- Q3
    
            a            b
    ======================
            1            1
            2            2
            2            2
    
LIMIT Clause

The LIMIT clause can be used to limit the number of records displayed. You can specify a very big integer for row_count to display to the last row, starting from a specific row. The LIMIT clause can be used as a prepared statement. In this case, the bind parameter (?) can be used instead of an argument.

INST_NUM () and ROWNUM cannot be included in the WHERE clause in a query that contains the LIMIT clause. Also, LIMIT cannot be used together with HAVING GROUPBY_NUM ().

LIMIT {[offset,] row_count | row_count [OFFSET offset]}
  • offset: Specifies the offset value of the starting row to be displayed. The offset value of the starting row of the result set is 0; it can be omitted and the default value is 0.
  • row_count: Specifies the number of records to be displayed. You can specify an integer greater than 0.
-- LIMIT clause can be used in prepared statement
PREPARE stmt FROM 'SELECT * FROM sales_tbl LIMIT ?, ?';
EXECUTE stmt USING 0, 10;

-- selecting rows with LIMIT clause
SELECT *
FROM sales_tbl
WHERE sales_amount > 100
LIMIT 5;
      dept_no  name                  sales_month  sales_amount
==============================================================
          201  'George'                        1           450
          201  'George'                        2           250
          201  'Laura'                         2           500
          301  'Max'                           1           300
          301  'Max'                           2           300
-- LIMIT clause can be used in subquery
SELECT t1.*
FROM (SELECT * FROM sales_tbl AS t2 WHERE sales_amount > 100 LIMIT 5) AS t1
LIMIT 1,3;

-- above query and below query shows the same result
SELECT t1.*
FROM (SELECT * FROM sales_tbl AS t2 WHERE sales_amount > 100 LIMIT 5) AS t1
LIMIT 3 OFFSET 1;
      dept_no  name                  sales_month  sales_amount
==============================================================
          201  'George'                        2           250
          201  'Laura'                         2           500
          301  'Max'                           1           300
Join Query

A join is a query that combines the rows of two or more tables or virtual tables (views). In a join query, a condition that compares the columns that are common in two or more tables is called a join condition. Rows are retrieved from each joined table, and are combined only when they satisfy the specified join condition.

A join query using an equality operator (=) is called an equi-join, and one without any join condition is called a cartesian product. Meanwhile, joining a single table is called a self join. In a self join, table ALIAS is used to distinguish columns, because the same table is used twice in the FROM clause.

A join that outputs only rows that satisfy the join condition from a joined table is called an inner or a simple join, whereas a join that outputs both rows that satisfy and do not satisfy the join condition from a joined table is called an outer join.

An outer join is divided into a left outer join which outputs all rows of the left table as a result(outputs NULL when the right table's columns don't match conditions), a right outer join which outputs all rows of the right table as a result(outputs NULL when the left table's columns don't match conditions) and a full outer join which outputs all rows of both tables. If there is no column value that corresponds to a table on one side in the result of an outer join query, all rows are returned as NULL.

FROM <table_specification> [{, <table_specification>
    | { <join_table_specification> | <join_table_specification2> } ...]

<table_specification> ::=
    <single_table_spec> [<correlation>] |
    <metaclass_specification> [<correlation>] |
    <subquery> <correlation> |
    TABLE (<expression>) <correlation>

<join_table_specification> ::=
    {
        [INNER | {LEFT | RIGHT} [OUTER]] JOIN |
        STRAIGHT_JOIN
     } <table_specification> ON <search_condition>

<join_table_specification2> ::=
            {
        CROSS JOIN |
        NATURAL [ LEFT | RIGHT ] JOIN
    } <table_specification>
  • <join_table_specification>
    • [INNER] JOIN: Used for inner join and requires join conditions.
    • {LEFT | RIGHT} [OUTER] JOIN: LEFT is used for a left outer join query, and RIGHT is for a right outer join query.
    • STRAIGHT_JOIN: (on changing)
  • <join_table_specification2>
    • CROSS JOIN: Used for cross join and requires no join conditions.
    • NATURAL [LEFT | RIGHT] JOIN: Used for natural join and join condition is not used. It operates in the equivalent same way to have a condition between columns equivalent of the same name .
Inner Join

The inner join requires join conditions. The INNER JOIN keyword can be omitted. When it is omitted, the table is separated by a comma (,). The ON join condition can be replaced with the WHERE condition.

The following example shows how to retrieve the years and host countries of the Olympic Games since 1950 where a world record has been set. The following query retrieves instances whose values of the host_year column in the history table are greater than 1950. The following two queries output the same result.

SELECT DISTINCT h.host_year, o.host_nation
FROM history h INNER JOIN olympic o ON h.host_year = o.host_year AND o.host_year > 1950;

SELECT DISTINCT h.host_year, o.host_nation
FROM history h, olympic o
WHERE h.host_year = o.host_year AND o.host_year > 1950;
    host_year  host_nation
===================================
         1968  'Mexico'
         1980  'U.S.S.R.'
         1984  'United States of America'
         1988  'Korea'
         1992  'Spain'
         1996  'United States of America'
         2000  'Australia'
         2004  'Greece'
Outer Join

CUBRID does not support full outer joins; it supports only left and right joins. Path expressions that include subqueries and sub-columns cannot be used in the join conditions of an outer join.

Join conditions of an outer join are specified in a different way from those of an inner join. In an inner join, join conditions can be expressed in the WHERE clause; in an outer join, they appear after the ON keyword within the FROM clause. Other retrieval conditions can be used in the WHERE or ON clause, but the retrieval result depends on whether the condition is used in the WHERE or ON clause.

The table execution order is fixed according to the order specified in the FROM clause. Therefore, when using an outer join, you should create a query statement in consideration of the table order. It is recommended to use standard statements using { LEFT | RIGHT } [ OUTER ] JOIN, because using an Oracle-style join query statements by specifying an outer join operator (+) in the WHERE clause, even if possible, might lead the execution result or plan in an unwanted direction.

The following example shows how to retrieve the years and host countries of the Olympic Games since 1950 where a world record has been set, but including the Olympic Games where any world records haven't been set in the result. This example can be expressed in the following right outer join query. In this example, all instances whose values of the host_year column in the history table are not greater than 1950 are also retrieved. All instances of host_nation are included because this is a right outer join. host_year that does not have a value is represented as NULL.

SELECT DISTINCT h.host_year, o.host_year, o.host_nation
FROM history h RIGHT OUTER JOIN olympic o ON h.host_year = o.host_year
WHERE o.host_year > 1950;
    host_year    host_year  host_nation
================================================
         NULL         1952  'Finland'
         NULL         1956  'Australia'
         NULL         1960  'Italy'
         NULL         1964  'Japan'
         NULL         1972  'Germany'
         NULL         1976  'Canada'
         1968         1968  'Mexico'
         1980         1980  'USSR'
         1984         1984  'USA'
         1988         1988  'Korea'
         1992         1992  'Spain'
         1996         1996  'USA'
         2000         2000  'Australia'
         2004         2004  'Greece'

A right outer join query can be converted to a left outer join query by switching the position of two tables in the FROM clause. The right outer join query in the previous example can be expressed as a left outer join query as follows:

SELECT DISTINCT h.host_year, o.host_year, o.host_nation
FROM olympic o LEFT OUTER JOIN history h ON h.host_year = o.host_year
WHERE o.host_year > 1950;
    host_year    host_year  host_nation
================================================
         NULL         1952  'Finland'
         NULL         1956  'Australia'
         NULL         1960  'Italy'
         NULL         1964  'Japan'
         NULL         1972  'Germany'
         NULL         1976  'Canada'
         1968         1968  'Mexico'
         1980         1980  'USSR'
         1984         1984  'USA'
         1988         1988  'Korea'
         1992         1992  'Spain'
         1996         1996  'USA'
         2000         2000  'Australia'
         2004         2004  'Greece'

Outer joins can also be represented by using (+) in the WHERE clause. The above example is a query that has the same meaning as the example using the LEFT OUTER JOIN. The (+) syntax is not ISO/ANSI standard, so it can lead to ambiguous situations. It is recommended to use the standard syntax LEFT OUTER JOIN (or RIGHT OUTER JOIN) if possible.

SELECT DISTINCT h.host_year, o.host_year, o.host_nation
FROM history h, olympic o
WHERE o.host_year = h.host_year(+) AND o.host_year > 1950;
    host_year    host_year  host_nation
================================================
         NULL         1952  'Finland'
         NULL         1956  'Australia'
         NULL         1960  'Italy'
         NULL         1964  'Japan'
         NULL         1972  'Germany'
         NULL         1976  'Canada'
         1968         1968  'Mexico'
         1980         1980  'USSR'
         1984         1984  'USA'
         1988         1988  'Korea'
         1992         1992  'Spain'
         1996         1996  'USA'
         2000         2000  'Australia'
         2004         2004  'Greece'

In the above examples, h.host_year=o.host_year is an outer join condition, and o.host_year > 1950 is a search condition. If the search condition is not written in the WHERE clause but in the ON clause, the meaning and the result will be different. The following query also includes instances whose values of o.host_year are not greater than 1950.

SELECT DISTINCT h.host_year, o.host_year, o.host_nation
FROM olympic o LEFT OUTER JOIN history h ON h.host_year = o.host_year AND o.host_year > 1950;
    host_year    host_year  host_nation
================================================
         NULL         1896  'Greece'
         NULL         1900  'France'
         NULL         1904  'USA'
         NULL         1908  'United Kingdom'
         NULL         1912  'Sweden'
         NULL         1920  'Belgium'
         NULL         1924  'France'
         NULL         1928  'Netherlands'
         NULL         1932  'USA'
         NULL         1936  'Germany'
         NULL         1948  'England'
         NULL         1952  'Finland'
         NULL         1956  'Australia'
         NULL         1960  'Italy'
         NULL         1964  'Japan'
         NULL         1972  'Germany'
         NULL         1976  'Canada'
         1968         1968  'Mexico'
         1980         1980  'USSR'
         1984         1984  'USA'
         1988         1988  'Korea'
         1992         1992  'Spain'
         1996         1996  'USA'
         2000         2000  'Australia'
         2004         2004  'Greece'

In the above example, LEFT OUTER JOIN should attach all rows to the result rows even if the left table's rows do not match to the condition; therefore, the left table's condition, "AND o.host_year > 1950" is ignored. But "WHERE o.host_year > 1950" is applied after the join operation is completed. Please consider that a condition after ON clause and a condition after WHERE clause can be applied differently in OUTER JOIN.

Cross Join

The cross join is a cartesian product, meaning that it is a combination of two tables, without any condition. For the cross join, the CROSS JOIN keyword can be omitted. When it is omitted, the table is separated by a comma (,).

The following example shows how to write cross join.

SELECT DISTINCT h.host_year, o.host_nation
FROM history h CROSS JOIN olympic o;

SELECT DISTINCT h.host_year, o.host_nation
FROM history h, olympic o;

The above two queries output the same results.

    host_year  host_nation
===================================
         1968  'Australia'
         1968  'Belgium'
         1968  'Canada'
         1968  'England'
         1968  'Finland'
         1968  'France'
         1968  'Germany'
...
         2004  'Spain'
         2004  'Sweden'
         2004  'USA'
         2004  'USSR'
         2004  'United Kingdom'

144 rows selected. (1.283548 sec) Committed.
Natural Join

When column names to be joined to each table are the same, that is, when you want to grant equivalent conditions between each column with the same name, a natural join, which can replace inner/outer join, can be used.

CREATE TABLE t1 (a int, b1 int);
CREATE TABLE t2 (a int, b2 int);

INSERT INTO t1 values(1,1);
INSERT INTO t1 values(3,3);
INSERT INTO t2 values(1,1);
INSERT INTO t2 values(2,2);

The below is an example of running NATURAL JOIN.

SELECT /*+ RECOMPILE*/ *
FROM t1 NATURAL JOIN t2;

Running the above query is the same as running the below query, and they display the same result.

SELECT /*+ RECOMPILE*/ *
FROM t1 INNER JOIN t2 ON t1.a=t2.a;
        a           b1            a           b2
================================================
        1            1            1            1

The below is an example of running NATURAL LEFT JOIN.

SELECT /*+ RECOMPILE*/ *
FROM t1 NATURAL LEFT JOIN t2;

Running the above query is the same as running the below query, and they display the same result.

SELECT /*+ RECOMPILE*/ *
FROM t1 LEFT JOIN t2 ON t1.a=t2.a;
            a           b1            a           b2
====================================================
            1            1            1            1
            3            3         NULL         NULL

The below is an example of running NATURAL RIGHT JOIN.

SELECT /*+ RECOMPILE*/ *
FROM t1 NATURAL RIGHT JOIN t2;

Running the above query is the same as running the below query, and they display the same result.

SELECT /*+ RECOMPILE*/ *
FROM t1 RIGHT JOIN t2 ON t1.a=t2.a;
            a           b1            a           b2
====================================================
            1            1            1            1
         NULL         NULL            2            2

(on changing)

STRAIGHT_JOIN

CUBRIDSUS-12814

Subquery

A subquery can be used wherever expressions such as SELECT or WHERE clause can be used. If the subquery is represented as an expression, it must return a single column; otherwise it can return multiple rows. Subqueries can be divided into single-row subquery and multiple-row subquery depending on how they are used.

Single-Row Subquery

A single-row subquery outputs a row that has a single column. If no row is returned by the subquery, the subquery expression has a NULL value. If the subquery is supposed to return more than one row, an error occurs.

The following example shows how to retrieve the history table as well as the host country where a new world record has been set. This example shows a single-row subquery used as an expression. In this example, the subquery returns host_nation values for the rows whose values of the host_year column in the olympic table are the same as those of the host_year column in the history table. If there are no values that meet the condition, the result of the subquery is NULL.

SELECT h.host_year, (SELECT host_nation FROM olympic o WHERE o.host_year=h.host_year) AS host_nation,
       h.event_code, h.score, h.unit
FROM history h;
    host_year  host_nation            event_code  score                 unit
============================================================================================
    2004       'Greece'               20283       '07:53.0'             'time'
    2004       'Greece'               20283       '07:53.0'             'time'
    2004       'Greece'               20281       '03:57.0'             'time'
    2004       'Greece'               20281       '03:57.0'             'time'
    2004       'Greece'               20281       '03:57.0'             'time'
    2004       'Greece'               20281       '03:57.0'             'time'
    2004       'Greece'               20326       '210'                 'kg'
    2000       'Australia'            20328       '225'                 'kg'
    2004       'Greece'               20331       '237.5'               'kg'
...
Multiple-Row Subquery

The multiple-row subquery returns one or more rows that contain the specified column. The result of the multiple-row subquery can create SET, MULTISET and LIST) by using an appropriate keyword.

The following example shows how to retrieve nations, capitals and host cities for Olympic Game all together in the nation table. In this example, the subquery result is used to create a List from the values of the host_city column in the olympic table. This query returns name and capital value for nation table, as well as a set that contains host_city values of the olympic table with host_nation value. If the name value is an empty set in the query result, it is excluded. If there is no olympic table that has the same value as the name, an empty set is returned.

SELECT name, capital, list(SELECT host_city FROM olympic WHERE host_nation = name) AS host_cities
FROM nation;
  name                      capital                 host_cities
==================================================================
  'Somalia'                   'Mogadishu'           {}
  'Sri Lanka'                 'Sri Jayewardenepura Kotte' {}
  'Sao Tome & Principe'       'Sao Tome'            {}
  ...
  'U.S.S.R.'                  'Moscow'              {'Moscow'}
  'Uruguay'                   'Montevideo'          {}
  'United States of America'  'Washington.D.C'      {'Atlanta ', 'St. Louis', 'Los Angeles', 'Los Angeles'}
  'Uzbekistan'                'Tashkent'            {}
  'Vanuatu'                   'Port Vila'           {}

Such multiple-row subquery expressions can be used anywhere a collection-type value expression is allowed. However, they cannot be used where a collection-type constant value is required as in the DEFAULT specification in the class attribute definition.

If the ORDER BY clause is not used explicitly in the subquery, the order of the multiple-row query result is not set. Therefore, the order of the multiple-row subquery result that creates LIST must be specified by using the ORDER BY clause.

VALUES

The VALUES clause prints out the values of rows defined in the expression. In most cases, the VALUES clause is used for creating a constant table, however, the clause itself can be used. When one or more rows are specified in the VALUES clause, all rows should have the same number of the elements.

VALUES (expression[, ...])[, ...]
  • expression : An expression enclosed within parentheses stands for one row in a table.

The VALUES clause can be used to express the UNION ALL query, which consists of constant values in a simpler way. For example, the following query can be executed.

VALUES (1 AS col1, 'first' AS col2), (2, 'second'), (3, 'third'), (4, 'fourth');

The above query prints out the following result.

SELECT 1 AS col1, 'first' AS col2
UNION ALL
SELECT 2, 'second'
UNION ALL
SELECT 3, 'third'
UNION ALL
SELECT 4, 'fourth';

The following example shows use of the VALUES clause with multiple rows in the INSERT statement.

INSERT INTO athlete (code, name, gender, nation_code, event)
VALUES ('21111', 'Jang Mi-Ran ', 'F', 'KOR', 'Weight-lifting'),
       ('21112', 'Son Yeon-Jae ', 'F', 'KOR', 'Rhythmic gymnastics');

The following example shows how to use subquery in the FROM statement.

SELECT a.*
FROM athlete a, (VALUES ('Jang Mi-Ran', 'F'), ('Son Yeon-Jae', 'F')) AS t(name, gender)
WHERE a.name=t.name AND a.gender=t.gender;
         code  name                gender   nation_code        event
=====================================================================================================
        21111  'Jang Mi-Ran'       'F'      'KOR'              'Weight-lifting'
        21112  'Son Yeon-Jae'      'F'      'KOR'              'Rhythmic gymnastics'
FOR UPDATE

The FOR UPDATE clause can be used in SELECT statements for locking rows returned by the statement for a later UPDATE/DELETE.

SELECT ... [FOR UPDATE [OF <spec_name_comma_list>]]

    <spec_name_comma_list> ::= <spec_name> [, <spec_name>, ... ]
        <spec_name> ::= table_name | view_name
  • <spec_name_comma_list>: A list of table/view names referenced from the FROM clause.

Only table/view referenced in <spec_name_comma_list> will be locked. If the <spec_name_comma_list> is missing but FOR UPDATE is present then we assume that all tables/views from the FROM clause of the SELECT statement are referenced. Rows are locked using X_LOCK.

Note

Restrictions

  • It cannot be used in subqueries (but it can reference subqueries).
  • It cannot be used in a statement that has GROUP BY, DISTINCT or aggregate functions.
  • It cannot reference UNIONs.

The following shows how to use SELECT ... FOR UPDATE statements.

CREATE TABLE t1(i INT);
INSERT INTO t1 VALUES (1), (2), (3), (4), (5);

CREATE TABLE t2(i INT);
INSERT INTO t2 VALUES (1), (2), (3), (4), (5);
CREATE INDEX idx_t2_i ON t2(i);

CREATE VIEW v12 AS SELECT t1.i AS i1, t2.i AS i2 FROM t1 INNER JOIN t2 ON t1.i=t2.i;

SELECT * FROM t1 ORDER BY 1 FOR UPDATE;
SELECT * FROM t1 ORDER BY 1 FOR UPDATE OF t1;
SELECT * FROM t1 INNER JOIN t2 ON t1.i=t2.i ORDER BY 1 FOR UPDATE OF t1, t2;

SELECT * FROM t1 INNER JOIN (SELECT * FROM t2 WHERE t2.i > 0) r ON t1.i=r.i WHERE t1.i > 0 ORDER BY 1 FOR UPDATE;

SELECT * FROM v12 ORDER BY 1 FOR UPDATE;
SELECT * FROM t1, (SELECT * FROM v12, t2 WHERE t2.i > 0 AND t2.i=v12.i1) r WHERE t1.i > 0 AND t1.i=r.i ORDER BY 1 FOR UPDATE OF r;
Hierarchical Query

Hierarchical Query is used to obtain a set of data organized in a hierarchy. The START WITH ... CONNECT BY clause is used in combination with the SELECT clause in the following form.

You can execute the queries by changing the order of two clauses like CONNECT BY ... START WITH.

SELECT column_list
FROM table_joins | tables
[WHERE join_conditions and/or filtering_conditions]
[hierarchical_clause]

hierarchical_clause :
    [START WITH condition] CONNECT BY [NOCYCLE] condition
    | CONNECT BY [NOCYCLE] condition [START WITH condition]
START WITH Clause

The START WITH clause will filter the rows from which the hierarchy will start. The rows that satisfy the START WITH condition will be the root nodes of the hierarchy. If START WITH is omitted, then all the rows will be considered as root nodes.

Note

If START WITH clause is omitted or the rows that satisfy the START WITH condition does not exist, all of rows in the table are considered as root nodes; which means that hierarchy relationship of sub rows which belong each root is searched. Therefore, some of results can be duplicate.

CONNECT BY Clause
  • PRIOR : The CONNECT BY condition is tested for a pair of rows. If it evaluates to true, the two rows satisfy the parent-child relationship of the hierarchy. We need to specify the columns that are used from the parent row and the columns that are used from the child row. We can use the PRIOR operator when applied to a column, which will refer to the value of the parent row for that column. If PRIOR is not used for a column, the value in the child row is used.

  • NOCYCLE : In some cases, the resulting rows of the table joins may contain cycles, depending on the CONNECT BY condition. Because cycles cause an infinite loop in the result tree construction, CUBRID detects them and either returns an error doesn't expand the branches beyond the point where a cycle is found (if the NOCYCLE keyword is specified). This keyword may be specified after the CONNECT BY keywords. It makes CUBRID run a statement even if the processed data contains cycles.

    If a CONNECT BY statement causes a cycle at runtime and the NOCYCLE keyword is not specified, CUBRID will return an error and the statement will be canceled. When specifying the NOCYCLE keyword, if CUBRID detects a cycle while processing a hierarchy node, it will set the CONNECT_BY_ISCYCLE attribute for that node to the value of 1 and it will stop further expansion of that branch.

The following example shows how to execute hierarchical query.

-- Creating tree table and then inserting data
CREATE TABLE tree(ID INT, MgrID INT, Name VARCHAR(32), BirthYear INT);

INSERT INTO tree VALUES (1,NULL,'Kim', 1963);
INSERT INTO tree VALUES (2,NULL,'Moy', 1958);
INSERT INTO tree VALUES (3,1,'Jonas', 1976);
INSERT INTO tree VALUES (4,1,'Smith', 1974);
INSERT INTO tree VALUES (5,2,'Verma', 1973);
INSERT INTO tree VALUES (6,2,'Foster', 1972);
INSERT INTO tree VALUES (7,6,'Brown', 1981);

-- Executing a hierarchical query with CONNECT BY clause
SELECT id, mgrid, name
FROM tree
CONNECT BY PRIOR id=mgrid
ORDER BY id;
   id        mgrid  name
========================================
    1         NULL  'Kim'
    2         NULL  'Moy'
    3            1  'Jonas'
    3            1  'Jonas'
    4            1  'Smith'
    4            1  'Smith'
    5            2  'Verma'
    5            2  'Verma'
    6            2  'Foster'
    6            2  'Foster'
    7            6  'Brown'
    7            6  'Brown'
    7            6  'Brown'
-- Executing a hierarchical query with START WITH clause
SELECT id, mgrid, name
FROM tree
START WITH mgrid IS NULL
CONNECT BY prior id=mgrid
ORDER BY id;
   id        mgrid  name
========================================
    1         NULL  'Kim'
    2         NULL  'Moy'
    3            1  'Jonas'
    4            1  'Smith'
    5            2  'Verma'
    6            2  'Foster'
    7            6  'Brown'
Hierarchical Query Execution
Hierarchical Query for Table Join

When target table is joined in SELECT statement, WHERE clause can include not only searching conditions but also joining conditions. At this time, CUBRID applies the joining conditions in WHERE clause at first, then conditions in CONNECT BY caluse; at last, the left searching conditions.

When specifying joining conditions and searching conditions together in WHERE clause, joining conditions can be applied as searching conditions even if there was no intention; so the operating order can be different; therefore, we recommend that you specify the table joining conditions in FROM clause, not in WHERE conditions.

Query Results

The resulting rows of the table joins are filtered according to the START WITH condition to obtain the root nodes for the hierarchy. If no START WITH condition is specified, then all the rows resulting from the table joins will be considered as root nodes. After the root nodes are obtained, CUBRID will select the child rows for the root nodes. These are all nodes from the table joins that respect the CONNECT BY condition. This step will be repeated for the child nodes to determine their child nodes and so on until no more child nodes can be added.

In addition, CUBRID evaluates the CONNECT BY clause first and all the rows of the resulting hierarchy tress by using the filtering condition in the WHERE clause.

The example illustrates how joins can be used in CONNECT BY queries.

-- Creating tree2 table and then inserting data
CREATE TABLE tree2(id int, treeid int, job varchar(32));

INSERT INTO tree2 VALUES(1,1,'Partner');
INSERT INTO tree2 VALUES(2,2,'Partner');
INSERT INTO tree2 VALUES(3,3,'Developer');
INSERT INTO tree2 VALUES(4,4,'Developer');
INSERT INTO tree2 VALUES(5,5,'Sales Exec.');
INSERT INTO tree2 VALUES(6,6,'Sales Exec.');
INSERT INTO tree2 VALUES(7,7,'Assistant');
INSERT INTO tree2 VALUES(8,null,'Secretary');

-- Executing a hierarchical query onto table joins
SELECT t.id,t.name,t2.job,level
FROM tree t INNER JOIN tree2 t2 ON t.id=t2.treeid
START WITH t.mgrid is null
CONNECT BY prior t.id=t.mgrid
ORDER BY t.id;
   id  name                  job                         level
==============================================================
    1  'Kim'                 'Partner'                       1
    2  'Moy'                 'Partner'                       1
    3  'Jonas'               'Developer'                     2
    4  'Smith'               'Developer'                     2
    5  'Verma'               'Sales Exec.'                   2
    6  'Foster'              'Sales Exec.'                   2
    7  'Brown'               'Assistant'                     3
Ordering Data with the Hierarchical Query

The ORDER SIBLINGS BY clause will cause the ordering of the rows while preserving the hierarchy ordering so that the child nodes with the same parent will be stored according to the column list.

ORDER SIBLINGS BY col_1 [ASC|DESC] [, col_2 [ASC|DESC] [...[, col_n [ASC|DESC]]...]]

The following example shows how to display information about seniors and subordinates in a company in the order of birth year.

The result with hierarchical query shows parent and child nodes in a row according to the column list specified in ORDER SIBLINGS BY statement by default. Sibling nodes that share the same parent node have outputted in a specified order.

-- Outputting a parent node and its child nodes, which sibling nodes that share the same parent are sorted in the order of birthyear.
SELECT id, mgrid, name, birthyear, level
FROM tree
START WITH mgrid IS NULL
CONNECT BY PRIOR id=mgrid
ORDER SIBLINGS BY birthyear;
   id        mgrid  name                    birthyear        level
==================================================================
    2         NULL  'Moy'                        1958            1
    6            2  'Foster'                     1972            2
    7            6  'Brown'                      1981            3
    5            2  'Verma'                      1973            2
    1         NULL  'Kim'                        1963            1
    4            1  'Smith'                      1974            2
    3            1  'Jonas'                      1976            2

The following example shows how to display information about seniors and subordinates in a company in the order of joining. For the same level, the employee ID numbers are assigned in the order of joining. id indicates employee ID numbers (parent and child nodes) and mgrid indicates the employee ID numbers of their seniors.

-- Outputting a parent node and its child nodes, which sibling nodes that share the same parent are sorted in the order of id.
SELECT id, mgrid, name, LEVEL
FROM tree
START WITH mgrid IS NULL
CONNECT BY PRIOR id=mgrid
ORDER SIBLINGS BY id;
   id        mgrid  name                        level
=====================================================
    1         NULL  'Kim'                           1
    3            1  'Jonas'                         2
    4            1  'Smith'                         2
    2         NULL  'Moy'                           1
    5            2  'Verma'                         2
    6            2  'Foster'                        2
    7            6  'Brown'                         3
Pseudo Columns for Hierarchical Query
LEVEL

LEVEL is a pseudocolumn representing depth of hierarchical queries. The LEVEL of root node is 1 and the LEVEL of its child node is 2.

The LEVEL (pseudocolumn) can be used in the WHERE clause, ORDER BY clause, and GROUP BY ... HAVING clause of the SELECT statement. And it can also be used in the statement using aggregate functions.

The following example shows how to retrieve the LEVEL value to check level of node.

-- Checking the LEVEL value
SELECT id, mgrid, name, LEVEL
FROM tree
WHERE LEVEL=2
START WITH mgrid IS NULL
CONNECT BY PRIOR id=mgrid
ORDER BY id;
   id        mgrid  name                        level
=====================================================
    3            1  'Jonas'                         2
    4            1  'Smith'                         2
    5            2  'Verma'                         2
    6            2  'Foster'                        2

The following example shows how to add LEVEL conditions after the CONNECT BY statement.

SELECT LEVEL FROM db_root CONNECT BY LEVEL <= 10;
        level
=============
            1
            2
            3
            4
            5
            6
            7
            8
            9
           10

Note that the format of "CONNECT BY expr(LEVEL) < expr", for example "CONNECT BY LEVEL +1 < 5") is not supported.

CONNECT_BY_ISLEAF

CONNECT_BY_ISLEAF is a pseudocolumn representing that the result of hierarchical query is leaf node. If the current row is a leaf node, it returns 1; otherwise, it returns 0.

The following example shows how to retrieve the CONNECT_BY_ISLEAF value to check whether it is a leaf node or not.

-- Checking a CONNECT_BY_ISLEAF value
SELECT id, mgrid, name, CONNECT_BY_ISLEAF
FROM tree
START WITH mgrid IS NULL
CONNECT BY PRIOR id=mgrid
ORDER BY id;
  id        mgrid  name                  connect_by_isleaf
=============================================================
   1         NULL  'Kim'                                 0
   2         NULL  'Moy'                                 0
   3            1  'Jonas'                               1
   4            1  'Smith'                               1
   5            2  'Verma'                               1
   6            2  'Foster'                              0
   7            6  'Brown'                               1
CONNECT_BY_ISCYCLE

CONNECT_BY_ISCYCLE is a pseudocolumn representing that a cycle was detected while processing the node, meaning that a child was also found to be an ancestor. A value of 1 for a row means a cycle was detected; the pseudo-column's value is 0, otherwise.

The CONNECT_BY_ISCYCLE pseudo-column can be used in the WHERE, ORDER BY and GROUP BY ... HAVING clauses of the SELECT statement. It can also be used in aggregate functions.

Note

This pseudocolumn is available only when the NOCYCLE keyword is used in the statement.

The following example shows how to retrieve the CONNECT_BY_ISCYCE value to check a row that occurs loop.

-- Creating a tree_cycle table and inserting data
CREATE TABLE tree_cycle(ID INT, MgrID INT, Name VARCHAR(32));

INSERT INTO tree_cycle VALUES (1,NULL,'Kim');
INSERT INTO tree_cycle VALUES (2,11,'Moy');
INSERT INTO tree_cycle VALUES (3,1,'Jonas');
INSERT INTO tree_cycle VALUES (4,1,'Smith');
INSERT INTO tree_cycle VALUES (5,3,'Verma');
INSERT INTO tree_cycle VALUES (6,3,'Foster');
INSERT INTO tree_cycle VALUES (7,4,'Brown');
INSERT INTO tree_cycle VALUES (8,4,'Lin');
INSERT INTO tree_cycle VALUES (9,2,'Edwin');
INSERT INTO tree_cycle VALUES (10,9,'Audrey');
INSERT INTO tree_cycle VALUES (11,10,'Stone');

-- Checking a CONNECT_BY_ISCYCLE value
SELECT id, mgrid, name, CONNECT_BY_ISCYCLE
FROM tree_cycle
START WITH name in ('Kim', 'Moy')
CONNECT BY NOCYCLE PRIOR id=mgrid
ORDER BY id;
id        mgrid  name        connect_by_iscycle
==================================================
 1         NULL  'Kim'                        0
 2           11  'Moy'                        0
 3            1  'Jonas'                      0
 4            1  'Smith'                      0
 5            3  'Verma'                      0
 6            3  'Foster'                     0
 7            4  'Brown'                      0
 8            4  'Lin'                        0
 9            2  'Edwin'                      0
10            9  'Audrey'                     0
11           10  'Stone'                      1
Operators for Hierarchical Query
CONNECT_BY_ROOT

The CONNECTION_BY_ROOT operator returns the value of a root row as a column value. This operator can be used in the WHERE and ORDER BY clauses of the SELECT statement.

The following example shows how to retrieve the root row's id value.

-- Checking the id value of a root row for each row
SELECT id, mgrid, name, CONNECT_BY_ROOT id
FROM tree
START WITH mgrid IS NULL
CONNECT BY PRIOR id=mgrid
ORDER BY id;
   id        mgrid  name                   connect_by_root id
=============================================================
    1         NULL  'Kim'                                   1
    2         NULL  'Moy'                                   2
    3            1  'Jonas'                                 1
    4            1  'Smith'                                 1
    5            2  'Verma'                                 2
    6            2  'Foster'                                2
    7            6  'Brown'                                 2
PRIOR

The PRIOR operator returns the value of a parent row as a column value and returns NULL for the root row. This operator can be used in the WHERE, ORDER BY and CONNECT BY clauses of the SELECT statement.

The following example shows how to retrieve the parent row's id value.

-- Checking the id value of a parent row for each row
SELECT id, mgrid, name, PRIOR id as "prior_id"
FROM tree
START WITH mgrid IS NULL
CONNECT BY PRIOR id=mgrid
ORDER BY id;
   id        mgrid  name                     prior_id
=====================================================
    1         NULL  'Kim'                        NULL
    2         NULL  'Moy'                        NULL
    3            1  'Jonas'                         1
    4            1  'Smith'                         1
    5            2  'Verma'                         2
    6            2  'Foster'                        2
    7            6  'Brown'                         6
Functions for Hierarchical Query
SYS_CONNECT_BY_PATH

The SYS_CONNECT_BY_PATH function returns the hierarchical path from a root to the specified row in string. The column and separator specified as an argument must be a character type. Each path separated by specified separator will be displayed consecutively. This function can be used in the WHERE and ORDER BY clauses of the SELECT statement.

SYS_CONNECT_BY_PATH (column_name, separator_char)

The following example shows how to retrieve path from a root to the specified row.

-- Executing a hierarchical query with SYS_CONNECT_BY_PATH function
SELECT id, mgrid, name, SYS_CONNECT_BY_PATH(name,'/') as [hierarchy]
FROM tree
START WITH mgrid IS NULL
CONNECT BY PRIOR id=mgrid
ORDER BY id;
   id        mgrid  name                  hierarchy
==============================================================
    1         NULL  'Kim'                 '/Kim'
    2         NULL  'Moy'                 '/Moy'
    3            1  'Jonas'               '/Kim/Jonas'
    4            1  'Smith'               '/Kim/Smith'
    5            2  'Verma'               '/Moy/Verma'
    6            2  'Foster'              '/Moy/Foster'
    7            6  'Brown'               '/Moy/Foster/Brown'
Examples of Hierarchical Query

The examples in this page shows how to write hierarchical queries by specifying the CONNECT BY clause within the SELECT statement.

A table that have relationship with recursive reference is create and the table consists of two columns named ID and ParentID; assume that ID is a primary key for the table and ParentID is a foreign key for the same table. In this context, the root node will have a ParentID value of NULL.

Once a table is create, you can get the entire data with hierarchical structure and a value of LEVEL by using the UNION ALL as shown below.

CREATE TABLE tree_table (ID int PRIMARY KEY, ParentID int, name VARCHAR(128));

INSERT INTO tree_table VALUES (1,NULL,'Kim');
INSERT INTO tree_table VALUES (2,1,'Moy');
INSERT INTO tree_table VALUES (3,1,'Jonas');
INSERT INTO tree_table VALUES (4,1,'Smith');
INSERT INTO tree_table VALUES (5,3,'Verma');
INSERT INTO tree_table VALUES (6,3,'Foster');
INSERT INTO tree_table VALUES (7,4,'Brown');
INSERT INTO tree_table VALUES (8,4,'Lin');
INSERT INTO tree_table VALUES (9,2,'Edwin');
INSERT INTO tree_table VALUES (10,9,'Audrey');
INSERT INTO tree_table VALUES (11,10,'Stone');

SELECT L1.ID, L1.ParentID, L1.name, 1 AS [Level]
    FROM tree_table AS L1
    WHERE L1.ParentID IS NULL
UNION ALL
SELECT L2.ID, L2.ParentID, L2.name, 2 AS [Level]
    FROM tree_table AS L1
        INNER JOIN tree_table AS L2 ON L1.ID=L2.ParentID
    WHERE L1.ParentID IS NULL
UNION ALL
SELECT L3.ID, L3.ParentID, L3.name, 3 AS [Level]
    FROM tree_table AS L1
        INNER JOIN tree_table AS L2 ON L1.ID=L2.ParentID
        INNER JOIN tree_table AS L3 ON L2.ID=L3.ParentID
    WHERE L1.ParentID IS NULL
UNION ALL
SELECT L4.ID, L4.ParentID, L4.name, 4 AS [Level]
    FROM tree_table AS L1
        INNER JOIN tree_table AS L2 ON L1.ID=L2.ParentID
        INNER JOIN tree_table AS L3 ON L2.ID=L3.ParentID
        INNER JOIN tree_table AS L4 ON L3.ID=L4.ParentID
    WHERE L1.ParentID IS NULL;
   ID     ParentID  name                        Level
=====================================================
    1         NULL  'Kim'                           1
    2            1  'Moy'                           2
    3            1  'Jonas'                         2
    4            1  'Smith'                         2
    9            2  'Edwin'                         3
    5            3  'Verma'                         3
    6            3  'Foster'                        3
    7            4  'Brown'                         3
    8            4  'Lin'                           3
   10            9  'Audrey'                        4

Because you do not know how many levels exist in the data, you can rewrite the query above as a stored procedure that loops until no new row is retrieved.

However, the hierarchical structure should be checked every step while looping, specify the CONNECT BY clause within the SELECT statement as follows; the example below shows how to get the entire data with hierarchical structure and the level of each row in the hierarchy.

SELECT ID, ParentID, name, Level
FROM tree_table
START WITH ParentID IS NULL
CONNECT BY ParentID=PRIOR ID;
   ID     ParentID  name                        level
=====================================================
    1         NULL  'Kim'                           1
    2            1  'Moy'                           2
    9            2  'Edwin'                         3
   10            9  'Audrey'                        4
   11           10  'Stone'                         5
    3            1  'Jonas'                         2
    5            3  'Verma'                         3
    6            3  'Foster'                        3
    4            1  'Smith'                         2
    7            4  'Brown'                         3
    8            4  'Lin'                           3

You can specify NOCYCLE to prevent an error from occurring as follows. When you run the following query, a loop does not appear; therefore, the result is the same as the above.

SELECT ID, ParentID, name, Level
FROM tree_table
START WITH ParentID IS NULL
CONNECT BY NOCYCLE ParentID=PRIOR ID;

CUBRID judges that this hierarchical query has a loop if the same row is found during searching process on the query. The below is an example that the loop exists; we define NOCYCLE to end the additional searching process if a loop exists.

CREATE TABLE tbl(seq INT, id VARCHAR(10), parent VARCHAR(10));

INSERT INTO tbl VALUES (1, 'a', null);
INSERT INTO tbl VALUES (2, 'b', 'a');
INSERT INTO tbl VALUES (3, 'b', 'c');
INSERT INTO tbl VALUES (4, 'c', 'b');
INSERT INTO tbl VALUES (5, 'c', 'b');

SELECT seq, id, parent, LEVEL,
  CONNECT_BY_ISCYCLE AS iscycle,
  CAST(SYS_CONNECT_BY_PATH(id,'/') AS VARCHAR(10)) AS idpath
FROM tbl
START WITH PARENT is NULL
CONNECT BY NOCYCLE PARENT = PRIOR id;
    seq  id           parent       level      iscycle  idpath
=============================================================================
      1  'a'          NULL             1            0  '/a'
      2  'b'          'a'              2            0  '/a/b'
      4  'c'          'b'              3            0  '/a/b/c'
      3  'b'          'c'              4            1  '/a/b/c/b'
      5  'c'          'b'              5            1  '/a/b/c/b/c'
      5  'c'          'b'              3            0  '/a/b/c'
      3  'b'          'c'              4            1  '/a/b/c/b'
      4  'c'          'b'              5            1  '/a/b/c/b/c'

The belows shows to output dates of March, 2013(201303) with a hierarchical query.

SELECT TO_CHAR(base_month + lvl -1, 'YYYYMMDD') h_date
FROM (
    SELECT LEVEL lvl, base_month
    FROM (
            SELECT TO_DATE('201303', 'YYYYMM') base_month FROM db_root
    )
    CONNECT BY LEVEL <= LAST_DAY(base_month) - base_month + 1
);
h_date
======================
  '20130301'
  '20130302'
  '20130303'
  '20130304'
  '20130305'
  '20130306'
  '20130307'
  '20130308'
  '20130309'
  '20130310'
  '20130311'
  '20130312'
  '20130313'
  '20130314'
  '20130315'
  '20130316'
  '20130317'
  '20130318'
  '20130319'
  '20130320'
  '20130321'
  '20130322'
  '20130323'
  '20130324'
  '20130325'
  '20130326'
  '20130327'
  '20130328'
  '20130329'
  '20130330'
  '20130331'

31 rows selected. (0.066175 sec) Committed.
Performance of Hierarchical Query

Although this form is shorter and clearer, please keep in mind that it has its limitations regarding speed.

If the result of the query contains all the rows of the table, the CONNECT BY form might be slower as it has to do additional processing (such as cycle detection, pseudo-column bookkeeping and others). However, if the result of the query only contains a part of the table rows, the CONNECT BY form might be faster.

For example, if we have a table with 20,000 records and we want to retrieve a sub-tree of roughly 1,000 records, a SELECT statement with a START WITH ... CONNECT BY clause will run up to 30% faster than an equivalent UNION ALL with SELECT statements.

INSERT

You can insert a new record into a table in a database by using the INSERT statement. CUBRID supports INSERT ... VALUES, INSERT ... SET and INSERT ... SELECT statements.

INSERT ... VALUES and INSERT ... SET statements are used to insert a new record based on the value that is explicitly specified while the INSERT ... SELECT statement is used to insert query result records obtained from different tables. Use the INSERT VALUES or INSERT ... SELECT statement to insert multiple rows by using the single INSERT statement.

<INSERT ... VALUES statement>
INSERT [INTO] table_name [(column_name, ...)]
    {VALUES | VALUE}({expr | DEFAULT}, ...)[,({expr | DEFAULT}, ...),...]
    [ON DUPLICATE KEY UPDATE column_name = expr, ... ]
INSERT [INTO] table_name DEFAULT [ VALUES ]

<INSERT ... SET statement>
INSERT [INTO] table_name
    SET column_name = {expr | DEFAULT}[, column_name = {expr | DEFAULT},...]
    [ON DUPLICATE KEY UPDATE column_name = expr, ... ]

<INSERT ... SELECT statement>
INSERT [INTO] table_name [(column_name, ...)]
    SELECT...
    [ON DUPLICATE KEY UPDATE column_name = expr, ... ]
  • table_name: Specifies the name of the target table into which you want to insert a new record.
  • column_name: Specifies the name of the column into which you want to insert the value. If you omit to specify the column name, it is considered that all columns defined in the table have been specified. Therefore, you must specify the values for all columns next to the VALUES keyword. If you do not specify all the columns defined in the table, a DEFAULT value is assigned to the non-specified columns; if the DEFAULT value is not defined, a NULL value is assigned.
  • expr | DEFAULT: Specifies values that correspond to the columns next to the VALUES keyword. Expressions or the DEFAULT keyword can be specified as a value. At this time, the order and number of the specified column list must correspond to the column value list. The column value list for a single record is described in parentheses.
  • DEFAULT: You can use the DEFAULT keyword to specify a default value as the column value. If you specify DEFAULT in the column value list next to the VALUES keyword, a default value column is stored for the given column: if you specify DEFAULT before the VALUES keyword, default values are stored for all columns in the table. NULL is stored for the column whose default value has not been defined.
  • ON DUPLICATE KEY UPDATE: In case constraints are violated because a duplicated value for a column where PRIMARY KEY or UNIQUE attribute is defined is inserted, the value that makes constraints violated is changed into a specific value by performing the action specified in the ON DUPLICATE KEY UPDATE statement.
CREATE TABLE a_tbl1(
    id INT UNIQUE,
    name VARCHAR,
    phone VARCHAR DEFAULT '000-0000'
);

--insert default values with DEFAULT keyword before VALUES
INSERT INTO a_tbl1 DEFAULT VALUES;

--insert multiple rows
INSERT INTO a_tbl1 VALUES (1,'aaa', DEFAULT),(2,'bbb', DEFAULT);

--insert a single row specifying column values for all
INSERT INTO a_tbl1 VALUES (3,'ccc', '333-3333');

--insert two rows specifying column values for only
INSERT INTO a_tbl1(id) VALUES (4), (5);

--insert a single row with SET clauses
INSERT INTO a_tbl1 SET id=6, name='eee';
INSERT INTO a_tbl1 SET id=7, phone='777-7777';

SELECT * FROM a_tbl1;
           id  name                  phone
=========================================================
         NULL  NULL                  '000-0000'
            1  'aaa'                 '000-0000'
            2  'bbb'                 '000-0000'
            3  'ccc'                 '333-3333'
            4  NULL                  '000-0000'
            5  NULL                  '000-0000'
            6  'eee'                 '000-0000'
            7  NULL                  '777-7777'
INSERT INTO a_tbl1 SET id=6, phone='000-0000'
ON DUPLICATE KEY UPDATE phone='666-6666';
SELECT * FROM a_tbl1 WHERE id=6;
           id  name                  phone
=========================================================
            6  'eee'                 '666-6666'
INSERT INTO a_tbl1 SELECT * FROM a_tbl1 WHERE id=7 ON DUPLICATE KEY UPDATE name='ggg';
SELECT * FROM a_tbl1 WHERE id=7;
           id  name                  phone
=========================================================
            7  'ggg'                 '777-7777'

In INSERT ... SET syntax, the evaluation of an assignment expression is performed from left to right. If the column value is not specified, then the default value is assigned. If there is no default value, NULL is assigned.

CREATE TABLE tbl (a INT, b INT, c INT);
INSERT INTO tbl SET a=1, b=a+1, c=b+2;
SELECT * FROM tbl;
        a            b            c
===================================
        1            2            4

In the above example, b's value will be 2 and c's value will be 4 since a's value is 1.

CREATE TABLE tbl2 (a INT, b INT, c INT);
INSERT INTO tbl2 SET a=b+1, b=1, c=b+2;

In the above example, a's value will be NULL since b's value is not specified yet when assigning a's value.

SELECT * FROM tbl2;
        a            b            c
===================================
     NULL            1            3
CREATE TABLE tbl3 (a INT, b INT default 10, c INT);
INSERT INTO tbl3 SET a=b+1, b=1, c=b+2;

In the above example, a's value will be 11 since b's value is not specified yet and b's default is 10.

SELECT * FROM tbl3;
        a            b            c
===================================
       11            1            3
INSERT ... SELECT Statement

If you use the SELECT query in the INSERT statement, you can insert query results which satisfy the specified retrieval condition from one or many tables to the target table.

INSERT [INTO] table_name [(column_name, ...)]
    SELECT...
    [ON DUPLICATE KEY UPDATE column_name = expr, ... ]

The SELECT statement can be used in place of the VALUES keyword, or be included as a subquery in the column value list next to VALUES. If you specify the SELECT statement in place of the VALUES keyword, you can insert multiple query result records into the column of the table at once. However, there should be only one query result record if the SELECT statement is specified in the column value list.

--creating an empty table which schema replicated from a_tbl1
CREATE TABLE a_tbl2 LIKE a_tbl1;

--inserting multiple rows from SELECT query results
INSERT INTO a_tbl2 SELECT * FROM a_tbl1 WHERE id IS NOT NULL;

--inserting column value with SELECT subquery specified in the value list
INSERT INTO a_tbl2 VALUES(8, SELECT name FROM a_tbl1 WHERE name <'bbb', DEFAULT);

SELECT * FROM a_tbl2;
           id  name                  phone
=========================================================
            1  'aaa'                 '000-0000'
            2  'bbb'                 '000-0000'
            3  'ccc'                 '333-3333'
            4  NULL                  '000-0000'
            5  NULL                  '000-0000'
            6  'eee'                 '000-0000'
            7  NULL                  '777-7777'
            8  'aaa'                 '000-0000'
ON DUPLICATE KEY UPDATE Clause

In a situation in which a duplicate value is inserted into a column for which the UNIQUE index or the PRIMARY KEY constraint has been set, you can update to a new value by specifying the ON DUPLICATE KEY UPDATE clause in the INSERT statement.

Note

  • If PRIMARY KEY and UNIQUE or multiple UNIQUE constraints exist on a table together, constraint violation can happen by one of them; so in this case, ON DUPLICATE KEY UPDATE clause is not recommended.
  • Even if UPDATE is executed after failing executing INSERT, AUTO_INCREMENT value which is increased once cannot be rolled back into the previous value.
<INSERT ... VALUES statement>
<INSERT ... SET statement>
<INSERT ... SELECT statement>
    INSERT ...
    [ON DUPLICATE KEY UPDATE column_name = expr, ... ]
  • column_name = expr: Specifies the name of the column whose value you want to change next to ON DUPLICATE KEY UPDATE and a new column value by using the equal sign.
--creating a new table having the same schema as a_tbl1
CREATE TABLE a_tbl3 LIKE a_tbl1;
INSERT INTO a_tbl3 SELECT * FROM a_tbl1 WHERE id IS NOT NULL and name IS NOT NULL;
SELECT * FROM a_tbl3;
           id  name                  phone
=========================================================
            1  'aaa'                 '000-0000'
            2  'bbb'                 '000-0000'
            3  'ccc'                 '333-3333'
            6  'eee'                 '000-0000'
--insert duplicated value violating UNIQUE constraint
INSERT INTO a_tbl3 VALUES(2, 'bbb', '222-2222');
ERROR: Operation would have caused one or more unique constraint violations.

With ON DUPLICATE KEY UPDATE, "affected rows" value per row will be 1 if a new row is inserted, and 2 if an existing row is updated.

--insert duplicated value with specifying ON DUPLICATED KEY UPDATE clause
INSERT INTO a_tbl3 VALUES(2, 'ggg', '222-2222')
ON DUPLICATE KEY UPDATE name='ggg', phone = '222-2222';

SELECT * FROM a_tbl3 WHERE id=2;
           id  name                  phone
=========================================================
            2  'ggg'                 '222-2222'

2 rows affected.
UPDATE

You can update the column value of a record stored in the target table or view to a new one by using the UPDATE statement. Specify the name of the column to update and a new value in the SET clause, and specify the condition to be used to extract the record to be updated in the WHERE Clause. You can one or more tables only with one UPDATE statement.

Note

Updating a view with JOIN syntax is possible from 10.0 version.

<UPDATE single table>
UPDATE table_name|view_name SET column_name = {<expr> | DEFAULT} [, column_name = {<expr> | DEFAULT} ...]
    [WHERE <search_condition>]
    [ORDER BY {col_name | <expr>}]
    [LIMIT row_count]

<UPDATE multiple tables>
UPDATE <table_specifications> SET column_name = {<expr> | DEFAULT} [, column_name = {<expr> | DEFAULT} ...]
    [WHERE <search_condition>]
  • <table_specifications>: You can specify the statement such as FROM clause of the SELECT statement and one or more tables can be specified.
  • column_name: Specifies the column name to be updated. Columns for one or more tables can be specified.
  • <expr> | DEFAULT: Specifies a new value for the column and expression or DEFAULT keyword can be specified as a value. The SELECT statement returning result record also can be specified.
  • <search_condition>: Update only data that meets the <search_condition> if conditions are specified in the WHERE Clause.
  • col_name | <expr>: Specifies base column to be updated.
  • row_count: Specifies the number of records to be updated after the LIMIT Clause. An integer greater than 0 can be specified.

In case of only one table is to be updated, you can specify ORDER BY Clause or LIMIT Clause. You can also limit the number of records to be updated in the LIMIT Clause. You can use the update with the ORDER BY Clause if you want to maintain the execution order or lock order of triggers.

Note

Previous versions of CUBRID 9.0 allow only one table for <table_specifications>.

The following example shows how to update one table.

--creating a new table having all records copied from a_tbl1
CREATE TABLE a_tbl5 AS SELECT * FROM a_tbl1;
SELECT * FROM a_tbl5 WHERE name IS NULL;
           id  name                  phone
=========================================================
         NULL  NULL                  '000-0000'
            4  NULL                  '000-0000'
            5  NULL                  '000-0000'
            7  NULL                  '777-7777'
UPDATE a_tbl5 SET name='yyy', phone='999-9999' WHERE name IS NULL LIMIT 3;
SELECT * FROM a_tbl5;
           id  name                  phone
=========================================================
         NULL  'yyy'                 '999-9999'
            1  'aaa'                 '000-0000'
            2  'bbb'                 '000-0000'
            3  'ccc'                 '333-3333'
            4  'yyy'                 '999-9999'
            5  'yyy'                 '999-9999'
            6  'eee'                 '000-0000'
            7  NULL                  '777-7777'
-- using triggers, that the order in which the rows are updated is modified by the ORDER BY clause.

CREATE TABLE t (i INT,d INT);
CREATE TRIGGER trigger1 BEFORE UPDATE ON t IF new.i < 10 EXECUTE PRINT 'trigger1 executed';
CREATE TRIGGER trigger2 BEFORE UPDATE ON t IF new.i > 10 EXECUTE PRINT 'trigger2 executed';
INSERT INTO t VALUES (15,1),(8,0),(11,2),(16,1), (6,0),(1311,3),(3,0);
UPDATE t  SET i = i + 1 WHERE 1 = 1;
trigger2 executed
trigger1 executed
trigger2 executed
trigger2 executed
trigger1 executed
trigger2 executed
trigger1 executed
TRUNCATE TABLE t;
INSERT INTO t VALUES (15,1),(8,0),(11,2),(16,1), (6,0),(1311,3),(3,0);
UPDATE t SET i = i + 1 WHERE 1 = 1  ORDER BY i;
trigger1 executed
trigger1 executed
trigger1 executed
trigger2 executed
trigger2 executed
trigger2 executed
trigger2 executed

The following example shows how to update multiple tables after joining them.

CREATE TABLE a_tbl(id INT PRIMARY KEY, charge DOUBLE);
CREATE TABLE b_tbl(rate_id INT, rate DOUBLE);
INSERT INTO a_tbl VALUES (1, 100.0), (2, 1000.0), (3, 10000.0);
INSERT INTO b_tbl VALUES (1, 0.1), (2, 0.0), (3, 0.2), (3, 0.5);

UPDATE
 a_tbl INNER JOIN b_tbl ON a_tbl.id=b_tbl.rate_id
SET
  a_tbl.charge = a_tbl.charge * (1 + b_tbl.rate)
WHERE a_tbl.charge > 900.0;

For a_tbl table and b_tbl table, which join the UPDATE statement, when the number of rows of a_tbl which joins one row of b_tbl is two or more and the column to be updated is included in a_tbl, update is executed by using the value of the row detected first among the rows of b_tbl.

In the above example, when the number of rows with id = 5, the JOIN condition column, is one in a_tbl and two in b_tbl, a_tbl.charge, the update target column in the row with a_tbl.id = 5, uses the value of rate of the first row in b_tbl only.

For more details on join syntax, see Join Query.

The following shows to update a view.

CREATE TABLE tbl1(a INT, b INT);
CREATE TABLE tbl2(a INT, b INT);
INSERT INTO tbl1 VALUES (5,5),(4,4),(3,3),(2,2),(1,1);
INSERT INTO tbl2 VALUES (6,6),(4,4),(3,3),(2,2),(1,1);
CREATE VIEW vw AS SELECT tbl2.* FROM tbl2 LEFT JOIN tbl1 ON tbl2.a=tbl1.a WHERE tbl2.a<=3;

UPDATE vw SET a=1000;

The below result for an UPDATE statement depends on the value of the update_use_attribute_references parameter.

CREATE TABLE tbl(a INT, b INT);
INSERT INTO tbl values (10, NULL);

UPDATE tbl SET a=1, b=a;

If the value of this parameter is yes, the updated value of "b" from the above UPDATE query will be 1 as being affected by "a=1".

SELECT * FROM tbl;
1, 1

If the value of this parameter is no, the updated value of "b" from the above UPDATE query will be NULL as being affected by the value of "a" which is stored at this record, not by "a=1".

SELECT * FROM tbl;
1, NULL
REPLACE

The REPLACE statement works like INSERT, but the difference is that it inserts a new record after deleting the existing record without displaying the error when a duplicate value is to be inserted into a column for which PRIMARY KEY or UNIQUE constraints have defined. You must have both INSERT and DELETE authorization to use the REPLACE statement, because it performs insertion or insertion after deletion operations. Please see GRANT for more information about authorization.

<REPLACE ... VALUES statement>
REPLACE [INTO] table_name [(column_name, ...)]
    {VALUES | VALUE}({expr | DEFAULT}, ...)[,({expr | DEFAULT}, ...),...]

<REPLACE ... SET statement>
REPLACE [INTO] table_name
    SET column_name = {expr | DEFAULT}[, column_name = {expr | DEFAULT},...]

<REPLACE ... SELECT statement>
REPLACE [INTO] table_name [(column_name, ...)]
    SELECT...
  • table_name: Specifies the name of the target table into which you want to insert a new record.
  • column_name: Specifies the name of the column into which you want to insert the value. If you omit to specify the column name, it is considered that all columns defined in the table have been specified. Therefore, you must specify the value for the column next to VALUES. If you do not specify all the columns defined in the table, a DEFAULT value is assigned to the non-specified columns; if the DEFAULT value is not defined, a NULL value is assigned.
  • expr | DEFAULT: Specifies values that correspond to the columns after VALUES. Expressions or the DEFAULT keyword can be specified as a value. At this time, the order and number of the specified column list must correspond to the column value list. The column value list for a single record is described in parentheses.

The REPLACE statement determines whether a new record causes the duplication of PRIMARY KEY or UNIQUE index column values. Therefore, for performance reasons, it is recommended to use the INSERT statement for a table for which a PRIMARY KEY or UNIQUE index has not been defined.

--creating a new table having the same schema as a_tbl1
CREATE TABLE a_tbl4 LIKE a_tbl1;
INSERT INTO a_tbl4 SELECT * FROM a_tbl1 WHERE id IS NOT NULL and name IS NOT NULL;

SELECT * FROM a_tbl4;
           id  name                  phone
=========================================================
            1  'aaa'                 '000-0000'
            2  'bbb'                 '000-0000'
            3  'ccc'                 '333-3333'
            6  'eee'                 '000-0000'
--insert duplicated value violating UNIQUE constraint
REPLACE INTO a_tbl4 VALUES(1, 'aaa', '111-1111'),(2, 'bbb', '222-2222');
REPLACE INTO a_tbl4 SET id=6, name='fff', phone=DEFAULT;

SELECT * FROM a_tbl4;
           id  name                  phone
=========================================================
            3  'ccc'                 '333-3333'
            1  'aaa'                 '111-1111'
            2  'bbb'                 '222-2222'
            6  'fff'                 '000-0000'
DELETE

You can delete records in the table by using the DELETE statement. You can specify delete conditions by combining the statement with the WHERE Clause. You can delete one or more tables with one DELETE statement.

<DELETE single table>
DELETE [FROM] table_name [ WHERE <search_condition> ] [LIMIT row_count]

<DELETE multiple tables FROM ...>
DELETE table_name[, table_name] ... FROM <table_specifications> [ WHERE <search_condition> ]

<DELETE FROM multiple tables USING ...>
DELETE FROM table_name[, table_name] ... USING <table_specifications> [ WHERE <search_condition> ]
  • <table_specifications>: You can specify the statement such as FROM clause of the SELECT statement and one or more tables can be specified.
  • table_name: Specifies the name of a table where the data to be deleted is contained. If the number of table is one, the FROM keyword can be omitted.
  • search_condition: Deletes only data that meets search_condition by using WHERE Clause. If it is specified, all data in the specified tables will be deleted.
  • row_count: Specifies the number of records to be deleted in the LIMIT Clause. An integer greater than 0 can be given.

When a table to delete records is only one, LIMIT Clause can be specified. You can limit the number of records by specifying the LIMIT Clause. If the number of records satisfying the WHERE Clause exceeds row_count, only the number of records specified in row_count will be deleted.

Note

  • On the DELETE statement with multiple tables, the table alias can be defined within <table_specifications> only. At the outside of <table_specifications>, the table alias defined in <table_specifications> can be used.
  • Previous versions of CUBRID 9.0 allow only one table for <table_specifications>.
CREATE TABLE a_tbl(
    id INT NOT NULL,
    phone VARCHAR(10));
INSERT INTO a_tbl VALUES(1,'111-1111'), (2,'222-2222'), (3, '333-3333'), (4, NULL), (5, NULL);

--delete one record only from a_tbl
DELETE FROM a_tbl WHERE phone IS NULL LIMIT 1;
SELECT * FROM a_tbl;
           id  phone
===================================
            1  '111-1111'
            2  '222-2222'
            3  '333-3333'
            5  NULL
--delete all records from a_tbl
DELETE FROM a_tbl;

Below tables are created to explain DELETE JOIN.

CREATE TABLE a_tbl(
    id INT NOT NULL,
    phone VARCHAR(10));
CREATE TABLE b_tbl(
    id INT NOT NULL,
    phone VARCHAR(10));
CREATE TABLE c_tbl(
    id INT NOT NULL,
    phone VARCHAR(10));

INSERT INTO a_tbl VALUES(1,'111-1111'), (2,'222-2222'), (3, '333-3333'), (4, NULL), (5, NULL);
INSERT INTO b_tbl VALUES(1,'111-1111'), (2,'222-2222'), (3, '333-3333'), (4, NULL);
INSERT INTO c_tbl VALUES(1,'111-1111'), (2,'222-2222'), (10, '333-3333'), (11, NULL), (12, NULL);

The below queries delete rows after joining multiple tables. They show the same result.

-- Below four queries show the same result.
--  <DELETE multiple tables FROM ...>

DELETE a, b FROM a_tbl a, b_tbl b, c_tbl c
WHERE a.id=b.id AND b.id=c.id;

DELETE a, b FROM a_tbl a INNER JOIN b_tbl b ON a.id=b.id
INNER JOIN c_tbl c ON b.id=c.id;

-- <DELETE FROM multiple tables USING ...>

DELETE FROM a, b USING a_tbl a, b_tbl b, c_tbl c
WHERE a.id=b.id AND b.id=c.id;

DELETE FROM a, b USING a_tbl a INNER JOIN b_tbl b ON a.id=b.id
INNER JOIN c_tbl c ON b.id=c.id;

For more details on join syntax, see Join Query.

MERGE

The MERGE statement is used to select rows from one or more sources and to update or to insert the rows onto one table or view. You can specify the condition whether to update or to insert the rows onto the target table or view. The MERGE statement is a deterministic statement, so you cannot update the same rows on the target table several times within one sentence.

MERGE [<merge_hint>] INTO <target> [[AS] <alias>]
USING <source> [[AS] <alias>], <source> [[AS] <alias>], ...
ON <join_condition>
[ <merge_update_clause> ]
[ <merge_insert_clause> ]

<merge_update_clause> ::=
WHEN MATCHED THEN UPDATE
SET <col = expr> [,<col = expr>,...] [WHERE <update_condition>]
[DELETE WHERE <delete_condition>]

<merge_insert_clause> ::=
WHEN NOT MATCHED THEN INSERT [(<attributes_list>)] VALUES (<expr_list>) [WHERE <insert_condition>]

<merge_hint> ::=
/*+ [ USE_UPDATE_IDX (<update_index_list>) ] [ USE_INSERT_IDX (<insert_index_list>) ] */
  • <target>: Target table to be updated or inserted. Several tables or views are available.
  • <source>: Source table to get the data. Several tables or views are available and sub-query is available, too.
  • <join_condition>: Specifies the updated conditions
  • <merge_update_clause>: If <join_condition> is TRUE, the new column value of a target table will be specified.
    • When the UPDATE clause is executed, all UPDATE triggers defined in <target> are enabled.
    • <col>: The column to be updated should be the column of the target table.
    • <expr>: Allows the expression including columns of <source> and <target>. Or it can be the DEFAULT keyword. <expr> cannot include the aggregate functions.
    • <update_condition>: Performs the UPDATE operation only when a specific condition is TRUE. For the condition, both of the source tables and the target tables can be referenced. The rows which do not satisfy the condition are not updated.
    • <delete_condition>: Specifies a target to be deleted after update. At this time, the DELETE condition is executed with the updated result value. When DELETE statement is executed, the DELETE trigger defined in <target> will be enabled.
    • The column referred by the ON condition clause cannot be updated.
    • When you update view, you cannot specify DEFAULT.
  • <merge_insert_clause>: If the <join_condition> condition is FALSE, the column value of the target table will be inserted.
    • When the INSERT clause is executed, all INSERT triggers defined in the target table are enabled.
    • <insert_condition>: Performs the INSERT operation only when the specified condition is TRUE. <Columns of <source> can be included in the condition.
    • <attribute_list>: Columns to be inserted in <target>.
    • <expr_list>: Integer filter condition can be used to insert all source rows to the target table. ON (0=1) is an example of integer filter condition.
    • This clause can be specified as it is or as <merge_update_clause>. If both of two are defined, the order does not matter.
  • <merge_hint>: Index hint of MERGE statement
    • USE_UPDATE_IDX (<update_index_list>): Index hint used in UPDATE clause of MERGE statement. Index names are listed on the update_index_list when UPDATE clause is run. This hint is applied to <join_condition> and <update_condition>.
    • USE_INSERT_IDX (<insert_index_list>): Index hint used in INSERT clause of MERGE statement. Index names are listed on the insert_index_list when INSERT clause is run. This hint is applied to <join_condition>.

To execute the MERGE statement, the SELECT authorization for the source table should be granted. When the UPDATE clause is included in the target table, the UPDATE authorization should be granted. When the DELETE clause is included in the target table, the DELETE should be granted. When the INSERT clause is included in the target table, the INSERT should be granted.

The following example shows how to merge the value of source_table to target_table.

-- source_table
CREATE TABLE source_table (a INT, b INT, c INT);
INSERT INTO source_table VALUES (1, 1, 1);
INSERT INTO source_table VALUES (1, 3, 2);
INSERT INTO source_table VALUES (2, 4, 5);
INSERT INTO source_table VALUES (3, 1, 3);

-- target_table
CREATE TABLE target_table (a INT, b INT, c INT);
INSERT INTO target_table VALUES (1, 1, 4);
INSERT INTO target_table VALUES (1, 2, 5);
INSERT INTO target_table VALUES (1, 3, 2);
INSERT INTO target_table VALUES (3, 1, 6);
INSERT INTO target_table VALUES (5, 5, 2);

MERGE INTO target_table tt USING source_table st
ON (st.a=tt.a AND st.b=tt.b)
WHEN MATCHED THEN UPDATE SET tt.c=st.c
     DELETE WHERE tt.c = 1
WHEN NOT MATCHED THEN INSERT VALUES (st.a, st.b, st.c);

-- the result of above query
SELECT * FROM target_table;
            a            b            c
=======================================
            1            2            5
            1            3            2
            3            1            3
            5            5            2
            2            4            5

In the above example, when column A and B of source_table are identical with the values of column A and B in target_table, column C of target_table is updated with the column C of source_table. Otherwise, the records in source_table are inserted to target_table. However, if the value of column C in target_table is 1 in the updated record, the record is deleted.

The following example shows how to use the MERGE statement to arrange the records of bonus score table to give to students.

CREATE TABLE bonus (std_id INT, addscore INT);
CREATE INDEX i_bonus_std_id ON bonus (std_id);

INSERT INTO bonus VALUES (1,10);
INSERT INTO bonus VALUES (2,10);
INSERT INTO bonus VALUES (3,10);
INSERT INTO bonus VALUES (4,10);
INSERT INTO bonus VALUES (5,10);
INSERT INTO bonus VALUES (6,10);
INSERT INTO bonus VALUES (7,10);
INSERT INTO bonus VALUES (8,10);
INSERT INTO bonus VALUES (9,10);
INSERT INTO bonus VALUES (10,10);

CREATE TABLE std (std_id INT, score INT);
CREATE INDEX i_std_std_id  ON std (std_id);
CREATE INDEX i_std_std_id_score ON std (std_id, score);

INSERT INTO std VALUES (1,60);
INSERT INTO std VALUES (2,70);
INSERT INTO std VALUES (3,80);
INSERT INTO std VALUES (4,35);
INSERT INTO std VALUES (5,55);
INSERT INTO std VALUES (6,30);
INSERT INTO std VALUES (7,65);
INSERT INTO std VALUES (8,65);
INSERT INTO std VALUES (9,70);
INSERT INTO std VALUES (10,22);
INSERT INTO std VALUES (11,67);
INSERT INTO std VALUES (12,20);
INSERT INTO std VALUES (13,45);
INSERT INTO std VALUES (14,30);

MERGE INTO bonus t USING (SELECT * FROM std WHERE score < 40) s
ON t.std_id = s.std_id
WHEN MATCHED THEN
UPDATE SET t.addscore = t.addscore + s.score * 0.1
WHEN NOT MATCHED THEN
INSERT (t.std_id, t.addscore) VALUES (s.std_id, 10 + s.score * 0.1) WHERE s.score <= 30;

SELECT * FROM bonus ORDER BY 1;
std_id     addscore
==========================
    1           10
    2           10
    3           10
    4           14
    5           10
    6           13
    7           10
    8           10
    9           10
   10           12
   12           12
   14           13

In the above example, the source table is a set of std table records, where the score is less than 40 and the target table is bonus. The student numbers (std_id) where the score (std.score) is less than 40 are 4, 6, 10, 12, and 14. Among them, for 4, 6, and 10 on the bonus table, the UPDATE clause adds 10% of the score of their own to the existing bonus. For 12 and 14 which are not on the bonus table, the INSERT clause adds 10 scores and 10% of the score of their own.

The following shows how to use index hints in MERGE statement.

CREATE TABLE target (i INT, j INT);
CREATE TABLE source (i INT, j INT);

INSERT INTO target VALUES (1,1),(2,2),(3,3);
INSERT INTO source VALUES (1,11),(2,22),(4,44),(5,55),(7,77),(8,88);

CREATE INDEX i_t_i ON target(i);
CREATE INDEX i_t_ij ON target(i,j);
CREATE INDEX i_s_i ON source(i);
CREATE INDEX i_s_ij ON source(i,j);

MERGE /*+ RECOMPILE USE_UPDATE_IDX(i_s_ij) USE_INSERT_IDX(i_t_ij, i_t_i) */
INTO target t USING source s ON t.i=s.i
WHEN MATCHED THEN UPDATE SET t.j=s.j WHERE s.i <> 1
WHEN NOT MATCHED THEN INSERT VALUES (i,j);
TRUNCATE

You can delete all records in the specified table by using the TRUNCATE statement.

This statement internally delete first all indexes and constraints defined in a table and then deletes all records. Therefore, it performs the job faster than using the DELETE FROM table_name statement without a WHERE clause.

If the PRIMARY KEY constraint is defined in the table and this is referred by one or more FOREIGN KEY, it follows the FOREIGN KEY ACTION. If the ON DELETE action of FOREIGN KEY is RESTRICT or NO_ACTION, the TRUNCATE statement returns an error. If it is CASCADE, it deletes FOREIGN KEY. The TRUNCATE statement initializes the AUTO INCREMENT column of the table. Therefore, if data is inserted, the AUTO INCREMENT column value increases from the initial value.

Note

To execute the TRUNCATE statement, the authorization of ALTER, INDEX, and DELETE is required on the table. For granting authorization, see GRANT.

TRUNCATE [ TABLE ] <table_name>
  • table_name : Specifies the name of the table that contains the data to be deleted.
CREATE TABLE a_tbl(A INT AUTO_INCREMENT(3,10) PRIMARY KEY);
INSERT INTO a_tbl VALUES (NULL),(NULL),(NULL);
SELECT * FROM a_tbl;
            a
=============
            3
            13
            23
--AUTO_INCREMENT column value increases from the initial value after truncating the table
TRUNCATE TABLE a_tbl;
INSERT INTO a_tbl VALUES (NULL);
SELECT * FROM a_tbl;
            a
=============
            3
PREPARED STATEMENT

In general, the prepared statement is executed through the interface functions of JDBC, PHP, or ODBC; it can also be executed in the SQL level. The following SQL statements are provided for execution of prepared statement.

  • Prepare the SQL statement to execute.

    PREPARE stmt_name FROM preparable_stmt
    
  • Execute the prepared statement.

    EXECUTE stmt_name [USING value [, value] ...]
    
  • Drop the prepared statement.

    {DEALLOCATE | DROP} PREPARE stmt_name
    

Note

  • In SQL level, PREPARE statement is recommended to use only in CSQL interpreter. If it is used in the application program, it is not guaranteed to work normally.
  • In SQL level, the number of PREPARE statements is limited to 20 per DB connection. It is limited to protect abusing DB server memory, because PREPARE statement in SQL level uses the memory of DB server.
  • In the interface function, the number of prepared statements is limited to MAX_PREPARED_STMT_COUNT of broker parameter per DB connection.
PREPARE Statement

The PREPARE statement prepares the query specified in preparable_stmt of the FROM clause and assigns the name to be used later when the SQL statement is referenced to stmt_name. See EXECUTE Statement for example.

PREPARE stmt_name FROM preparable_stmt
  • stmt_name : The prepared statement is specified. If an SQL statement with the same stmt_name exists in the given client session, clear the existing prepared statement and prepare a new SQL statement. If the PREPARE statement is not executed properly due to an error in the given SQL statement, it is processed as if the stmt_name assigned to the SQL statement does not exist.
  • preparable_stmt : You must use only one SQL statement. Multiple SQL statements cannot be specified. You can use a question mark (?) as a bind parameter in the preparable_stmt statement and it should not be enclosed with quotes.

Remark

The PREPARE statement starts by connecting an application to a server and will be maintained until the application terminates the connection. The connection maintained during this period is called a session. You can set the session time with the session_state_timeout parameter of cubrid.conf; the default value is 21600 seconds (=6 hours).

The data managed by the session includes the PREPARE statement, user-defined variables, the last ID inserted (LAST_INSERT_ID), and the number of rows affected by the statement (ROW_COUNT) that you execute at the end.

EXECUTE Statement

The EXECUTE statement executes the prepared statement. You can bind the data value after the USING clause if a bind parameter (?) is included in the prepared statement. You cannot specify user-defined variables like an attribute in the USING clause. A value such as literal and an input parameter only can be specified.

EXECUTE stmt_name [USING value [, value] ...]
  • stmt_name : The name given to the prepared statement to be executed is specified. An error message is displayed if the stmt_name is not valid, or if the prepared statement does not exist.
  • value : The data to bind is specified if there is a bind parameter in the prepared statement. The number and the order of the data must correspond to that of the bind parameter. If it does not, an error message is displayed.
PREPARE st FROM 'SELECT 1 + ?';
EXECUTE st USING 4;
   1+ ?:0
==========================
   5
PREPARE st FROM 'SELECT 1 + ?';
SET @a=3;
EXECUTE st USING @a;
   1+ ?:0
==========================
   4
PREPARE st FROM 'SELECT ? + ?';
EXECUTE st USING 1,3;
   ?:0 + ?:1
==========================
   4
PREPARE st FROM 'SELECT ? + ?';
EXECUTE st USING 'a','b';
   ?:0 + ?:1
==========================
   'ab'
PREPARE st FROM 'SELECT FLOOR(?)';
EXECUTE st USING '3.2';
   floor( ?:0 )
==========================
   3.000000000000000e+000
DEALLOCATE PREPARE/DROP PREPARE Statements

The statements DEALLOCATE PREPARE and DROP PREPARE are used interchangeably and they clear the prepared statement. All prepared statements are cleared automatically by the server when the client session is terminated even if the DEALLOCATE PREPARE or DROP PREPARE statement is not executed.

{DEALLOCATE | DROP} PREPARE stmt_name
  • stmt_name : The name given to the prepared statement to be cleared is specified. An error message is displayed if the stmt_name is not valid, or if the prepared statement does not exist.
DEALLOCATE PREPARE stmt1;
DO

The DO statement executes the specified expression, but does not return the result. This can be used to determine whether or not the syntax of the expression is correct because an error is returned when a specified expression does not comply with the syntax. In general, the execution speed of the DO statement is higher than that of the SELECT statement because the database server does not return the operation result or errors.

DO expression
  • expression : Specifies an expression.
DO 1+1;
DO SYSDATE + 1;
DO (SELECT count(*) FROM athlete);

Query Optimization

Updating Statistics

Statistics for tables and indexes enables queries of the database system to process efficiently. Statistics are updated automatically when DDL statements such as CREATE TABLE, CREATE/DROP INDEX are executed. However, since it is not automatically updated when DML statements such as INSERT and DELETE is performed, it is necessary to update the statistics by UPDATE STATISTICS statement(See Checking Statistics Information).

UPDATE STATISTICS statement is recommended only when a mass of INSERT or DELETE statements make the big difference between the statistics and the actual information.

UPDATE STATISTICS ON class-name[, class-name, ...] [WITH FULLSCAN];

UPDATE STATISTICS ON ALL CLASSES [WITH FULLSCAN];

UPDATE STATISTICS ON CATALOG CLASSES [WITH FULLSCAN];
  • WITH FULLSCAN: It updates the statistics with all the data in the specified table. If this is omitted, it updates the statistics with sampling data. Most cases are enough to update statistics with sampling data; it is recommended not to use WITH FULLSCAN because it can be a burden to the system.

    Note

    From 10.0 version, on the HA environment, UPDATE STATISTICS on the master node is replicated to the slave/replica node.

  • ALL CLASSES: If the ALL CLASSES keyword is specified, the statistics on all the tables existing in the database are updated.

  • CATALOG CLASSES: It updates the statistics of the catalog tables.

CREATE TABLE foo (a INT, b INT);
CREATE INDEX idx1 ON foo (a);
CREATE INDEX idx2 ON foo (b);

UPDATE STATISTICS ON foo;
UPDATE STATISTICS ON foo WITH FULLSCAN;

UPDATE STATISTICS ON ALL CLASSES;
UPDATE STATISTICS ON ALL CLASSES WITH FULLSCAN;

UPDATE STATISTICS ON CATALOG CLASSES;
UPDATE STATISTICS ON CATALOG CLASSES WITH FULLSCAN;

When starting and ending an update of statistics information, NOTIFICATION message is written on the server error log. You can check the updating term of statistics information by these two messages.

Time: 05/07/13 15:06:25.052 - NOTIFICATION *** file ../../src/storage/statistics_sr.c, line 123  CODE = -1114 Tran = 1, CLIENT = testhost:csql(21060), EID = 4
Started to update statistics (class "code", oid : 0|522|3).

Time: 05/07/13 15:06:25.053 - NOTIFICATION *** file ../../src/storage/statistics_sr.c, line 330  CODE = -1115 Tran = 1, CLIENT = testhost:csql(21060), EID = 5
Finished to update statistics (class "code", oid : 0|522|3, error code : 0).
Checking Statistics Information

You can check the statistics Information with the session command of the CSQL Interpreter.

csql> ;info stats table_name
  • table_name: Table name to check the statistics Information

The following shows the statistical information of t1 table in CSQL interpreter.

CREATE TABLE t1 (code INT);
INSERT INTO t1 VALUES(1),(2),(3),(4),(5);
CREATE INDEX i_t1_code ON t1(code);
UPDATE STATISTICS ON t1;
;info stats t1
CLASS STATISTICS
****************
 Class name: t1 Timestamp: Mon Mar 14 16:26:40 2011
 Total pages in class heap: 1
 Total objects: 5
 Number of attributes: 1
 Attribute: code
    id: 0
    Type: DB_TYPE_INTEGER
    Minimum value: 1
    Maximum value: 5
    B+tree statistics:
        BTID: { 0 , 1049 }
        Cardinality: 5 (5) , Total pages: 2 , Leaf pages: 1 , Height: 2
Viewing Query Plan

To view a query plan for a CUBRID SQL query, you can use following methods.

  • Press "show plan" button on CUBRID Manager or CUBRID Query Browser. For how to use CUBRID Manager or CUBRID Query Browser, see CUBRID Manager Manual or CUBRID Query Browser Manual.

    _images/query_plan_on_CM.png
  • Change the value of the optimization level by running ";plan simple" or ";plan detail" on CSQL interpreter, or by using the SET OPTIMIZATION statement. You can get the current optimization level value by using the GET OPTIMIZATION statement. For details on CSQL Interpreter, see Session Commands.

SET OPTIMIZATION or GET OPTIMIZATION LEVEL syntax is as following.

SET OPTIMIZATION LEVEL opt-level [;]
GET OPTIMIZATION LEVEL [ { TO | INTO } variable ] [;]
  • opt-level : A value that specifies the optimization level. It has the following meanings.

    • 0: Does not perform query optimization. The query is executed using the simplest query plan. This value is used only for debugging.
    • 1: Creates a query plan by performing query optimization and executes the query. This is a default value used in CUBRID, and does not have to be changed in most cases.
    • 2: Creates a query plan by performing query optimization. However, the query itself is not executed. In general, this value is not used; it is used together with the following values to be set for viewing query plans.
    • 257: Performs query optimization and outputs the created query plan. This value works for displaying the query plan by internally interpreting the value as 256+1 related with the value 1.
    • 258: Performs query optimization and outputs the created query plan, but does not execute the query. That is, this value works for displaying the query plan by internally interpreting the value as 256+2 related with the value 2. This setting is useful to examine the query plan but not to intend to see the query results.
    • 513: Performs query optimization and outputs the detailed query plan. This value works for displaying more detailed query plan than the value 257 by internally interpreting the value as 512+1.
    • 514: Performs query optimization and outputs the detailed query plan. However, the query is not executed. This value works for displaying more detailed query plan than the value 258 by internally interpreting the value as 512+2.

    Note

    If you configure the optimization level as not executing the query like 2, 258, or 514, all queries(not only SELECT, but also INSERT, UPDATE, DELETE, REPLACE, TRIGGER, SERIAL, etc.) are not executed.

The CUBRID query optimizer determines whether to perform query optimization and output the query plan by referring to the optimization level value set by the user.

The following shows the result which ran the query after inputting ";plan simple" or "SET OPTIMIZATION LEVEL 257;" in CSQL.

SET OPTIMIZATION LEVEL 257;
--  csql> ;plan simple
SELECT /*+ RECOMPILE */  DISTINCT h.host_year, o.host_nation
FROM history h INNER JOIN olympic o
ON h.host_year = o.host_year AND o.host_year > 1950;
Query plan:

 Sort(distinct)
    Nested-loop join(h.host_year=o.host_year)
        Index scan(olympic o, pk_olympic_host_year, (o.host_year> ?:0 ))
        Sequential scan(history h)
  • Sort(distinct): Perform DISTINCT.
  • Nested-loop join: Join method is Nested-loop.
  • Index scan: Perform index-scan by using pk_olympic_host_year index about olympic table. At that time, the condition which used this index is "o.host_year > ?".

The following shows the result which ran the query after inputting ";plan detail" or "SET OPTIMIZATION LEVEL 513;" in CSQL.

SET OPTIMIZATION LEVEL 513;
--  csql> ;plan detail

SELECT /*+ RECOMPILE */  DISTINCT h.host_year, o.host_nation
FROM history h INNER JOIN olympic o
ON h.host_year = o.host_year AND o.host_year > 1950;
Join graph segments (f indicates final):
seg[0]: [0]
seg[1]: host_year[0] (f)
seg[2]: [1]
seg[3]: host_nation[1] (f)
seg[4]: host_year[1]
Join graph nodes:
node[0]: history h(147/1)
node[1]: olympic o(25/1) (sargs 1)
Join graph equivalence classes:
eqclass[0]: host_year[0] host_year[1]
Join graph edges:
term[0]: h.host_year=o.host_year (sel 0.04) (join term) (mergeable) (inner-join) (indexable host_year[1]) (loc 0)
Join graph terms:
term[1]: o.host_year range (1950 gt_inf max) (sel 0.1) (rank 2) (sarg term) (not-join eligible) (indexable host_year[1]) (loc 0)

Query plan:

temp(distinct)
    subplan: nl-join (inner join)
                 edge:  term[0]
                 outer: iscan
                            class: o node[1]
                            index: pk_olympic_host_year term[1]
                            cost:  1 card 2
                 inner: sscan
                            class: h node[0]
                            sargs: term[0]
                            cost:  1 card 147
                 cost:  3 card 15
    cost:  9 card 15

Query stmt:

select distinct h.host_year, o.host_nation from history h, olympic o where h.host_year=o.host_year and (o.host_year> ?:0 )

On the above output, the information which is related to the query plan is "Query plan:". Query plan is performed sequentially from the inside above line. In other words, "outer: iscan -> inner:scan" is repeatedly performed and at last, "temp(distinct)" is performed. "Join graph segments" is used for checking more information on "Query plan:". For example, "term[0]" in "Query plan:" is represented as "term[0]: h.host_year=o.host_year (sel 0.04) (join term) (mergeable) (inner-join) (indexable host_year[1]) (loc 0)" in "Join graph segments".

The following shows the explanation of the above items of "Query plan:".

  • temp(distinct): (distinct) means that CUBRID performs DISTINCT query. temp means that it saves the result to the temporary space.
    • nl-join: "nl-join" means nested loop join.
    • (inner join): join type is "inner join".
      • outer: iscan: performs iscan(index scan) in the outer table.
        • class: o node[1]: It uses o table. For details, see node[1] of "Join graph segments".
        • index: pk_olympic_host_year term[1]: use pk_olympic_host_year index and for details, see term[1] of "Join graph segments".
        • cost: a cost to perform this syntax.
          • card: It means cardinality. Note that this is an approximate value.
      • inner: sscan: It performs sscan(sequential scan) in the inner table.
        • class: h node[0]: It uses h table. For details, see node[0] of "Join graph segments".
        • sargs: term[0]: sargs represent data filter(WHERE condition which does not use an index); it means that term[0] is the condition used as data filter.
        • cost: A cost to perform this syntax.
          • card: It means cardinality. Note that this is an approximate value.
    • cost: A cost to perform all syntaxes. It includes the previously performed cost.
      • card: It means cardinality. Note that this is an approximate value.

Query Plan Related Terms

The following show the meaning for each term which is printed as a query plan.

  • Join method: It is printed as "nl-join" on the above. The following are the join methods which are printed on the query plan.
    • nl-join: Nested loop join
    • m-join: Sort merge join
    • idx_join: Nested loop join, and it is a join which uses an index in the inner table as reading rows of the outer table.
  • Join type: It is printed as "(inner join)" on the above. The following are the join types which are printed on the query plan.
    • inner join
    • left outer join
    • right outer join: On the query plan, the different "outer" direction with the query's direction can be printed. For example, even if you specified "right outer" on the query, but "left outer" can be printed on the query plan.
    • cross join
  • Types of join tables: It is printed as outer or inner on the above. They are separated as outer table and inner table which are based on the position on either side of the loop, on the nested loop join.
    • outer table: The first base table to read when joining.
    • inner table: The target table to read later when joining.
  • Scan method: It is printed as iscan or sscan. You can judge that if the query uses index or not.
    • sscan: sequential scan. Also it can be called as full table scan; it scans all of the table without using an index.
    • iscan: index scan. It limits the range to scan by using an index.
  • cost: It internally calculate the cost related to CPU, IO etc., mainly the use of resources.
  • card: It means cardinality. It is a number of rows which are predicted as selected.

The following is an example of performing m-join(sort merge join) as specifying USE_MERGE hint. In general, sort merge join is used when sorting and merging an outer table and an inner table is judged as having an advantage than performing nested loop join. In most cases, it is desired that you do not perform sort merge join.

Note

From 9.3 version, if USE_MERGE hint is not specified or the optimizer_enable_merge_join parameter of cubrid.conf is not specified as yes, sort merge join will not be considered to be applied.

SET OPTIMIZATION LEVEL 513;
-- csql> ;plan detail

SELECT /*+ RECOMPILE USE_MERGE*/  DISTINCT h.host_year, o.host_nation
FROM history h LEFT OUTER JOIN olympic o ON h.host_year = o.host_year AND o.host_year > 1950;
Query plan:

temp(distinct)
    subplan: temp
                 order: host_year[0]
                 subplan: m-join (left outer join)
                              edge:  term[0]
                              outer: temp
                                         order: host_year[0]
                                         subplan: sscan
                                                      class: h node[0]
                                                      cost:  1 card 147
                                         cost:  10 card 147
                              inner: temp
                                         order: host_year[1]
                                         subplan: iscan
                                                      class: o node[1]
                                                      index: pk_olympic_host_year term[1]
                                                      cost:  1 card 2
                                         cost:  7 card 2
                              cost:  18 card 147
                 cost:  24 card 147
    cost:  30 card 147

The following performs the idx-join(index join). If performing join by using an index of inner table is judged as having an advantage, you can ensure performing idx-join by specifying USE_IDX hint.

SET OPTIMIZATION LEVEL 513;
-- csql> ;plan detail

CREATE INDEX i_history_host_year ON history(host_year);

SELECT /*+ RECOMPILE */  DISTINCT h.host_year, o.host_nation
FROM history h INNER JOIN olympic o ON h.host_year = o.host_year;
Query plan:

temp(distinct)
    subplan: idx-join (inner join)
                 outer: sscan
                            class: o node[1]
                            cost:  1 card 25
                 inner: iscan
                            class: h node[0]
                            index: i_history_host_year term[0] (covers)
                            cost:  1 card 147
                 cost:  2 card 147
    cost:  9 card 147

On the above query plan, "(covers)" is printed on the "index: i_history_host_year term[0]" of "inner: iscan", it means that Covering Index functionality is applied. In other words, it does not retrieve data storage additionally because there are required data inside the index in inner table.

If you ensure that left table's row number is a lot smaller than the right table's row number on the join tables, you can specify ORDERED hint. Then always the left table will be outer table, and the right table will be inner table.

SELECT /*+ RECOMPILE ORDERED */  DISTINCT h.host_year, o.host_nation
FROM history h INNER JOIN olympic o ON h.host_year = o.host_year;
Query Profiling

If the performance analysis of SQL is required, you can use query profiling feature. To use query profiling, specify SQL trace with SET TRACE ON syntax; to print out the profiling result, run SHOW TRACE syntax.

And if you want to always include the query plan when you run SHOW TRACE, you need to add /*+ RECOMPLIE */ hint on the query.

The format of SET TRACE ON syntax is as follows.

SET TRACE {ON | OFF} [OUTPUT {TEXT | JSON}]
  • ON: set on SQL trace.
  • OFF: set off SQL trace.
  • OUTPUT TEXT: print out as a general TEXT format. If you omit OUTPUT clause, TEXT format is specified.
  • OUTPUT JSON: print out as a JSON format.

As below, if you run SHOW TRACE syntax, the trace result is shown.

SHOW TRACE;

Below is an example that prints out the query tracing result after setting SQL trace ON.

csql> SET TRACE ON;
csql> SELECT /*+ RECOMPILE */ o.host_year, o.host_nation, o.host_city, SUM(p.gold)
        FROM OLYMPIC o, PARTICIPANT p
        WHERE o.host_year = p.host_year AND p.gold > 20
        GROUP BY o.host_nation;
csql> SHOW TRACE;
=== <Result of SELECT Command in Line 2> ===

  trace
======================
  '
Query Plan:
  SORT (group by)
    NESTED LOOPS (inner join)
      TABLE SCAN (o)
      INDEX SCAN (p.fk_participant_host_year) (key range: o.host_year=p.host_year)

  rewritten query: select o.host_year, o.host_nation, o.host_city, sum(p.gold) from OLYMPIC o, PARTICIPANT p where o.host_year=p.host_year and (p.gold> ?:0 ) group by o.host_nation

Trace Statistics:
  SELECT (time: 1, fetch: 975, ioread: 2)
    SCAN (table: olympic), (heap time: 0, fetch: 26, ioread: 0, readrows: 25, rows: 25)
      SCAN (index: participant.fk_participant_host_year), (btree time: 1, fetch: 941, ioread: 2, readkeys: 5, filteredkeys: 5, rows: 916) (lookup time: 0, rows: 14)
    GROUPBY (time: 0, sort: true, page: 0, ioread: 0, rows: 5)
'

In the above example, under lines of "Trace Statistics:" are the result of tracing. Each items of tracing result are as below.

  • SELECT (time: 1, fetch: 975, ioread: 2)

    • time: 4 => Total query time took 4ms.
    • fetch: 975 => 975 times were fetched regarding pages. (not the number of pages, but the count of accessing pages. even if the same pages are fetched, the count is increased.).
    • ioread: disk accessed 2 times.

    : Total statistics regarding SELECT query. If the query is rerun, fetching count and ioread count can be shrinken because some of query result are read from buffer.

    • SCAN (table: olympic), (heap time: 0, fetch: 26, ioread: 0, readrows: 25, rows: 25)

      • heap time: 0 => It took less than 1ms. CUBRID rounds off a value less than millisecond, so a time value less than 1ms is displayed as 0.
      • fetch: 26 => page fetching count is 26.
      • ioread: 0 => disk accessing count is 0.
      • readrows: 25 => the number of rows read when scanning is 25.
      • rows: 25 => the number of rows in result is 25.

      : Heap scan statistics for the olympic table.

      • SCAN (index: participant.fk_participant_host_year), (btree time: 1, fetch: 941, ioread: 2, readkeys: 5, filteredkeys: 5, rows: 916) (lookup time: 0, rows: 14)

        • btree time: 1 => It took 1ms.
        • fetch: 941 => page fetching count is 941.
        • ioread: 2 => disk accessing count is 2.
        • readkeys: 5 => the number of keys read is 5.
        • filteredkeys: 5 => the number of keys which the key filter is applied is 5.
        • rows: 916 => the number of rows scanning is 916.
        • lookup time: 0 => It took less than 1ms when accessing data after index scan.
        • rows: 14 => the number of rows after applying data filter; in the query, the number of rows is 14 when data filter "p.gold > 20" is applied.

        : Index scanning statistics regarding participant.fk_participant_host_year index.

    • GROUPBY (time: 0, sort: true, page: 0, ioread: 0, rows: 5)

      • time: 0 => It took less than 1ms when "group by" is applied.
      • sort: true => It's true because sorting is applied.
      • page: 0 => the number or temporary pages used in sorting is 0.
      • ioread: 0 => It took less than 1ms to access disk.
      • rows: 5 => the number of result rows regarding "group by" is 5.

      : Group by statistics.

The following is an example to join 3 tables.

csql> SET TRACE ON;
csql> SELECT /*+ RECOMPILE */ o.host_year, o.host_nation, o.host_city, n.name, SUM(p.gold), SUM(p.silver), SUM(p.bronze)
        FROM OLYMPIC o, PARTICIPANT p, NATION n
        WHERE o.host_year = p.host_year AND p.nation_code = n.code AND p.gold > 10
        GROUP BY o.host_nation;
csql> SHOW TRACE;

  trace
======================
  '
Query Plan:
  SORT (group by)
    NESTED LOOPS (inner join)
      NESTED LOOPS (inner join)
        TABLE SCAN (o)
        INDEX SCAN (p.fk_participant_host_year) (key range: (o.host_year=p.host_year))
      INDEX SCAN (n.pk_nation_code) (key range: p.nation_code=n.code)

  rewritten query: select o.host_year, o.host_nation, o.host_city, n.[name], sum(p.gold), sum(p.silver), sum(p.bronze) from OLYMPIC o, PARTICIPANT p, NATION n where (o.host_year=p.host_year and p.nation_code=n.code and (p.gold> ?:0 )) group by o.host_nation

Trace Statistics:
  SELECT (time: 1, fetch: 1059, ioread: 2)
    SCAN (table: olympic), (heap time: 0, fetch: 26, ioread: 0, readrows: 25, rows: 25)
      SCAN (index: participant.fk_participant_host_year), (btree time: 1, fetch: 945, ioread: 2, readkeys: 5, filteredkeys: 5, rows: 916) (lookup time: 0, rows: 38)
        SCAN (index: nation.pk_nation_code), (btree time: 0, fetch: 76, ioread: 0, readkeys: 38, filteredkeys: 38, rows: 38) (lookup time: 0, rows: 38)
    GROUPBY (time: 0, sort: true, page: 0, ioread: 0, rows: 5)
'

The following are the explanation regarding items of trace statistics.

SELECT

  • time: total estimated time when this query is performed(ms)
  • fetch: total page fetching count about this query
  • ioread: total I/O read count about this query. disk access count when the data is read

SCAN

  • heap: data scanning job without index
    • time, fetch, ioread: the estimated time(ms), page fetching count and I/O read count in the heap of this operation
    • readrows: the number of read rows when this operation is performed
    • rows: the number of result rows when this operation is performed
  • btree: index scanning job
    • time, fetch, ioread: the estimated time(ms), page fetching count and I/O read count in the btree of this operation
    • readkeys: the number of the keys which are read in btree when this operation is performed
    • filteredkeys: the number of the keys to which the key filter is applied from the read keys
    • rows: the number of result rows when this operation is performed; the number of result rows to which key filter is applied
  • lookup: data accessing job after index scanning
    • time: the estimated time(ms) in this operation
    • rows: the number of the result rows in this operation; the number of result rows to which the data filter is applied

GROUPBY

  • time: the estimated time(ms) in this operation
  • sort: sorting or not
  • page: the number of pages which is read in this operation; the number of used pages except the internal sorting buffer
  • rows: the number of the result rows in this operation

INDEX SCAN

  • key range: the range of a key
  • covered: covered index or not(true/false)
  • loose: loose index scan or not(true/false)
  • hash: hash aggregate evaluation or not, when sorting tuples in the aggregate function(true/false). See NO_HASH_AGGREGATE hint.

The above example can be output as JSON format.

csql> SET TRACE ON OUTPUT JSON;
csql> SELECT n.name, a.name FROM athlete a, nation n WHERE n.code=a.nation_code;
csql> SHOW TRACE;

  trace
======================
  '{
  "Trace Statistics": {
    "SELECT": {
      "time": 29,
      "fetch": 5836,
      "ioread": 3,
      "SCAN": {
        "access": "temp",
        "temp": {
          "time": 5,
          "fetch": 34,
          "ioread": 0,
          "readrows": 6677,
          "rows": 6677
        }
      },
      "MERGELIST": {
        "outer": {
          "SELECT": {
            "time": 0,
            "fetch": 2,
            "ioread": 0,
            "SCAN": {
              "access": "table (nation)",
              "heap": {
                "time": 0,
                "fetch": 1,
                "ioread": 0,
                "readrows": 215,
                "rows": 215
              }
            },
            "ORDERBY": {
              "time": 0,
              "sort": true,
              "page": 21,
              "ioread": 3
            }
          }
        }
      }
    }
  }
}'

On CSQL interpreter, if you use the command to set the SQL trace on automatically, the trace result is printed out automatically after printing the query result even if you do not run SHOW TRACE; syntax.

For how to set the trace on automatically, see Set SQL trace.

Note

  • CSQL interpreter which is run in the standalone mode(use -S option) does not support SQL trace feature.
  • When multiple queries are performed at once(batch query, array query), they are not profiled.
Using SQL Hint

Using hints can affect the performance of query execution. You can allow the query optimizer to create more efficient execution plan by referring to the SQL HINT. The SQL HINTs related tale join and index are provided by CUBRID.

{ SELECT | UPDATE | DELETE } /*+ <hint> [ { <hint> } ... ] */ ...;

MERGE /*+ <merge_statement_hint> [ { <merge_statement_hint> } ... ] */ INTO ...;

<hint> ::=
USE_NL [ (<spec_name_comma_list>) ] |
USE_IDX [ (<spec_name_comma_list>) ] |
USE_MERGE [ (<spec_name_comma_list>) ] |
ORDERED |
USE_DESC_IDX |
INDEX_SS [ (<spec_name_comma_list>) ] |
INDEX_LS |
NO_DESC_IDX |
NO_COVERING_IDX |
NO_MULTI_RANGE_OPT |
NO_SORT_LIMIT |
NO_HASH_AGGREGATE |
RECOMPILE

<spec_name_comma_list> ::= <spec_name> [, <spec_name>, ... ]
    <spec_name> ::= table_name | view_name

<merge_statement_hint> ::=
USE_UPDATE_INDEX (<update_index_list>) |
USE_DELETE_INDEX (<insert_index_list>) |
RECOMPILE

SQL hints are specified by using a plus sign(+) to comments. To use a hint, there are three styles as being introduced on Comment. Therefore, also SQL hint can be used as three styles.

  • /*+ hint */
  • --+ hint
  • //+ hint

The hint comment must appear after the keyword such as SELECT, UPDATE or DELETE, and the comment must begin with a plus sign (+), following the comment delimiter. When you specify several hints, they are separated by blanks.

The following hints can be specified in UPDATE, DELETE and SELECT statements.

  • USE_NL: Related to a table join, the query optimizer creates a nested loop join execution plan with this hint.
  • USE_MERGE: Related to a table join, the query optimizer creates a sort merge join execution plan with this hint.
  • ORDERED: Related to a table join, the query optimizer create a join execution plan with this hint, based on the order of tables specified in the FROM clause. The left table in the FROM clause becomes the outer table; the right one becomes the inner table.
  • USE_IDX: Related to an index, the query optimizer creates an index join execution plan corresponding to a specified table with this hint.
  • USE_DESC_IDX: This is a hint for the scan in descending index. For more information, see Index Scan in Descending Order.
  • INDEX_SS: Consider the query plan of index skip scan. For more information, see Index Skip Scan.
  • INDEX_LS: Consider the query plan of loose index scan. For more information, see Loose Index Scan.
  • NO_DESC_IDX: This is a hint not to use the descending index.
  • NO_COVERING_IDX: This is a hint not to use the covering index. For details, see Covering Index.
  • NO_MULTI_RANGE_OPT: This is a hint not to use the multi-key range optimization. For details, see Multiple Key Ranges Optimization.
  • NO_SORT_LIMIT: This is a hint not to use the SORT-LIMIT optimization. For more details, see SORT-LIMIT optimization.
  • NO_HASH_AGGREGATE: This is a hint not to use hashing for the sorting tuples in aggregate functions. Instead, external sorting is used in aggregate functions. By using an in-memory hash table, we can reduce or even eliminate the amount of data that needs to be sorted. However, in some scenarios the user may know beforehand that hash aggregation will fail and can use the hint to skip hash aggregation entirely. For setting the memory size of hashing aggregate, see max_agg_hash_size.

    Note

    Hash aggregate evaluation will not work for functions evaluated on distinct values (e.g. AVG(DISTINCT x)) and for the GROUP_CONCAT and MEDIAN functions, since they require an extra sorting step for the tuples of each group.

  • RECOMPILE : Recompiles the query execution plan. This hint is used to delete the query execution plan stored in the cache and establish a new query execution plan.

Note

If <spec_name> is specified together with USE_NL, USE_IDX or USE_MERGE, the specified join method applies only to the <spec_name>.

SELECT /*+ ORDERED USE_NL(B) USE_NL(C) USE_MERGE(D) */ *
FROM A INNER JOIN B ON A.col=B.col
INNER JOIN C ON B.col=C.col INNER JOIN D  ON C.col=D.col;

If you run the above query, USE_NL is applied when A and B are joined; USE_NL is applied when C is joined, too; USE_MERGE is applied when D is joined.

If USE_NL and USE_MERGE are specified together without <spec_name>, the given hint is ignored. In some cases, the query optimizer cannot create a query execution plan based on the given hint. For example, if USE_NL is specified for a right outer join, the query is converted to a left outer join internally, and the join order may not be guaranteed.

MERGE statement can have below hints.

  • USE_INSERT_INDEX (<insert_index_list>): An index hint which is used in INSERT clause of MERGE statement. Lists index names to insert_index_list to use when executing INSERT clause. This hint is applied to <join_condition> of MERGE statement.
  • USE_UPDATE_INDEX (<update_index_list>): An index hint which is used in UPDATE clause of MERGE statement. Lists index names to update_index_list to use when executing UPDATE clause. This hint is applied to <join_condition> and <update_condition> of MERGE statement.
  • RECOMPILE: See the above RECOMPILE.

Table/view names to join can be specified to the joining hint; at this time, table/view names are separated by ",".

SELECT /*+ USE_NL(a, b) */ *
FROM a INNER JOIN b ON a.col=b.col;

The following example shows how to retrieve the years when Sim Kwon Ho won medals and the types of medals. It can be expressed by the following query. The query optimizer creates a nested loop join execution plan that has the athlete table as an outer table and the game table as an inner table.

-- csql> ;plan_detail

SELECT /*+ USE_NL ORDERED  */ a.name, b.host_year, b.medal
FROM athlete a, game b
WHERE a.name = 'Sim Kwon Ho' AND a.code = b.athlete_code;
Query plan:

idx-join (inner join)
    outer: sscan
               class: a node[0]
               sargs: term[1]
               cost:  44 card 7
    inner: iscan
               class: b node[1]
               index: fk_game_athlete_code term[0]
               cost:  3 card 8653
    cost:  73 card 9

The following example shows how to specify tables when using a USE_NL hint.

-- csql> ;plan_detail

SELECT /*+ USE_NL(a,b)  */ a.name, b.host_year, b.medal
FROM athlete a, game b
WHERE a.name = 'Sim Kwon Ho' AND a.code = b.athlete_code;
Index Hint

The index hint syntax allows the query processor to select a proper index by specifying the index in the query. You can specify the index hint by USING INDEX clause or by {USE|FORCE|IGNORE} INDEX syntax after "FROM table" clause.

USING INDEX

USING INDEX clause should be specified after WHERE clause of SELECT, DELETE or UPDATE statement. USING INDEX clause forces a sequential/index scan to be used or an index that can improve the performance to be included.

If USING INDEX clause is specified with the list of index names, query optimizer creates optimized execution plan by calculating the query execution cost based on the specified indexes only and comparing the index scan cost and the sequential scan cost of the specified indexes(CUBRID performs cost-based query optimization to select an execution plan).

The USING INDEX clause is useful to get the results in the desired order without ORDER BY. When index scan is performed by CUBRID, the results are created in the order they were saved in the index. When there are more than one indexes in one table, you can use USING INDEX to get the query results in a given order of indexes.

SELECT ... WHERE ...
[USING INDEX { NONE | [ ALL EXCEPT ] <index_spec> [ {, <index_spec> } ...] } ] [ ; ]

DELETE ... WHERE ...
[USING INDEX { NONE | [ ALL EXCEPT ] <index_spec> [ {, <index_spec> } ...] } ] [ ; ]

UPDATE ... WHERE ...
[USING INDEX { NONE | [ ALL EXCEPT ] <index_spec> [ {, <index_spec> } ...] } ] [ ; ]

<index_spec> ::=
  [table_spec.]index_name [(+) | (-)] |
  table_spec.NONE
  • NONE: If NONE is specified, a sequential scan is used on all tables.
  • ALL EXCEPT: All indexes except the specified indexes can be used when the query is executed.
  • index_name(+): If (+) is specified after the index_name, it is the first priority in index selection. IF this index is not proper to run the query, it is not selected.
  • index_name(-): If (-) is specified after the index_name, it is excluded from index selection.
  • table_spec.NONE: All indexes are excluded from the selection, so sequential scan is used.
USE, FORCE, IGNORE INDEX

Index hints can be specified through USE, FORCE, IGNORE INDEX syntax after table specification of FROM clause.

FROM table_spec [ <index_hint_clause> ] ...

<index_hint_clause> ::=
  { USE | FORCE | IGNORE } INDEX  ( <index_spec> [, <index_spec>  ...] )

<index_spec> ::=
  [table_spec.]index_name
  • USE INDEX ( <index_spec> ): Only specified indexes are considered when choose them.
  • FORCE INDEX ( <index_spec> ): Specified indexes are chosen as the first priority.
  • IGNORE INDEX ( <index_spec> ): Specified indexes are excluded from the choice.

USE, FORCE, IGNORE INDEX syntax is automatically rewritten as the proper USING INDEX syntax by the system.

Examples of index hint
CREATE TABLE athlete2 (
   code             SMALLINT PRIMARY KEY,
   name             VARCHAR(40) NOT NULL,
   gender           CHAR(1),
   nation_code      CHAR(3),
   event            VARCHAR(30)
);
CREATE UNIQUE INDEX athlete2_idx1 ON athlete2 (code, nation_code);
CREATE INDEX athlete2_idx2 ON athlete2 (gender, nation_code);

Below two queries do the same behavior and they select index scan if the specified index, athlete2_idx2's scan cost is lower than sequential scan cost.

SELECT /*+ RECOMPILE */ *
FROM athlete2 USE INDEX (athlete2_idx2)
WHERE gender='M' AND nation_code='USA';

SELECT /*+ RECOMPILE */ *
FROM athlete2
WHERE gender='M' AND nation_code='USA'
USING INDEX athlete2_idx2;

Below two queries do the same behavior and they always use athlete2_idx2

SELECT /*+ RECOMPILE */ *
FROM athlete2 FORCE INDEX (athlete2_idx2)
WHERE gender='M' AND nation_code='USA';

SELECT /*+ RECOMPILE */ *
FROM athlete2
WHERE gender='M' AND nation_code='USA'
USING INDEX athlete2_idx2(+);

Below two queries do the same behavior and they always don't use athlete2_idx2

SELECT /*+ RECOMPILE */ *
FROM athlete2 IGNORE INDEX (athlete2_idx2)
WHERE gender='M' AND nation_code='USA';

SELECT /*+ RECOMPILE */ *
FROM athlete2
WHERE gender='M' AND nation_code='USA'
USING INDEX athlete2_idx2(-);

Below query always do the sequential scan.

SELECT *
FROM athlete2
WHERE gender='M' AND nation_code='USA'
USING INDEX NONE;

SELECT *
FROM athlete2
WHERE gender='M' AND nation_code='USA'
USING INDEX athlete2.NONE;

Below query forces to be possible to use all indexes except athlete2_idx2 index.

SELECT *
FROM athlete2
WHERE gender='M' AND nation_code='USA'
USING INDEX ALL EXCEPT athlete2_idx2;

When two or more indexes have been specified in the USING INDEX clause, the query optimizer selects the proper one of the specified indexes.

SELECT *
FROM athlete2 USE INDEX (athlete2_idx2, athlete2_idx1)
WHERE gender='M' AND nation_code='USA';

SELECT *
FROM athlete2
WHERE gender='M' AND nation_code='USA'
USING INDEX athlete2_idx2, athlete2_idx1;

When a query is run for several tables, you can specify a table to perform index scan by using a specific index and another table to perform sequential scan. The query has the following format.

SELECT *
FROM tab1, tab2
WHERE ...
USING INDEX tab1.idx1, tab2.NONE;

When executing a query with the index hint syntax, the query optimizer considers all available indexes on the table for which no index has been specified. For example, when the tab1 table includes idx1 and idx2 and the tab2 table includes idx3, idx4, and idx5, if indexes for only tab1 are specified but no indexes are specified for tab2, the query optimizer considers the indexes of tab2.

SELECT ...
FROM tab1, tab2 USE INDEX(tab1.idx1)
WHERE ... ;

SELECT ...
FROM tab1, tab2
WHERE ...
USING INDEX tab1.idx1;

The above query select the scan method of table tab1 after comparing the cost between the sequential scan of the table tab1 and the index scan of the index idx1, and select the scan method of table tab2 after comparing the cost between the sequential scan of the table tab2 and the index scan of the indexes idx3, idx4, idx5.

Special Indexes
Filtered Index

The filtered index is used to sort, search, or operate a well-defined partials set for one table. It is called the partial index since only some data that satisfy the condition are kept in that index.

CREATE /*+ hints */ INDEX index_name
ON table_name (col1, col2, ...)
WHERE <filter_predicate>;

ALTER  /*+ hints */ INDEX index_name
[ ON table_name (col1, col2, ...)
[ WHERE <filter_predicate> ] ]
REBUILD;

<filter_predicate> ::= <filter_predicate> AND <expression> | <expression>
  • <filter_predicate>: Condition to compare the column and the constant. When there are several conditions, filtering is available only when they are connected by using AND. The filter conditions can include most of the operators and functions supported by CUBRID. However, the date/time function that shows the current date/time (ex: SYS_DATETIME()) or random functions (ex: RAND()), which outputs different results for one input are not allowed.

If you want to apply the filtered index, that filtered index must be specified by USE INDEX syntax or FORCE INDEX syntax.

  • When a filtered index is specified by USING INDEX clause or USE INDEX syntax:

    If columns of which the index consists are not included on the conditions of WHERE clause, the filtered index is not used.

    CREATE TABLE blogtopic
    (
        blogID BIGINT NOT NULL,
        title VARCHAR(128),
        author VARCHAR(128),
        content VARCHAR(8096),
        postDate TIMESTAMP NOT NULL,
        deleted SMALLINT DEFAULT 0
    );
    
    CREATE INDEX my_filter_index ON blogtopic(postDate) WHERE deleted=0;
    

    On the below query, postDate, a column of which my_filter_index consists, is included on the conditions of WHERE condition. Therefore, this index can be used by "USE INDEX" syntax.

    SELECT *
    FROM blogtopic USE INDEX (my_filter_index)
    WHERE postDate>'2010-01-01' AND deleted=0;
    
  • When a filtered index is specified by USING INDEX <index_name>(+) clause or FORCE INDEX syntax:

    Even if a column of which the index consists is not included on the condition of WHERE clause, the filtered index is used.

    On the below query, my_filter_index cannot be used by "USE INDEX" syntax because a column of which my_filter_index consists is not included on the WHERE condition.

    SELECT *
    FROM blogtopic USE INDEX (my_filter_index)
    WHERE author = 'David' AND deleted=0;
    

    Therefore, to use my_filter_index, it should be forced by "FORCE INDEX".

    SELECT *
    FROM blogtopic FORCE INDEX (my_filter_index)
    WHERE author = 'David' AND deleted=0;
    

The following example shows a bug tracking system that maintains bugs/issues. After a specified period of development, the bugs table records bugs. Most of the bugs have already been closed. The bug tracking system makes queries on the table to find new open bugs. In this case, the indexes on the bug table do not need to know the records on closed bugs. Then the filtered indexes allow indexing of open bugs only.

CREATE TABLE bugs
(
    bugID BIGINT NOT NULL,
    CreationDate TIMESTAMP,
    Author VARCHAR(255),
    Subject VARCHAR(255),
    Description VARCHAR(255),
    CurrentStatus INTEGER,
    Closed SMALLINT
);

Indexes for open bugs can be created by using the following sentence:

CREATE INDEX idx_open_bugs ON bugs(bugID) WHERE Closed = 0;

To process queries that are interested in open bugs, specify the index as an index hint. It will allow creating query results by accessing less index pages through filtered indexes.

SELECT *
FROM bugs
WHERE Author = 'madden' AND Subject LIKE '%fopen%' AND Closed = 0
USING INDEX idx_open_bugs(+);

SELECT *
FROM bugs FORCE INDEX (idx_open_bugs)
WHERE CreationDate > CURRENT_DATE - 10 AND Closed = 0;

On the above example, if you use "USING INDEX idx_open_bugs" clause or "USE INDEX (idx_open_bugs)" syntax, a query is processed without using the idx_open_bugs index.

Warning

If you execute queries by specifying indexes with index hint syntax even though the conditions of creating filtered indexes does not match the query conditions, CUBRID performs a query by choosing a specified index. Therefore, query results can be different with the given searching conditions.

Note

Constraints

Only generic indexes are allowed as filtered indexes. For example, the filtered unique index is not allowed. Also, it is not allowed that columns which compose an index are all NULLable. For example, below is not allowed because Author is NULLable.

CREATE INDEX idx_open_bugs ON bugs (Author) WHERE Closed = 0;
ERROR: before ' ; '
Invalid filter expression (bugs.Closed=0) for index.

However, below is allowed because Author is NULLable, but CreationDate is not NULLable.

CREATE INDEX idx_open_bugs ON bugs (Author, CreationDate) WHERE Closed = 0;

The following cases are not allowed as filtering conditions.

  • Functions, which output different results with the same input, such as date/time function or random function

    CREATE INDEX idx ON bugs(creationdate) WHERE creationdate > SYS_DATETIME;
    
    ERROR: before ' ; '
    'sys_datetime ' is not allowed in a filter expression for index.
    
    CREATE INDEX idx ON bugs(bugID) WHERE bugID > RAND();
    
    ERROR: before ' ; '
    'rand ' is not allowed in a filter expression for index.
    
  • In case of using the OR operator

    CREATE INDEX IDX ON bugs (bugID) WHERE bugID > 10 OR bugID = 3;
    
    ERROR: before ' ; '
    ' or ' is not allowed in a filter expression for index.
    
  • In case of including functions like INCR(), DECR() functions, which modify the data of a table.

  • In case of Serial-related functions and including pseudo columns.

  • In case of including aggregate functions such as MIN(), MAX(), STDDEV()

  • In case of using the types where indexes cannot be created

  • The IS NULL operator can be used only when at least one column of an index is not NULL.

    CREATE TABLE t (a INT, b INT);
    
    -- IS NULL cannot be used with expressions
    CREATE INDEX idx ON t (a) WHERE (not a) IS NULL;
    
    ERROR: before ' ; '
    Invalid filter expression (( not t.a<>0) is null ) for index.
    
    CREATE INDEX idx ON t (a) WHERE (a+1) IS NULL;
    
    ERROR: before ' ; '
    Invalid filter expression ((t.a+1) is null ) for index.
    
    -- At least one attribute must not be used with IS NULL
    CREATE INDEX idx ON t(a,b) WHERE a IS NULL ;
    
    ERROR: before '  ; '
    Invalid filter expression (t.a is null ) for index.
    
    CREATE INDEX idx ON t(a,b) WHERE a IS NULL and b IS NULL;
    
    ERROR: before ' ; '
    Invalid filter expression (t.a is null  and t.b is null ) for index.
    
    CREATE INDEX idx ON t(a,b) WHERE a IS NULL and b IS NOT NULL;
    
  • Index Skip Scan (ISS) is not allowed for the filtered indexes.

  • The length of condition string used for the filtered index is limited to 128 characters.

    CREATE TABLE t(VeryLongColumnNameOfTypeInteger INT);
    
    CREATE INDEX idx ON t(VeryLongColumnNameOfTypeInteger)
    WHERE VeryLongColumnNameOfTypeInteger > 3 AND VeryLongColumnNameOfTypeInteger < 10 AND
    SQRT(VeryLongColumnNameOfTypeInteger) < 3 AND SQRT(VeryLongColumnNameOfTypeInteger) < 10;
    
    ERROR: before ' ; '
    The maximum length of filter predicate string must be 128.
    
Function-based Index

Function-based index is used to sort or find the data based on the combination of values of table rows by using a specific function. For example, to find the space-ignored string, it can be used to optimize the query by using the function that provides the feature. In addition, it is useful to search the non-case-sensitive names.

CREATE /*+ hints */ INDEX index_name
ON table_name (function_name (argument_list));

ALTER /*+ hints */ INDEX index_name
[ ON table_name (function_name (argument_list)) ]
REBUILD;

After the following indexes have been created, the SELECT query automatically uses the function-based index.

CREATE INDEX idx_trim_post ON posts_table(TRIM(keyword));

SELECT *
FROM posts_table
WHERE TRIM(keyword) = 'SQL';

If a function-based index is created by using the LOWER function, it can be used to search the non-case-sensitive names.

CREATE INDEX idx_last_name_lower ON clients_table(LOWER(LastName));

SELECT *
FROM clients_table
WHERE LOWER(LastName) = LOWER('Timothy');

To make an index selected while creating a query plan, the function used for the index should be used for the query condition in the same way. The SELECT query above uses the last_name_lower index created above. However, this index is not used for the following condition:

SELECT *
FROM clients_table
WHERE LOWER(CONCAT('Mr. ', LastName)) = LOWER('Mr. Timothy');

In addition, to make the function-based index used by force, use the USING INDEX syntax.

CREATE INDEX i_tbl_first_four ON tbl(LEFT(col, 4));
SELECT *
FROM clients_table
WHERE LEFT(col, 4) = 'CAT5'
USING INDEX i_tbl_first_four;

Functions with the function-based indexes are as follows:

ABS ACOS ADD_MONTHS ADDDATE ASIN
ATAN ATAN2 BIT_COUNT BIT_LENGTH CEIL
CHAR_LENGTH CHR COS COT DATE
DATE_ADD DATE_FORMAT DATE_SUB DATEDIFF DAY
DAYOFMONTH DAYOFWEEK DAYOFYEAR DEGREES EXP
FLOOR FORMAT FROM_DAYS FROM_UNIXTIME GREATEST
HOUR IFNULL INET_ATON INET_NTOA INSTR
LAST_DAY LEAST LEFT LN LOCATE
LOG LOG10 LOG2 LOWER LPAD
LTRIM MAKEDATE MAKETIME MD5 MID
MINUTE MOD MONTH MONTHS_BETWEEN NULLIF
NVL NVL2 OCTET_LENGTH POSITION POWER
QUARTER RADIANS REPEAT REPLACE REVERSE
RIGHT ROUND RPAD RTRIM SECOND
SECTOTIME SIN SQRT STR_TO_DATE STRCMP
SUBDATE SUBSTR SUBSTRING SUBSTRING_INDEX TAN
TIME TIME_FORMAT TIMEDIFF TIMESTAMP TIMETOSEC
TO_CHAR TO_DATE TO_DATETIME TO_DAYS TO_NUMBER
TO_TIME TO_TIMESTAMP TRANSLATE TRIM TRUNC
UNIX_TIMESTAMP UPPER WEEK WEEKDAY YEAR

Arguments of functions which can be used in the function-based indexes, only column names and constants are allowed; nested expressions are not allowed. For example, a statement below will cause an error.

CREATE INDEX my_idx ON tbl (TRIM(LEFT(col, 3)));
CREATE INDEX my_idx ON tbl (LEFT(col1, col2 + 3));

However, implicit cast is allowed. In the example below, the first argument type of the LEFT () function should be VARCHAR and the second argument type should be INTEGER; it works normally.

CREATE INDEX my_idx ON tbl (LEFT(int_col, str_col));

Function-based indexes cannot be used with filtered indexes. The example will cause an error.

CREATE INDEX my_idx ON tbl (TRIM(col)) WHERE col > 'SQL';

Function-based indexes cannot become multiple-columns indexes. The example will cause an error.

CREATE INDEX my_idx ON tbl (TRIM(col1), col2, LEFT(col3, 5));
Optimization using indexes
Covering Index

The covering index is the index including the data of all columns in the SELECT list and the WHERE, HAVING, GROUP BY, and ORDER BY clauses.

You only need to scan the index pages, as the covering index contains all the data necessary for executing a query, and it also reduces the I/O costs as it is not necessary to scan the data storage any further. To increase data search speed, you can consider creating a covering index but you should be aware that the INSERT and the DELETE processes may be slowed down due to the increase in index size.

The rules about the applicability of the covering index are as follows:

  • If the covering index is applicable, you should use the CUBRID query optimizer first.
  • For the join query, if the index includes columns of the table in the SELECT list, use this index.
  • You cannot use the covering index if an index cannot be used.
CREATE TABLE t (col1 INT, col2 INT, col3 INT);
CREATE INDEX i_t_col1_col2_col3 ON t (col1,col2,col3);
INSERT INTO t VALUES (1,2,3),(4,5,6),(10,8,9);

The following example shows that the index is used as a covering index because columns of both SELECT and WHERE condition exist within the index.

-- csql> ;plan simple
SELECT * FROM t WHERE col1 < 6;
Query plan:
 Index scan(t t, i_t_col1_col2_col3, [(t.col1 range (min inf_lt t.col3))] (covers))

         col1         col2         col3
=======================================
            1            2            3
            4            5            6

Warning

If the covering index is applied when you get the values from the VARCHAR type column, the empty strings that follow will be truncated. If the covering index is applied to the execution of query optimization, the resulting query value will be retrieved. This is because the value will be stored in the index with the empty string being truncated.

If you don't want this, use the NO_COVERING_IDX hint, which does not use the covering index function. If you use the hint, you can get the result value from the data area rather than from the index area.

The following is a detailed example of the above situation. First, create a table with columns in VARCHAR types, and then INSERT the value with the same start character string value but the number of empty characters. Next, create an index in the column.

CREATE TABLE tab(c VARCHAR(32));
INSERT INTO tab VALUES('abcd'),('abcd    '),('abcd ');
CREATE INDEX i_tab_c ON tab(c);

If you must use the index (the covering index applied), the query result is as follows:

-- csql>;plan simple
SELECT * FROM tab WHERE c='abcd    ' USING INDEX i_tab_c(+);
Query plan:
 Index scan(tab tab, i_tab_c, (tab.c='abcd    ') (covers))

 c
======================
'abcd'
'abcd'
'abcd'

The following is the query result when you don't use the index.

SELECT * FROM tab WHERE c='abcd    ' USING INDEX tab.NONE;
Query plan:
 Sequential scan(tab tab)

 c
======================
'abcd'
'abcd    '
'abcd '

As you can see in the above comparison result, the value in the VARCHAR type retrieved from the index will appear with the following empty string truncated when the covering index has been applied.

Note

If covering index optimization is available to be applied, the I/O performance can be improved because the disk I/O is decreased. But if you don't want covering index optimization in a special condition, specify a NO_COVERING_IDX hint to the query. For how to add a query, see Using SQL Hint.

Optimizing ORDER BY Clause

The index including all columns in the ORDER BY clause is referred to as the ordered index. Optimizing the query with ORDER BY clause is no need for the additional sorting process(skip order by), because the query results are searched by the ordered index. In general, for an ordered index, the columns in the ORDER BY clause should be located at the front of the index.

SELECT *
FROM tab
WHERE col1 > 0
ORDER BY col1, col2;
  • The index consisting of tab (col1, col2) is an ordered index.
  • The index consisting of tab (col1, col2, col3) is also an ordered index. This is because the col3, which is not referred to by the ORDER BY clause, comes after col1 and col2 .
  • The index consisting of tab (col1) is not an ordered index.
  • You can use the index consisting of tab (col3, col1, col2) or tab (col1, col3, col2) for optimization. This is because col3 is not located at the back of the columns in the ORDER BY clause.

Although the columns composing an index do not exist in the ORDER BY clause, you can use an ordered index if the column condition is a constant.

SELECT *
FROM tab
WHERE col2=val
ORDER BY col1,col3;

If the index consisting of tab (col1, col2, col3) exists and the index consisting of tab (col1, col2) do not exist when executing the above query, the query optimizer uses the index consisting of tab (col1, col2, col3) as an ordered index. You can get the result in the requested order when you execute an index scan, so you don't need to sort records.

If you can use the sorted index and the covering index, use the latter first. If you use the covering index, you don't need to retrieve additional data, because the data result requested is included in the index page, and you won't need to sort the result if you are satisfied with the index order.

If the query doesn't include any conditions and uses an ordered index, the ordered index will be used under the condition that the first column meets the NOT NULL condition.

CREATE TABLE tab (i INT, j INT, k INT);
CREATE INDEX i_tab_j_k on tab (j,k);
INSERT INTO tab VALUES (1,2,3),(6,4,2),(3,4,1),(5,2,1),(1,5,5),(2,6,6),(3,5,4);

The following example shows that indexes consisting of tab (j, k) become sorted indexes and no separate sorting process is required because GROUP BY is executed by j and k columns.

SELECT i,j,k
FROM tab
WHERE j > 0
ORDER BY j,k;
--  the  selection from the query plan dump shows that the ordering index i_tab_j_k was used and sorting was not necessary
--  (/* --> skip ORDER BY */)
Query plan:
iscan
    class: tab node[0]
    index: i_tab_j_k term[0]
    sort:  2 asc, 3 asc
    cost:  1 card 0
Query stmt:
select tab.i, tab.j, tab.k from tab tab where ((tab.j> ?:0 )) order by 2, 3
/* ---> skip ORDER BY */

            i            j            k
=======================================
            5            2            1
            1            2            3
            3            4            1
            6            4            2
            3            5            4
            1            5            5
            2            6            6

The following example shows that j and k columns execute ORDER BY and the index including all columns are selected so that indexes consisting of tab (j, k) are used as covering indexes; no separate process is required because the value is selected from the indexes themselves.

SELECT /*+ RECOMPILE */ j,k
FROM tab
WHERE j > 0
ORDER BY j,k;
--  in this case the index i_tab_j_k is a covering index and also respects the ordering index property.
--  Therefore, it is used as a covering index and sorting is not performed.

Query plan:
iscan
    class: tab node[0]
    index: i_tab_j_k term[0] (covers)
    sort:  1 asc, 2 asc
    cost:  1 card 0

Query stmt: select tab.j, tab.k from tab tab where ((tab.j> ?:0 )) order by 1, 2
/* ---> skip ORDER BY */

            j            k
==========================
            2            1
            2            3
            4            1
            4            2
            5            4
            5            5
            6            6

The following example shows that i column exists, ORDER BY is executed by j and k columns, and columns that perform SELECT are i, j, and k. Therefore, indexes consisting of tab (i, j, k) are used as covering indexes; separate sorting process is required for ORDER BY j, k even though the value is selected from the indexes themselves.

CREATE INDEX i_tab_j_k ON tab (i,j,k);
SELECT /*+ RECOMPILE */ i,j,k
FROM tab
WHERE i > 0
ORDER BY j,k;
-- since an index on (i,j,k) is now available, it will be used as covering index. However, sorting the results according to
-- the ORDER BY  clause is needed.
Query plan:
temp(order by)
    subplan: iscan
                 class: tab node[0]
                 index: i_tab_i_j_k term[0] (covers)
                 sort:  1 asc, 2 asc, 3 asc
                 cost:  1 card 1
    sort:  2 asc, 3 asc
    cost:  7 card 1

Query stmt: select tab.i, tab.j, tab.k from tab tab where ((tab.i> ?:0 )) order by 2, 3

            i            j            k
=======================================
            5            2            1
            1            2            3
            3            4            1
            6            4            2
            3            5            4
            1            5            5
            2            6            6

Note

Even if the type of a column in the ORDER BY clause is converted by using CAST(), ORDER BY optimization is executed when the sorting order is the same as before.

Before | After
numeric type numeric type
string type string type
DATETIME TIMESTAMP
TIMESTAMP DATETIME
DATETIME DATE
TIMESTAMP DATE
DATE DATETIME
Index Scan in Descending Order

When a query is executed by sorting in descending order as follows, it usually creates a descending index. In this way, you do not have to go through addition procedure.

SELECT *
FROM tab
[WHERE ...]
ORDER BY a DESC;

However, if you create an ascending index and an descending index in the same column, the possibility of deadlock increases. In order to decrease the possibility of such case, CUBRID supports the descending scan only with ascending index. Users can use the USE_DESC_IDX hint to specify the use of the descending scan. If the hint is not specified, the following three query executions should be considered, provided that the columns listed in the ORDER BY clause can use the index.

  • Sequential scan + Sort in descending order
  • Scan in general ascending order + sort in descending
  • Scan in descending order that does not require a separate scan

Although the USE_DESC_IDX hint is omitted for the scan in descending order, the query optimizer decides the last execution plan of the three listed for an optimal plan.

Note

The USE_DESC_IDX hint is not supported for the join query.

CREATE TABLE di (i INT);
CREATE INDEX i_di_i on di (i);
INSERT INTO di VALUES (5),(3),(1),(4),(3),(5),(2),(5);

The query will be executed as an ascending scan without USE_DESC_IDX hint.

-- The query will be executed with an ascending scan.

SELECT  *
FROM di
WHERE i > 0
LIMIT 3;
Query plan:

Index scan(di di, i_di_i, (di.i range (0 gt_inf max) and inst_num() range (min inf_le 3)) (covers))

            i
=============
            1
            2
            3

If you add USE_DESC_IDX hint to the above query, a different result will be shown by descending scan.

-- We now run the following query, using the ''use_desc_idx'' SQL hint:

SELECT /*+ USE_DESC_IDX */ *
FROM di
WHERE i > 0
LIMIT 3;
Query plan:
 Index scan(di di, i_di_i, (di.i range (0 gt_inf max) and inst_num() range (min inf_le 3)) (covers) (desc_index))

            i
=============
            5
            5
            5

The following example requires descending order by ORDER BY clause. In this case, there is no USE_DESC_IDX but do the descending scan.

-- We also run the same query, this time asking that the results are displayed in descending order.
-- However, no hint is given.
-- Since ORDER BY...DESC clause exists, CUBRID will use descending scan, even though the hint is not given,
-- thus avoiding to sort the records.

SELECT *
FROM di
WHERE i > 0
ORDER BY i DESC LIMIT 3;
Query plan:
 Index scan(di di, i_di_i, (di.i range (0 gt_inf max)) (covers) (desc_index))

            i
=============
            5
            5
            5
Optimizing GROUP BY Clause

GROUP BY clause optimization works on the premise that if all columns in the GROUP BY clause are included in an index, CUBRID can use the index upon executing a query, so CUBRID don't execute a separate sorting job. The columns in the GROUP BY clause must exist in front side of the column forming the index.

SELECT *
FROM tab
WHERE col1 > 0
GROUP BY col1,col2;
  • You can use the index consisting of tab(col1, col2) for optimization.
  • The index consisting of tab(col1, col2, col3) can be used because col3 which is not referred to by GROUP BY comes after col1 and col2.
  • You cannot use the index consisting of tab(col1) for optimization.
  • You also cannot use the index consisting of tab(col3, col1, col2) or tab(col1, col3, col2), because col3 is not located at the back of the column in the GROUP BY clause.

You can use the index if the column condition is a constant although the column consisting of the index doesn't exist in the GROUP BY clause.

SELECT *
FROM tab
WHERE col2=val
GROUP BY col1,col3;

If there is any index that consists of tab(col1, col2, col3) in the above example, use the index for optimizing GROUP BY.

Row sorting by GROUP BY is not required, because you can get the result as the requested order on the index scan.

If the index consisting of the GROUP BY column and the first column of the index is NOT NULL, even though there is no WHERE clause, the GROUP BY optimization will be applied.

If there is an index made of GROUP BY columns even when using aggregate functions, GROUP BY optimization is applied.

CREATE INDEX i_T_a_b_c ON T(a, b, c);
SELECT a, MIN(b), c, MAX(b) FROM T WHERE a > 18 GROUP BY a, b;

Note

When a column of DISTINCT or a GROUP BY clause contains the subkey of a index, loose index scan adjusts the scope dynamically to unique values of the each columns constituting the partial key, and starts the search of a B-tree. Regarding this, see Loose Index Scan.

Example

CREATE TABLE tab (i INT, j INT, k INT);
CREATE INDEX i_tab_j_k ON tab (j, k);
INSERT INTO tab VALUES (1,2,3),(6,4,2),(3,4,1),(5,2,1),(1,5,5),(2,6,6),(3,5,4);

UPDATE STATISTICS on tab;

The following example shows that indexes consisting of tab(j,k) are used and no separate sorting process is required because GROUP BY is executed by j and k columns.

SELECT /*+ RECOMPILE */ j,k
FROM tab
WHERE j > 0
GROUP BY j,k;

--  the  selection from the query plan dump shows that the index i_tab_j_k was used and sorting was not necessary
--  (/* ---> skip GROUP BY */)
Query plan:
iscan
    class: tab node[0]
    index: i_tab_j_k term[0]
    sort:  2 asc, 3 asc
    cost:  1 card 0

Query stmt:
select tab.i, tab.j, tab.k from tab tab where ((tab.j> ?:0 )) group by tab.j, tab.k
/* ---> skip GROUP BY */
            i            j            k
            5            2            1
            1            2            3
            3            4            1
            6            4            2
            3            5            4
            1            5            5
            2            6            6

The following example shows that an index consisting of tab(j,k) is used and no separate sorting process is required while GROUP BY is executed by j and k columns, no condition exists for j, and j column has NOT NULL attribute.

ALTER TABLE tab CHANGE COLUMN j j INT NOT NULL;

SELECT *
FROM tab
GROUP BY j,k;
--  the  selection from the query plan dump shows that the index i_tab_j_k was used (since j has the NOT NULL constraint )
--  and sorting was not necessary (/* ---> skip GROUP BY */)
Query plan:
iscan
    class: tab node[0]
    index: i_tab_j_k
    sort:  2 asc, 3 asc
    cost:  1 card 0

Query stmt: select tab.i, tab.j, tab.k from tab tab group by tab.j, tab.k
/* ---> skip GROUP BY */
=== <Result of SELECT Command in Line 1> ===
            i            j            k
=======================================
            5            2            1
            1            2            3
            3            4            1
            6            4            2
            3            5            4
            1            5            5
            2            6            6
CREATE TABLE tab (k1 int, k2 int, k3 int, v double);
INSERT INTO tab
    SELECT
        RAND(CAST(UNIX_TIMESTAMP() AS INT)) MOD 5,
        RAND(CAST(UNIX_TIMESTAMP() AS INT)) MOD 10,
        RAND(CAST(UNIX_TIMESTAMP() AS INT)) MOD 100000,
        RAND(CAST(UNIX_TIMESTAMP() AS INT)) MOD 100000
    FROM db_class a, db_class b, db_class c, db_class d LIMIT 20000;
CREATE INDEX idx ON tab(k1, k2, k3);

If you create tables and indexes of the above, the following example runs the GROUP BY with k1, k2 columns and performs an aggregate function in k3; therefore, the index which consists of tab(k1, k2, k3) is used and no sort processing is required. In addition, because all columns of k1, k2, k3 of ** SELECT ** list are present in the index configured in the tab(k1, k2, k3), covering index is applied.

SELECT /*+ RECOMPILE INDEX_SS */ k1, k2, SUM(DISTINCT k3)
FROM tab
WHERE k2 > -1 GROUP BY k1, k2;
Query plan:

iscan
    class: tab node[0]
    index: idx term[0] (covers) (index skip scan)
    sort:  1 asc, 2 asc
    cost:  85 card 2000

Query stmt:

select tab.k1, tab.k2, sum(distinct tab.k3) from tab tab where (tab.k2> ?:0 ) group by tab.k1, tab.k2

/* ---> skip GROUP BY */

The following example performs GROUP BY clause with k1, k2 columns; therefore, the index composed with tab(k1, k2, k3) is used and no sort processing is required. However, v column in the SELECT list is not present in the index composed of tab(k1, k2, k3); therefore, it does not apply covering index.

SELECT /*+ RECOMPILE INDEX_SS */ k1, k2, stddev_samp(v)
FROM tab
WHERE k2 > -1 GROUP BY k1, k2;
Query plan:

iscan
    class: tab node[0]
    index: idx term[0] (index skip scan)
    sort:  1 asc, 2 asc
    cost:  85 card 2000

Query stmt:

select tab.k1, tab.k2, stddev_samp(tab.v) from tab tab where (tab.k2> ?:0 ) group by tab.k1, tab.k2

/* ---> skip GROUP BY */
Multiple Key Ranges Optimization

Optimizing the LIMIT clause is crucial for performance because the most queries have limit filter. A representative optimization of this case is Multiple Key Ranges Optimization.

Multiple Key Ranges Optimization generate the query result with Top N Sorting to scan only some key ranges in an index rather than doing a full index scan. Top N Sorting always keeps the best N tuples sorted rather than selecting all tuples and then sorting. Therefore, it shows the outstanding performance.

For example, when you search only the recent 10 posts which your friends wrote, CUBRID which applied Multiple KEY Ranges Optimization finds the result not by sorting after finding all your friends' posts, but by scanning the index which keeps the recent 10 sorted posts of each friends.

An example of Multiple Key Ranges Optimization is as follows.

CREATE TABLE t (a int, b int);
CREATE INDEX i_t_a_b ON t (a,b);

-- Multiple key range optimization
SELECT *
FROM t
WHERE a IN (1,2,3)
ORDER BY b
LIMIT 2;
Query plan:
iscan
class: t node[0]
index: i_t_a_b term[0] (covers) (multi_range_opt)
sort: 1 asc, 2 asc
cost: 1 card 0

On a single table, multiple key range optimization can be applied if below conditions are satisfied.

SELECT /*+ hints */ ...
FROM table
WHERE col_1 = ? AND col_2 = ? AND ... AND col(j-1) = ?
AND col_(j) IN (?, ?, ...)
AND col_(j+1) = ? AND ... AND col_(p-1) = ?
AND key_filter_terms
ORDER BY col_(p) [ASC|DESC], col_(p+1) [ASC|DESC], ... col_(p+k-1) [ASC|DESC]
LIMIT n;

Firstly, upper limit(n) for LIMIT should be less than or equal to the value of multi_range_optimization_limit system parameter.

And you need the proper index to the multiple key range optimization, this index should cover all k columns specified in the ORDER BY clause. In other words, this index should include all k columns specified in the ORDER BY clause and the sorting order should be the same as the columns' order. Also this index should include all columns used in WHERE clause.

Among columns that comprise the index,

  • Columns in front of range condition(e.g. IN condition) are represented as equivalent condition(=).
  • Only one column with range condition exists.
  • Columns after range condition exist as key filters.
  • There should be no data filtering condition. In other words, the index should include all columns used in WHERE clause.
  • Columns after the key filter exist in ORDER BY clause.
  • Columns of key filter condition always should not the column of ORDER BY clause.
  • If key filter condition with correlated subquery exists, related columns to this should be included into WHERE clause with no range condition.

On the below example, Multiple Key Ranges Optimization can be applied.

CREATE TABLE t (a INT, b INT, c INT, d INT, e INT);
CREATE INDEX i_t_a_b ON t (a,b,c,d,e);

SELECT *
FROM t
WHERE a = 1 AND b = 3 AND c IN (1,2,3) AND d = 3
ORDER BY e
LIMIT 2;

Queries with multiple joined tables can also support Multiple Key Ranges Optimization:

SELECT /*+ hints */ ...
FROM table_1, table_2, ... table_(sort), ...
WHERE col_1 = ? AND col_2 = ? AND ...
AND col_(j) IN (?, ?, ... )
AND col_(j+1) = ? AND ... AND col_(p-1) = ?
AND key_filter_terms
AND join_terms
ORDER BY col_(p) [ASC|DESC], col_(p+1) [ASC|DESC], ... col_(p+k-1) [ASC|DESC]
LIMIT n;

If queries with multiple joined tables can support Multiple Key Ranges Optimization, below conditions should be satisfied:

  • Columns in ORDER BY clause only exist on one table, and this table should satisfy all required conditions by Multiple Key Ranges Optimization on a single table query. Let the "sort table" be the table that contains all sorting columns.
  • All columns of "sort table" specified in a JOIN condition between "sort table" and "outer tables" should be included on an index. In other words, there should be no data filtering condition.
  • All columns of "sort table" specified in a JOIN condition between "sort table" and "outer tables" should be included on the WHERE clause with no range condition.

Note

In most cases available to apply Multiple Key Ranges Optimization, this optimization shows the best performance. However, if you do not want this optimization on the special case, specify NO_MULTI_RANGE_OPT hint to the query. For details, see Using SQL Hint.

Index Skip Scan

Index Skip Scan (here after ISS) is an optimization method that allows ignoring the first column of an index when the first column of the index is not included in the condition but the following column is included in the condition (in most cases, =).

Applying ISS is considered when INDEX_SS for specific tables is specified through a query hint and the below cases are satisfied.

  1. The query condition should be specified from the second column of the composite index.
  2. The used index should not be a filtered index.
  3. The first column of an index should not be a range filter or key filter.
  4. A hierarchical query is not supported.
  5. A query which an aggregate function is included is not supported.

In a INDEX_SS hint, a list of table to consider applying ISS, can be input; if a list of table is omitted, applying ISS for all tables can be considered.

/*+ INDEX_SS */
/*+ INDEX_SS(tbl1) */
/*+ INDEX_SS(tbl1, tbl2) */

Note

When "INDEX_SS" is input, the ISS hint is applied to all tables; when "INDEX_SS()" is input, this hint is ignored.

CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b INT, c INT);
CREATE TABLE t2 (id INT PRIMARY KEY, a INT, b INT, c INT);
CREATE INDEX i_t1_ac ON t1(a,c);
CREATE INDEX i_t2_ac ON t2(a,c);

INSERT INTO t1 SELECT rownum, rownum, rownum, rownum
FROM db_class x1, db_class x2, db_class LIMIT 10000;

INSERT INTO t2 SELECT id, a%5, b, c FROM t1;


SELECT /*+ INDEX_SS */ *
FROM t1, t2
WHERE t1.b<5 AND t1.c<5 AND t2.c<5
USING INDEX i_t1_ac, i_t2_ac limit 1;

SELECT /*+ INDEX_SS(t1) */ *
FROM t1, t2
WHERE t1.b<5 AND t1.c<5 AND t2.c<5
USING INDEX i_t1_ac, i_t2_ac LIMIT 1;

SELECT /*+ INDEX_SS(t1, t2) */ *
FROM t1, t2
WHERE t1.b<5 AND t1.c<5 AND t2.c<5
USING INDEX i_t1_ac, i_t2_ac LIMIT 1;

Generally, ISS should consider several columns (C1, C2, ..., Cn). Here, a query has the conditions for the consecutive columns and the conditions are started from the second column (C2) of the index.

INDEX (C1, C2, ..., Cn);

SELECT ... WHERE C2 = x AND C3 = y AND ... AND Cp = z; -- p <= n
SELECT ... WHERE C2 < x AND C3 >= y AND ... AND Cp BETWEEN (z AND w); -- other conditions than equal

The query optimizer eventually determines whether ISS is the most optimum access method based on the cost. ISS is applied under very specific situations, such as when the first column of an index has a very small number of DISTINCT values compared to the number of records. In this case, ISS provides higher performance compared to Index Full Scan. For example, when the first column of index columns has very low cardinality, such as the value of men/women or millions of records with the value of 1~100, it may be inefficient to perform index scan by using the first column value. So ISS is useful in this case.

ISS skips reading most of the index pages in the disk and uses range search which is dynamically readjusted. Generally, ISS can be applied to a specific scenario when the number of DISTINCT values in the first column is very small. If ISS is applied to this case, ISS provides significantly higher performance than the index full scan. However, it means improper index creation that ISS is applied to a lot queries. So DBA should consider whether readjusting the indexes or not.

CREATE TABLE tbl (name STRING, gender CHAR (1), birthday DATETIME);

INSERT INTO tbl
SELECT ROWNUM, CASE (ROWNUM MOD 2) WHEN 1 THEN 'M' ELSE 'F' END, SYSDATETIME
FROM db_class a, db_class b, db_class c, db_class d, db_class e LIMIT 360000;

CREATE INDEX idx_tbl_gen_name ON tbl (gender, name);
-- Note that gender can only have 2 values, 'M' and 'F' (low cardinality)

UPDATE STATISTICS ON ALL CLASSES;
-- csql>;plan simple
-- this will qualify to use Index Skip Scanning
SELECT /*+ RECOMPILE INDEX_SS */ *
FROM tbl
WHERE name = '1000';
Query plan:

 Index scan(tbl tbl, idx_tbl_gen_name, tbl.[name]= ?:0  (index skip scan))
-- csql>;plan simple
-- this will qualify to use Index Skip Scanning
SELECT /*+ RECOMPILE INDEX_SS */ *
FROM tbl
WHERE name between '1000' and '1050';
Query plan:

 Index scan(tbl tbl, idx_tbl_gen_name, (tbl.[name]>= ?:0  and tbl.[name]<= ?:1 ) (index skip scan))
Loose Index Scan

When GROUP BY clause or DISTINCT column includes a subkey of a index, loose index scan starts B-tree search by adjusting the range dynamically for unique value of each of the columns that make up the subkey. Therefore, it is possible to significantly reduce the scanning area of B-tree.

Applying loose index scan is advantageous when the cardinality of the grouped column is very small, compared to the total data amount.

Loose index scan optimization is considered to be applied when INDEX_LS is input as a hint and the below cases are satisfied:

  1. when an index covers all SELECT list, that is, covered index is applied.
  2. when the statement is SELECT DISTINCT, SELECT ... GROUP BY statement or a single tuple SELECT.
  3. all aggregate functions (with the exception of MIN/MAX) must have DISTINCT input
  4. COUNT(*) should not be used
  5. when cardinality of the used subkey is 100 times smaller than the cardinality of the whole index

a subkey is a prefix part in a composite index; e.g. when there is INDEX(a, b, c, d), (a), (a, b) or (a, b, c) belongs to the subkey.

When you run the below query regarding the above table,

SELECT /*+ INDEX_LS */ a, b FROM tbl GROUP BY a;

CUBRID cannot use a subkey because there is no condition for the column a. However, if the condition of the subkey is specified as follows, loose index scan can be applied.

SELECT /*+ INDEX_LS */ a, b FROM tbl WHERE a > 10 GROUP BY a;

As follows, a subkey can be used when the grouped column is on the first and the WHERE-condition column is on the following position; therefore, also in this case, loose index scan can be applied.

SELECT /*+ INDEX_LS */ a, b FROM tbl WHERE b > 10 GROUP BY a;

The following shows the cases when loose index scan optimization is applied.

CREATE TABLE tbl1 (
    k1 INT,
    k2 INT,
    k3 INT,
    k4 INT
);

INSERT INTO tbl1
SELECT ROWNUM MOD 2, ROWNUM MOD 400, ROWNUM MOD 80000, ROWNUM
FROM db_class a, db_class b, db_class c, db_class d, db_class e LIMIT 360000;

CREATE INDEX idx ON tbl1 (k1, k2, k3);

CREATE TABLE tbl2 (
    k1 INT,
    k2 INT
);

INSERT INTO tbl2 VALUES (0, 0), (1, 1), (0, 2), (1, 3), (0, 4), (0, 100), (1000, 1000);

UPDATE STATISTICS ON ALL CLASSES;
-- csql>;plan simple
-- add a condition to the grouped column, k1 to enable loose index scan
SELECT /*+ RECOMPILE INDEX_LS */ DISTINCT k1
FROM tbl1
WHERE k1 > -1000000 LIMIT 20;
Query plan:

 Sort(distinct)
    Index scan(tbl1 tbl1, idx, (tbl1.k1> ?:0 ) (covers) (loose index scan on prefix 1))
-- csql>;plan simple
-- different key ranges/filters
SELECT /*+ RECOMPILE INDEX_LS */ DISTINCT k1
FROM tbl1
WHERE k1 >= 0 AND k1 <= 1;
Query plan:

 Sort(distinct)
    Index scan(tbl1 tbl1, idx, (tbl1.k1>= ?:0  and tbl1.k1<= ?:1 ) (covers) (loose index scan on prefix 1))
-- csql>;plan simple
SELECT /*+ RECOMPILE INDEX_LS */ DISTINCT k1, k2
FROM tbl1
WHERE k1 >= 0 AND k1 <= 1 AND k2 > 3 AND k2 < 11;
Query plan:

 Sort(distinct)
    Index scan(tbl1 tbl1, idx, (tbl1.k1>= ?:0  and tbl1.k1<= ?:1 ), [(tbl1.k2> ?:2  and tbl1.k2< ?:3 )] (covers) (loose index scan on prefix 2))
-- csql>;plan simple
SELECT /*+ RECOMPILE INDEX_LS */ DISTINCT k1, k2
FROM tbl1
WHERE k1 >= 0 AND k1 + k2 <= 10;
Query plan:

 Sort(distinct)
    Index scan(tbl1 tbl1, idx, (tbl1.k1>= ?:0 ), [tbl1.k1+tbl1.k2<=10] (covers) (loose index scan on prefix 2))
-- csql>;plan simple
SELECT /*+ RECOMPILE INDEX_LS */ tbl1.k1, tbl1.k2
FROM tbl2 INNER JOIN tbl1
ON tbl2.k1 = tbl1.k1 AND tbl2.k2 = tbl1.k2
GROUP BY tbl1.k1, tbl1.k2;
Sort(group by)
   Nested loops
       Sequential scan(tbl2 tbl2)
       Index scan(tbl1 tbl1, idx, tbl2.k1=tbl1.k1 and tbl2.k2=tbl1.k2 (covers) (loose index scan on prefix 2))
SELECT /*+ RECOMPILE INDEX_LS */ MIN(k2), MAX(k2)
FROM tbl1;
Query plan:

 Index scan(tbl1 tbl1, idx (covers) (loose index scan on prefix 2))
-- csql>;plan simple
SELECT /*+ RECOMPILE INDEX_LS */ SUM(DISTINCT k1), SUM(DISTINCT k2)
FROM tbl1;
Query plan:

 Index scan(tbl1 tbl1, idx (covers) (loose index scan on prefix 2))
-- csql>;plan simple
SELECT /*+ RECOMPILE INDEX_LS */ DISTINCT k1
FROM tbl1
WHERE k2 > 0;
Query plan:

 Sort(distinct)
    Index scan(tbl1 tbl1, idx, [(tbl1.k2> ?:0 )] (covers) (loose index scan on prefix 2))

The following shows the cases when loose index scan optimization is not applied.

-- csql>;plan simple
-- not enabled when full key is used
SELECT /*+ RECOMPILE INDEX_LS */ DISTINCT k1, k2, k3
FROM tbl1
ORDER BY 1, 2, 3 LIMIT 10;
Query plan:

 Sort(distinct)
    Sequential scan(tbl1 tbl1)
-- csql>;plan simple
SELECT /*+ RECOMPILE INDEX_LS */ k1, k2, k3
FROM tbl1
WHERE k1 > -10000 GROUP BY k1, k2, k3 LIMIT 10;
Query plan:

 Index scan(tbl1 tbl1, idx, (tbl1.k1> ?:0 ) (covers))
 skip GROUP BY
-- csql>;plan simple
-- not enabled when using count star
SELECT /*+ RECOMPILE INDEX_LS */ COUNT(*), k1
FROM tbl1
WHERE k1 > -10000 GROUP BY k1;
Query plan:

 Index scan(tbl1 tbl1, idx, (tbl1.k1> ?:0 ) (covers))
 skip GROUP BY
-- csql>;plan simple
-- not enabled when index is not covering
SELECT /*+ RECOMPILE INDEX_LS */ k1, k2, SUM(k4)
FROM tbl1
WHERE k1 > -1 AND k2 > -1 GROUP BY k1, k2 LIMIT 10;
Query plan:

 Index scan(tbl1 tbl1, idx, (tbl1.k1> ?:0 ), [(tbl1.k2> ?:1 )])
 skip GROUP BY
-- csql>;plan simple
-- not enabled for non-distinct aggregates
SELECT /*+ RECOMPILE INDEX_LS */ k1, SUM(k2)
FROM tbl1
WHERE k1 > -1 GROUP BY k1;
Query plan:

 Index scan(tbl1 tbl1, idx, (tbl1.k1> ?:0 ) (covers))
 skip GROUP BY
-- csql>;plan simple
SELECT /*+ RECOMPILE */ SUM(k1), SUM(k2)
FROM tbl1;
Query plan:

 Sequential scan(tbl1 tbl1)
In Memory Sort

The "in memory sort(IMS)" feature is an optimization applied to the LIMIT queries specifying ORDER BY. Normally, when executing a query which specifies ORDER BY and LIMIT clauses, CUBRID generates the full sorted result set and then applies the LIMIT operator to this result set. With the IMS optimization, instead of generating the whole result set, CUBRID uses an in-memory binary heap in which only tuples satisfying the ORDER BY and LIMIT clauses are allowed. This optimization improves performance by eliminating the need for a full unordered result set.

Whether this optimization is applied or not is not transparent to users. CUBRID decides to use in memory sort in the following situation:

  • The query specifies ORDER BY and LIMIT clauses.
  • The size of the final result (after applying the LIMIT clause) is less than the amount of memory used by external sort (see sort_buffer_size in Memory-Related Parameters).

Note that IMS considers the actual size of the result and not the count of tuples the result contains. For example, for the default sort buffer size (two megabytes), this optimization will be applied for a LIMIT value of 524,288 tuples consisting of one 4 byte INTEGER type but only for ~2,048 tuples of CHAR(1024) values. This optimization is not applied to queries requiring DISTINCT ordered result sets.

SORT-LIMIT optimization

The SORT-LIMIT optimization applies to queries specifying ORDER BY and LIMIT clauses. The idea behind it is to evaluate the LIMIT operator as soon as possible in the query plan in order to benefit from the reduced cardinality during joins.

A SORT-LIMIT plan can be generated when the following conditions are met:

  • All referred tables in the ORDER BY clause belong to the SORT-LIMIT plan.

  • A table belonging to a SORT-LIMIT plan is either:

    • The owner of a foreign key from a fk->pk join
    • The left side of a LEFT JOIN.
    • The right side of a RIGHT JOIN.
  • LIMIT rows should be specified as less rows than the value of sort_limit_max_count system parameter(default: 1000).

  • Query does not have cross joins.

  • Query joins at least two relations.

  • Query does not have a GROUP BY clause.

  • Query does not specify DISTINCT.

  • ORDER BY expressions can be evaluated during scan.

    For example, the below query cannot apply SORT-LIMIT plan because SUM cannot be evaluated during scan.

    SELECT SUM(u.i) FROM u, t where u.i = t.i ORDER BY 1 LIMIT 5;
    

The below is an example of planning SORT-LIMIT.

CREATE TABLE t(i int PRIMARY KEY, j int, k int);
CREATE TABLE u(i int, j int, k int);
ALTER TABLE u ADD constraint fk_t_u_i FOREIGN KEY(i) REFERENCES t(i);
CREATE INDEX i_u_j ON u(j);

INSERT INTO t SELECT ROWNUM, ROWNUM, ROWNUM FROM _DB_CLASS a, _DB_CLASS b LIMIT 1000;
INSERT INTO u SELECT 1+(ROWNUM % 1000), RANDOM(1000), RANDOM(1000) FROM _DB_CLASS a, _DB_CLASS b, _DB_CLASS c LIMIT 5000;

SELECT /*+ RECOMPILE */ * FROM u, t WHERE u.i = t.i AND u.j > 10 ORDER BY u.j LIMIT 5;

The above SELECT query's plan is printed out as below; we can see "(sort limit)".

Query plan:

idx-join (inner join)
    outer: temp(sort limit)
               subplan: iscan
                            class: u node[0]
                            index: i_u_j term[1]
                            cost:  1 card 0
               cost:  1 card 0
    inner: iscan
               class: t node[1]
               index: pk_t_i term[0]
               cost:  6 card 1000
    sort:  2 asc
    cost:  7 card 0

Partitioning

Partitioning is a method by which a table is divided into multiple independent physical units called partitions. In CUBRID, each partition is a table implemented as a subclass of the partitioned table. Each partition holds a subset of the partitioned table data defined by a Partitioning key and a partitioning method. Users can access data stored in partitions by executing statements on the partitioned table. This means that users can partition tables without modifying statements or code that is used to access these tables (benefiting from the advantages of partitioning almost without modifying the user application).

Partitioning can enhance manageability, performance and availability. Some advantages of partitioning a table are:

  • Improved management of large capacity tables
  • Improved performance by narrowing the range of access when retrieving data
  • Improved performance and decreased physical loads by distributing disk I/O
  • Decreased possibility of data corruption and improved availability by partitioning a table into multiple chunks
  • Optimized storage cost

Partitioned data is auto-managed by CUBRID. INSERT and UPDATE statements executed on partitioned tables perform an additional step during execution to identify the partition in which a tuple must be placed. During UPDATE statement execution, CUBRID identifies situations in which the modified tuple should be moved to another partition and performs this operation keeping the partitioning definition consistent. Inserting tuples for which there is no valid partition will return an error.

When executing SELECT statements, CUBRID applies a procedure called Partition Pruning to narrow the search space to only those partitions for which the search predicates will produce results. Pruning (eliminating) most of the partitions during a SELECT statement greatly improves performance.

Table partitioning is most effective when applied to large tables. Exactly what a "large" table means is dependent on the user application and on the way in which the table is used in queries. Which is the best partitioning method (range, list or hash) for a table, also depends on how the table is used in queries and how data will be distributed between partitions. Even though partitioned tables can be used just like normal tables, there are some Notes on Partitioning which should be taken into consideration.

Partitioning key

The partitioning key is an expression which is used by the partitioning method to distribute data across defined partitions. The following data types are supported for the partitioning key:

  • CHAR
  • VARCHAR
  • SMALLINT
  • INT
  • BIGINT
  • DATE
  • TIME
  • TIMESTAMP
  • DATETIME

The following restrictions apply to the partitioning key:

Range Partitioning

Range partitioning is a partitioning method in which a table is partitioned using a user specified range of values of the partitioning key for each partition. Ranges are defined as continuous non-overlapping intervals. This partitioning method is most useful when table data can be divided into range intervals (e.g. order placement date for an orders table or age intervals for a user's table). Range partitioning is the most versatile partitioning method in terms of Partition Pruning because almost all search predicates can be used to identify matching ranges.

Tables can be partitioned by range by using the PARTITION BY RANGE clause in CREATE or ALTER statements.

CREATE TABLE table_name (
   ...
)
PARTITION BY RANGE ( <partitioning_key> ) (
    PARTITION partition_name VALUES LESS THAN ( <range_value> ) [COMMENT 'comment_string'] ,
    PARTITION partition_name VALUES LESS THAN ( <range_value> ) [COMMENT 'comment_string'] ,
    ...
)

ALTER TABLE table_name
PARTITION BY RANGE ( <partitioning_key> ) (
    PARTITION partition_name VALUES LESS THAN ( <range_value> ) [COMMENT 'comment_string'] ,
    PARTITION partition_name VALUES LESS THAN ( <range_value> ) [COMMENT 'comment_string'] ,
    ...
)
  • partitioning_key : specifies the Partitioning key.
  • partition_name : specifies the partition name.
  • range_value : specifies the upper limit of the partitioning key value. All tuples for which the evaluation of partitioning key is less than (but not equal to) the range_value will be stored in this partition.
  • comment_string: specifies a comment for each partition.

The following example shows how to create the participant2 table which holds countries participating at the Olympics and partition this table into partitions holding participants before year 2000(before_2000 partition) and participants before year 2008(before_2008 partition):

CREATE TABLE participant2 (
    host_year INT,
    nation CHAR(3),
    gold INT,
    silver INT,
    bronze INT
)
PARTITION BY RANGE (host_year) (
    PARTITION before_2000 VALUES LESS THAN (2000),
    PARTITION before_2008 VALUES LESS THAN (2008)
);

When creating partitions, CUBRID sorts the user supplied range values from smallest to largest and creates the non-overlapping intervals from the sorted list. In the above example, the created range intervals are [-inf, 2000) and [2000, 2008). The identifier MAXVALUE can be used to specify an infinite upper limit for a partition.

ALTER TABLE participant2 ADD PARTITION (
  PARTITION before_2012 VALUES LESS THAN (2012),
  PARTITION last_one VALUES LESS THAN MAXVALUE
);

When inserting a tuple into a range-partitioned table, CUBRID identifies the range to which the tuple belongs by evaluating the partitioning key. If the partitioning key value is NULL, the data is stored in the partition with the smallest specified range value. If there is no range which would accept the partitioning key value, CUBRID returns an error. CUBRID also returns an error when updating a tuple if the new value of the partitioning key does not belong to any of the defined ranges.

The below is an example to add a comment for each partition.

CREATE TABLE tbl (a int, b int) PARTITION BY RANGE(a) (
    PARTITION less_1000 VALUES LESS THAN (1000) COMMENT 'less 1000 comment',
    PARTITION less_2000 VALUES LESS THAN (2000) COMMENT 'less 2000 comment'
);

ALTER TABLE tbl PARTITION BY RANGE(a) (
    PARTITION less_1000 VALUES LESS THAN (1000) COMMENT 'new partition comment');

To see a partition comment, refer to COMMENT of Partition.

Hash Partitioning

Hash partitioning is a partitioning method which is used to distribute data across a specified number of partition. This partitioning method is useful when table data contains values for which ranges or lists would be meaningless (for example, a keywords table or an users table for which user_id is the most interesting value). If the values for the partitioning key are evenly distributed across the table data, hash-partitioning technique divides table data evenly between the defined partitions. For hash partitioning, Partition Pruning can only be applied on equality predicates (e.g. predicates using = and IN expressions), making hash partitioning useful only if most of the queries specify such a predicate for the partitioning key.

Tables can be partitioned by hash by using the PARTITION BY HASH clause in CREATE or ALTER statements:

CREATE TABLE table_name (
   ...
)
PARTITION BY HASH ( <partitioning_key> )
PARTITIONS ( number_of_partitions )

ALTER TABLE table_name
PARTITION BY HASH (<partitioning_key>)
PARTITIONS (number_of_partitions)
  • partitioning_key : Specifies the Partitioning key.
  • number_of_partitions : Specifies the number of partitions to be created.

The following example shows how to create the nation2 table with country code and country names, and define 4 hash partitions based on code values. Only the number of partitions, not the name, is defined in hash partitioning.

CREATE TABLE nation2 (
  code CHAR (3),
  name VARCHAR (50)
)
PARTITION BY HASH (code) PARTITIONS 4;

When a value is inserted into a hash-partitioned table, the partition to store the data is determined by the hash value of the partitioning key. If the partitioning key value is NULL, the data is stored in the first partition.

List Partitioning

List partitioning is a partitioning method in which a table is divided into partitions according to user specified list of values for the partitioning key. The lists of values for partitions must be disjoint sets. This partitioning method is useful when table data can be divided into lists of possible values which have a certain meaning (e.g. department id for an employees table or country code for a user's table). As for hash partitioning, Partition Pruning for list partitioned tables can only be applied on equality predicates (e.g. predicates using = and IN expressions).

Tables can be partitioned by list by using the PARTITION BY LIST clause in CREATE or ALTER statements:

CREATE TABLE table_name (
  ...
)
PARTITION BY LIST ( <partitioning_key> ) (
  PARTITION partition_name VALUES IN ( <values_list> ) [COMMENT 'comment_string'],
  PARTITION partition_name VALUES IN ( <values_list> ) [COMMENT 'comment_string'],
  ...
)

ALTER TABLE table_name
PARTITION BY LIST ( <partitioning_key> ) (
  PARTITION partition_name VALUES IN ( <values_list> ) [COMMENT 'comment_string'],
  PARTITION partition_name VALUES IN ( <values_list> ) [COMMENT 'comment_string'],
  ...
)
  • partitioning_key: specifies the Partitioning key.
  • partition_name: specifies the partition name.
  • value_list: specifies the list of values for the partitioning key.
  • comment_string: specifies a comment for each partition.

The following example shows how to create the athlete2 table with athlete names and sport events, and define list partitions based on event values.

CREATE TABLE athlete2 (name VARCHAR (40), event VARCHAR (30))
PARTITION BY LIST (event) (
    PARTITION event1 VALUES IN ('Swimming', 'Athletics'),
    PARTITION event2 VALUES IN ('Judo', 'Taekwondo', 'Boxing'),
    PARTITION event3 VALUES IN ('Football', 'Basketball', 'Baseball')
);

When inserting a tuple into a list-partitioned table, the value of the partitioning key must belong to one of the value lists defined for partitions. For this partitioning model, CUBRID does not automatically assign a partition for NULL values of the partitioning key. To be able to store NULL values into a list-partitioned table, a partition which includes the NULL value in the values list must be created:

CREATE TABLE athlete2 (name VARCHAR (40), event VARCHAR (30))
PARTITION BY LIST (event) (
    PARTITION event1 VALUES IN ('Swimming', 'Athletics' ),
    PARTITION event2 VALUES IN ('Judo', 'Taekwondo', 'Boxing'),
    PARTITION event3 VALUES IN ('Football', 'Basketball', 'Baseball', NULL)
);

The below is examples of adding comments for each partition.

CREATE TABLE athlete2 (name VARCHAR (40), event VARCHAR (30))
PARTITION BY LIST (event) (
    PARTITION event1 VALUES IN ('Swimming', 'Athletics') COMMENT 'G1',
    PARTITION event2 VALUES IN ('Judo', 'Taekwondo', 'Boxing') COMMENT 'G2',
    PARTITION event3 VALUES IN ('Football', 'Basketball', 'Baseball') COMMENT 'G3');

CREATE TABLE athlete3 (name VARCHAR (40), event VARCHAR (30));
ALTER TABLE athlete3 PARTITION BY LIST (event) (
    PARTITION event1 VALUES IN ('Handball', 'Volleyball', 'Tennis') COMMENT 'G1');
COMMENT of Partition

A partition's comment can be written only for the range partition and the list partition. You cannot write the comment about the hash partition. The partition comment can be shown by running this syntax.

SHOW CREATE TABLE table_name;
SELECT class_name, partition_name, COMMENT FROM db_partition WHERE class_name ='table_name';

Or you can use CSQL interpreter by running ;sc command.

$ csql -u dba demodb

csql> ;sc tbl
Partition Pruning

Partition pruning is an optimization method, limiting the scope of a search on a partitioned table by eliminating partitions. During partition pruning, CUBRID examines the WHERE clause of the query to identify partitions for which this clause is always false, as considering the way partitioning was defined. In the following example, the SELECT query will only be applied to partitions before_2008 and before_2012, since CUBRID knows that the rest of partitions hold data for which YEAR (opening_date) is less than 2004.

CREATE TABLE olympic2 (opening_date DATE, host_nation VARCHAR (40))
PARTITION BY RANGE (YEAR(opening_date)) (
    PARTITION before_1996 VALUES LESS THAN (1996),
    PARTITION before_2000 VALUES LESS THAN (2000),
    PARTITION before_2004 VALUES LESS THAN (2004),
    PARTITION before_2008 VALUES LESS THAN (2008),
    PARTITION before_2012 VALUES LESS THAN (2012)
);

SELECT opening_date, host_nation
FROM olympic2
WHERE YEAR(opening_date) > 2004;

Partition pruning greatly reduces the disk I/O and the amount of data which must be processed during query execution. It is important to understand when pruning is performed in order to fully benefit from it. In order for CUBRID to successfully prune partitions, the following conditions have to be met:

  • Partitioning key must be used in the WHERE clause directly (without applying other expressions to it)
  • For range-partitioning, the partitioning key must be used in range predicates (<, >, BETWEEN, etc) or equality predicates (=, IN, etc).
  • For list and hash partitioning, the partitioning key must be used in equality predicates (=, IN, etc).

The following queries explain how pruning is performed on the olympic2 table from the example above:

-- prune all partitions except before_2012
SELECT host_nation
FROM olympic2
WHERE YEAR (opening_date) >= 2008;

-- prune all partitions except before_2008
SELECT host_nation
FROM olympic2
WHERE YEAR(opening_date) BETWEEN 2005 and 2007;

-- no partition is pruned because partitioning key is not used
SELECT host_nation
FROM olympic2
WHERE opening_date = '2008-01-02';

-- no partition is pruned because partitioning key is not used directly
SELECT host_nation
FROM olympic2
WHERE YEAR(opening_date) + 1 = 2008;

-- no partition is pruned because there is no useful predicate in the WHERE clause
SELECT host_nation
FROM olympic2
WHERE YEAR(opening_date) != 2008;

Note

In versions older than CUBRID 9.0, partition pruning was performed during query compilation stage. Starting with CUBRID 9.0, partition pruning is performed during the query execution stage, because executing partition pruning during query execution allows CUBRID to apply this optimization on much more complex queries. However, pruning information is not displayed in query planning stage anymore, since query planning happens before query execution and this information is not available at that time.

Users can also access partitions directly (independent of the partitioned table) either by using the table name assigned by CUBRID to a partition or by using the table PARTITION (name) clause:

-- to specify a partition with its table name
SELECT * FROM olympic2__p__before_2008;

-- to specify a partition with PARTITION clause
SELECT * FROM olympic2 PARTITION (before_2008);

Both of the queries above access partition before_2008 as if it were a normal table (not a partition). This is a very useful feature because it allows certain query optimizations to be used even though they are disabled on partitioned tables (see Notes on Partitioning for more info). Users should note that, when accessing partitions directly, the scope of the query is limited to that partition. This means that tuples from other partitions are not considered (even though the WHERE clause includes them) and, for INSERT and UPDATE statements, if the tuple inserted/updated does not belong to the specified partition, an error is returned.

By executing queries on a partition rather than the partitioned table, some of the benefits of partitioning are lost. For example, if users only execute queries on the partitioned table, this table can be repartitioned or partitions can be dropped without having to modify the user application. If users access partitions directly, this benefit is lost. Users should also note that, even though using partitions in INSERT statements is allowed (for consistency), it is discouraged because there is no performance gain from it.

Partitioning Management

Partitioned tables can be managed using partition specific clauses of the ALTER statement. CUBRID allows several actions to be performed on partitions:

  1. Modifying a partitioned table into a regular table.
  2. Partitions reorganization.
  3. Adding partitions to an already partitioned table.
  4. Dropping partitions.
  5. Promote partitions to regular tables.
Modifying a Partitioned Table into a Regular Table

Changing a partitioned table into a regular table can be done using the REMOVE PARTITIONING clause of the ALTER statement:

ALTER {TABLE | CLASS} table_name REMOVE PARTITIONING
  • table_name : Specifies the name of the table to be altered.

When removing partitioning, CUBRID moves all data from partitions into the partitioned table. This is a costly operation and should be carefully planned.

Partition Reorganization

Partition reorganization is a process through which a partition can be divided into smaller partitions or a group of partitions can be merged into a single partition. For this purpose, CUBRID implements the REORGANIZE PARTITION clause of the ALTER statement:

ALTER {TABLE | CLASS} table_name
REORGANIZE PARTITION <alter_partition_name_comma_list>
INTO ( <partition_definition_comma_list> )

partition_definition_comma_list ::=
PARTITION partition_name VALUES LESS THAN ( <range_value> ), ...
  • table_name : Specifies the name of the table to be redefined.
  • alter_partition_name_comma_list : Specifies the partition to be redefined(current partitions). Multiple partitions are separated by commas (,).
  • partition_definition_comma_list : Specifies the redefined partitions(new partitions). Multiple partitions are separated by commas (,).

This clause applies only to range and list partitioning. Since data distribution in hash-partitioning method is semantically different, hash-partitioned tables only allow adding and dropping partitions. See Hash Partitioning Reorganization for details.

The following example shows how to reorganize the before_2000 partition of the participant2 table into the before_1996 and before_2000 partitions.

ALTER TABLE participant2
REORGANIZE PARTITION before_2000 INTO (
  PARTITION before_1996 VALUES LESS THAN (1996),
  PARTITION before_2000 VALUES LESS THAN (2000)
);

The following example shows how to merge the two partitions defined in the above example back into a single before_2000 partition.

ALTER TABLE participant2
REORGANIZE PARTITION before_1996, before_2000 INTO (
  PARTITION before_2000 VALUES LESS THAN (2000)
);

The following example shows how to reorganize partitions defined on the athlete2, dividing the event2 partition into event2_1 (Judo) and event2_2 (Taekwondo, Boxing).

ALTER TABLE athlete2
REORGANIZE PARTITION event2 INTO (
    PARTITION event2_1 VALUES IN ('Judo'),
    PARTITION event2_2 VALUES IN ('Taekwondo', 'Boxing')
);

The following example shows how to combine the event2_1 and event2_2 partitions back into a single event2 partition.

ALTER TABLE athlete2
REORGANIZE PARTITION event2_1, event2_2 INTO (
    PARTITION event2 VALUES IN ('Judo', 'Taekwondo', 'Boxing')
);

Note

  • In a range-partitioned table, only adjacent partitions can be reorganized.
  • During partition reorganization, CUBRID moves data between partitions in order to reflect the new partitioning schema. Depending on the size of the reorganized partitions, this might be a time consuming operations and should be carefully planned.
  • The REORGANIZE PARTITION clause cannot be used to change the partitioning method. For example, a range-partitioned table cannot be changed into a hash-partitioned one.
  • There must be at least one partition remaining after deleting partitions.
Adding Partitions

Partitions can be added to a partitioned table by using the ADD PARTITION clause of the ALTER statement.

ALTER {TABLE | CLASS} table_name
ADD PARTITION (<partition_definitions_comma_list>)
  • table_name : Specifies the name of the table to which partitions are added.
  • partition_definitions_comma_list : Specifies the partitions to be added. Multiple partitions are separated by commas (,).

The following example shows how to add the before_2012 and last_one partitions to the participant2 table.

ALTER TABLE participant2 ADD PARTITION (
  PARTITION before_2012 VALUES LESS THAN (2012),
  PARTITION last_one VALUES LESS THAN MAXVALUE
);

Note

  • For range-partitioned tables, range values for added partitions must be greater than the largest range value of the existing partitions.
  • For range-partitioned tables, if the upper limit of the range of one of the existing partitions is specified by MAXVALUE, ADD PARTITION clause will always return an error (the REORGANIZE PARTITION clause should be used instead).
  • The ADD PARTITION clause can only be used on already partitioned tables.
  • This clause has different semantics when executed on hash-partitioned tables. See Hash Partitioning Reorganization for details.
Dropping Partitions

Partitions can be dropped from a partitioned table by using the DROP PARTITION clause of the ALTER statement.

ALTER {TABLE | CLASS} table_name
DROP PARTITION partition_name_list
  • table_name : Specifies the name of the partitioned table.
  • <partition_name_list> : Specifies the names of the partitions to be dropped, separated by comma(,).

The following example shows how to drop the before_2000 partition in the participant2 table.

ALTER TABLE participant2 DROP PARTITION before_2000;

Note

  • When dropping a partition, all stored data in the partition is deleted. If you want to change the partitioning of a table without losing data, use the ALTER TABLE ... REORGANIZE PARTITION statement.
  • The number of rows deleted is not returned when a partition is dropped. If you want to delete the data, but want to maintain the table and partitions, use the DELETE statement.

This statement is not allowed on hash-partitioned tables. To drop partitions of a hash-partitioned table, use the hash partitioning specific alter clauses.

Hash Partitioning Reorganization

Because data distribution among partitions in a hash-partitioned table is controlled internally by CUBRID, hash-partitioning reorganization behaves differently for hash-partitioned tables than for list or range partitioned tables. CUBRID allows the number of partitions defined on a hash-partitioned table to be increased or reduced. When modifying the number of partitions of a hash-partitioned table, no data is lost. However, because the domain of the hashing function is modified, table data has to be redistributed between the new partitions in order to maintain hash-partitioning consistency.

The number of partitions defined on a hash-partitioned table can be reduced using the COALESCE PARTITION clause of the ALTER statement.

ALTER {TABLE | CLASS} table_name
COALESCE PARTITION number_of_shrinking_partitions
  • table_name : Specifies the name of the table to be redefined.
  • number_of_shrinking_partitions : Specifies the number of partitions to be deleted.

The following example shows how to decrease the number of partitions in the nation2 table from 4 to 3.

ALTER TABLE nation2 COALESCE PARTITION 1;

The number of partitions defined on a hash partitioned table can be increased using the ADD PARTITION clause of the ALTER statement.

ALTER {TABLE | CLASS} table_name
ADD PARTITION PARTITIONS number
  • table_name : Specifies the name of the table to be redefined.
  • number : Specifies the number of partitions to be added.

The following example shows how to add 3 partitions to the nation2.

ALTER TABLE nation2 ADD PARTITION PARTITIONS 3;
Partition Promotion

The PROMOTE clause of the ALTER statement promotes a partition of a partitioned table to a regular table. This feature is useful when a certain partition contains historic data which is almost never used. By promoting the partition to a regular table, performance on the partitioned table is increased and the data removed from this table (contained in the promoted partition) can still be accessed. Promoting a partition is an irreversible process, promoted partitions cannot be added back to the partitioned table.

The partition PROMOTE statement is allowed only on range and list-partitioned tables. Since users do not control how data is distributed among hash partitions, promoting such a partition does not make sense.

When the partition is promoted to a standalone table, this table inherits the data and ordinary indexes only. The following constraints are not available on the promoted partition:

  • Primary Key
  • Foreign key
  • Unique index
  • AUTO_INCREMENT attribute and serial
  • Triggers
  • Methods
  • Inheritance relationship (super-class and sub-class)

The syntax for promoting partitions is:

ALTER TABLE table_name PROMOTE PARTITION <partition_name_list>
  • partition_name_list: The user defined names of partitions to promote separated by comma(,)

The following example creates a partitioned table, inserts some tuples into it and then promotes two of its partitions:

CREATE TABLE t (i INT) PARTITION BY LIST (i) (
    PARTITION p0 VALUES IN (1, 2),
    PARTITION p1 VALUES IN (3, 4),
    PARTITION p2 VALUES IN (5, 6)
);

INSERT INTO t VALUES(1), (2), (3), (4), (5), (6);

Schema and data of table t are shown below.

csql> ;schema t
=== <Help: Schema of a Class> ===
...
 <Partitions>
     PARTITION BY LIST ([i])
     PARTITION p0 VALUES IN (1, 2)
     PARTITION p1 VALUES IN (3, 4)
     PARTITION p2 VALUES IN (5, 6)

csql> SELECT * FROM t;

=== <Result of SELECT Command in Line 1> ===
            i
=============
            1
            2
            3
            4
            5
            6

The following statement promotes partitions p0 and p2:

ALTER TABLE t PROMOTE PARTITION p0, p2;

After promotion, table t has only one partition (p1) and contains the following data.

csql> ;schema t
=== <Help: Schema of a Class> ===
 <Class Name>
     t
 ...
 <Partitions>
     PARTITION BY LIST ([i])
     PARTITION p1 VALUES IN (3, 4)

csql> SELECT * FROM t;

=== <Result of SELECT Command in Line 1> ===
            i
=============
            3
            4
Indexes on Partitioned Tables

All indexes created on a partitioning table are local indexes. With local indexes, data for each partition is stored in a separate(local) index. This increases concurrency on a partitioned table's indexes, since transactions access data from different partitions also do different, local, indexes.

In order to ensure local unique indexes, the following restriction must be satisfied when creating unique indexes on partitions:

  • The partitioning key must be part of the primary key's and the all the unique indexes' definition.

If this is not satisfied, CUBRID will return an error:

csql> CREATE TABLE t(i INT , j INT) PARTITION BY HASH (i) PARTITIONS 4;
Execute OK. (0.142929 sec) Committed.

1 command(s) successfully processed.
csql> ALTER TABLE t ADD PRIMARY KEY (i);
Execute OK. (0.123776 sec) Committed.

1 command(s) successfully processed.
csql> CREATE UNIQUE INDEX idx2 ON t(j);

In the command from line 1,

ERROR: Partition key attributes must be present in the index key.


0 command(s) successfully processed.

It is important to understand the benefits of local indexes. In a global index scan, for each partition that was not pruned a separate index scan would have been performed. This leads to poorer performance than scanning local indexes because data from other partitions is fetched from disk and then discarded (it belongs to another partition than the one being scanned at the moment). INSERT statements also show better performance on local indexes since these indexes are smaller.

Notes on Partitioning

Partitioned tables normally behave like regular tables. However there are some notes that should be taken into consideration in order to fully benefit from partitioning a table.

Statistics on Partitioning Tables

Since CUBRID 9.0, the clause ANALYZE PARTITION of the ALTER statement has been deprecated. Since partition pruning happens during query execution, this statement will not produce any useful results. Since 9.0, CUBRID keeps separated statistics on each partition. The statistics on the partitioned table are computed as a mean value of the statistics of the table partitions. This is done to optimize the usual case in which, for a query, all partitions are pruned except one.

Restrictions on Partitioned Tables

The following restrictions apply to partitioned tables:

  • The maximum number of partitions which can be defined on a table is 1,024.
  • Partitions cannot be a part of the inheritance chain. Classes cannot inherit a partition and partitions cannot inherit other classes than the partitioned class (which it inherits by default).
  • The following query optimizations are not performed on partitioned tables:
Partitioning Key and Charset, Collation

Partitioning keys and partition definition must have the same character set. The following query will return an error:

CREATE TABLE t (c CHAR(50) COLLATE utf8_bin)
PARTITION BY LIST (c) (
    PARTITION p0 VALUES IN (_utf8'x'),
    PARTITION p1 VALUES IN (_iso88591'y')
);
ERROR: Invalid codeset '_iso88591' for partition value. Expecting '_utf8' codeset.

CUBRID uses the collation defined on the table when performing comparisons on the partitioning key. The following example will return an error because, for utf8_en_ci collation 'test' equals 'TEST'.

CREATE TABLE tbl (str STRING) COLLATE utf8_en_ci
PARTITION BY LIST (str) (
    PARTITION p0 VALUES IN ('test'),
    PARTITION p1 VALUES IN ('TEST')
);
ERROR: Partition definition is duplicated. 'p1'

Globalization

Globalization includes internationalization and localization. Internationalization can be applied to various languages and regions. Localization fits the language and culture in a specific area as appending the language-specific components. CUBRID supports multilingual collations including Europe and Asia to facilitate the localization.

If you want to know overall information about character data setting, see Configuration Guide for Characters.

If you want to know about charset, collation and locale, see An Overview of Globalization.

For timezone type and realted functions, see Date/Time Types with Timezone. For timezone related system parameters, see Timezone Parameter. If you want to update a timezone information as a new one, timezone library should be recompiled; for details, see Compiling Timezone Library.

If you want to apply the wanted locale to the database, you have to set the locale firstly, then create the database. Regarding this setting, see Locale Setting.

If you want to change the collation or charset specified on the database, specify COLLATE modifier or CHARSET modifier to the column, table, expression, and specify COLLATE modifier or Charset Introducer to the string literal. Regarding this setting, see Collation.

The functions or operators related to strings can work differently by charset and collation. Regarding this, see Operations Requiring Collation and Charset.

An Overview of Globalization
Character data

Character data (strings) may be stored with VARCHAR(STRING), CHAR, ENUM, and they support charset and collation.

Charset(character set, codeset) controls how characters are stored (on any type of storage) as bytes, or how a series of bytes forms a character. CUBRID supports ISO-88591-1, UTF-8 and EUC-KR charsets. For UTF-8, we support only the Unicode characters up to codepoint 10FFFF (encoded on up to four bytes). For instance, the character "Ç" is encoded in codeset ISO-8859-1 using a single byte (C7), in UTF-8 is encoded with 2 bytes (C3 88), while in EUC-KR this character is not available.

Collation decides how strings compare. Most often, users require case insensitive and case sensitive comparisons. For instance, the strings "ABC" and "abc" are equal in a case insensitive collation, while in a case sensitive collation, they are not, and depending on other collation settings, the relationship can be "ABC" < "abc" , or "ABC" > "abc".

Collation means more than comparing character casing. Collation decides the relationship between two strings (greater, lower, equal), is used in string matching (LIKE), or computing boundaries in index scan.

In CUBRID, a collation implies a charset. For instance, collations "utf8_en_ci" and "iso88591_en_ci" perform case insensitive compare, but operate on different charsets. Although for ASCII range, in these particular cases the results are similar, the collation with "utf8_en_ci" is slower, since it needs to work on variable number of bytes (UTF-8 encoding).

  • "'a' COLLATE iso88591_en_ci" indicates "_iso88591'a' COLLATE iso88591_en_ci".
  • "'a' COLLATE utf8_en_ci" indicates "_utf8'a' COLLATE utf8_en_ci".

All string data types support precision. Special care is required with fixed characters(CHAR). The values of this types are padded to fill up the precision. For instance, inserting "abc" into a CHAR(5) column, will result in storing "abc " (2 padding spaces are added). Space (ASCII 32 decimal, Unicode 0020) is the padding character for most charsets. But, for EUC-KR charset, the padding consists of one character which is stored with two bytes (A1 A1).

Locale Attributes

Locale is defined by following attributes.

  • Charset (codeset): How bytes are interpreted into single characters (Unicode codepoints)
  • Collations: Among all collations defined in locale of LDML(UNICODE Locale Data Markup Language) file, the last one is the default collation. Locale data may contain several collations.
  • Alphabet (casing rules): One locale data may have up 2 alphabets, one for identifier and one for user data. One locale data can have two types of alphabets.
  • Calendar: Names of weekdays, months, day periods (AM/PM)
  • Numbering settings: Symbols for digit grouping
  • Text conversion data: For CSQL conversion. Option.
  • Unicode normalization data: Data converted by normalizing several characters with the same shape into one based on a specified rule. After normalization, characters with the same shape will have the same code value even though the locale is different. Each locale can activate/deactivate the normalization functionality.

Note

Generally, locale supports a variety of character sets. However, CUBRID locale supports both ISO and UTF-8 character sets for English and Korean. The other operator-defined locales using the LDML file support the UTF-8 character set only.

Collation Properties

A collation is an assembly of information which defines an order for characters and strings. In CUBRID, collation has the following properties.

  • Strength: This is a measure of how "different" basic comparable items (characters) are. This affects selectivity. In LDML files, collation strength is configurable and has four levels. For example a Case insensitive collation should be set with level = "secondary" (2) or "primary" (1).
  • Whether it supports or not expansions and contractions

Each column has a collation, so when applying LOWER(), UPPER() functions the casing rules of locale which defines the collation's default language is used.

Depending on collation properties some CUBRID optimizations may be disabled for some collations:

  • LIKE rewrite: is disabled for collations which maps several different character to the same weight (case insensitive collations for example) and for collations with expansions.
  • Covering index scan: disabled for collations which maps several different character to the same weight (see Covering Index).

For more information, see Collation settings impacting CUBRID features .

Collation Naming Rules

The collation name in CUBRID follows the conversion:

<charset>_<lang specific>_<desc1>_<desc2>_...
  • <charset>: The full charset name as used by CUBRID. iso88591, utf8, euckr.
  • <lang specific>: a region/language specific. The language code is expected as two characters; en, de, es, fr, it, ja, km, ko, tr, vi, zh, ro. "gen" if it does not address a specific language, but a more general sorting rule.
  • <desc1>_<desc2>_...: They have the following meaning. Most of them apply only to LDML collations.
    • ci: case insensitive In LDML, can be obtained using the settings: strength="secondary" caseLevel="off" caseFirst="off".
    • cs: case sensitive; By default all collations are case sensitive. In LDML, can be obtained using at least: strength="tertiary".
    • bin: it means that the sorting order under such collation is almost the same with the order of codepoints; If memory (byte) comparison is used, then almost the same result is obtained. Space character and EUC double-byte padding character are always sorted as zero in "bin" collation. No collations with such setting are currently configured in LDML (they are already available as built-in), but a similar one can be obtained using the maximum setting strength="quaternary" or strength="identical".
    • ai: accent insensitive; this means that 'Á' is sorted the same as 'A'. Due to particularities of the UCA based algorithms, an accent insensitive collation is also a case insensitive collation. In LDML, can be obtained using: strength="primary".
    • uca: this signals a UCA based collation; this is used only to differentiate such collations from similar built-in variants. All LDML collations are based on UCA, but in order to keep shorter names only two collations ( 'utf8_ko_cs_uca' , 'utf8_tr_cs_uca' ) have this description in their names, in order to differentiate them from 'utf8_ko_cs' and 'utf8_tr_cs' collations.
    • exp: this collations use a full-word matching/compare algorithm, contrary to the rest of collations which use character-by-character compare. This collation uses a more complex algorithm, with multiple passes which is much slower, but may prove useful for alphabetical sorts. In LDML, the Expansion needs to be explicit by adding CUBRIDExpansions="use".
    • ab: accent backwards; it is particularity of French-Canadian sorting, where level 2 of UCA (used to store accents weights) is compared from end of string towards the beginning. This collation setting can be used only when :ref`expansion` setting is also activated. The "backwards" setting allows for the following sorting:
      • Normal Accent Ordering: cote < coté < côte < côté
      • Backward Accent Ordering: cote < côte < coté < côté
    • cbm: contraction boundary match; it is a particularity of collations with Expansion and Contraction and refers to how it behaves at string matching when a Contraction is found. Suppose the collation has defined the Contraction "ch"; then normally, the pattern "bac" will not match the string"bachxxx" But when the collation is configured to allow "matching the characters starting a contraction", the above matching will return a positive. Only one collation is configured in this manner - 'utf8_ja_exp_cbm' - Japanese sorting requires a lot of contractions.

The collation names are not dynamically generated. They are user defined (configured in LDML), and should reflect the settings of the collation.

The name of collation influences the internal numeric id of the collation. For instance, in CUBRID only 256 collations are allowed, and the numeric IDs are assigned as:

  • 0 -31: built-in collations (for these collations the name and id are hard-coded)
  • 32 - 46: LDML collations having "gen" as "language" part
  • 47 - 255: the rest of LDML collations

If you want to include all locales into the database which CUBRID provide, first, copy cubrid_locales.all.txt of $CUBRID/conf directory into cubrid_locales.txt and next, run make_locale script(in extension, Linux is .sh, Windows is .bat). For more details on make_locale script, see Step 2: Compiling Locale.

If you want to include the newly added locale information into the existing database, run "cubrid synccolldb <dbname>". For more information, see Synchronization of Database Collations with System Collations.

If you include all locales defined in LDML files, CUBRID has the following collations.

CUBRID Collation
Collation Locale for casing Character range
iso88591_bin en_US - English ASCII + ISO88591 (C0-FE, except D7, F7)
iso88591_en_cs en_US - English ASCII + ISO88591 (C0-FE, except D7, F7)
iso88591_en_ci en_US - English ASCII + ISO88591 (C0-FE, except D7, F7)
utf8_bin en_US - English ASCII
euckr_bin ko_KR - Korean, same as en_US - English ASCII
utf8_en_cs en_US - English ASCII
utf8_en_ci en_US - English ASCII
utf8_tr_cs tr_TR - Turkish Turkish alphabet
utf8_ko_cs ko_KR - Korean, same as en_US - English ASCII
utf8_gen de_DE - German, generic Unicode casing customized with German rules All Unicode codepoints in range 0000-FFFF
utf8_gen_ai_ci de_DE - German, generic Unicode casing customized with German rules All Unicode codepoints in range 0000-FFFF
utf8_gen_ci de_DE - German, generic Unicode casing customized with German rules All Unicode codepoints in range 0000-FFFF
utf8_de_exp_ai_ci de_DE - German, generic Unicode casing customized with German rules All Unicode codepoints in range 0000-FFFF
utf8_de_exp de_DE - German, generic Unicode casing customized with German rules All Unicode codepoints in range 0000-FFFF
utf8_ro_cs ro_RO - Romanian, same as generic Unicode casing All Unicode codepoints in range 0000-FFFF
utf8_es_cs es_ES - Spanish, same as generic Unicode casing All Unicode codepoints in range 0000-FFFF
utf8_fr_exp_ab fr_FR - French, same as generic Unicode casing All Unicode codepoints in range 0000-FFFF
utf8_ja_exp ja_JP - Japanese, same as generic Unicode casing All Unicode codepoints in range 0000-FFFF
utf8_ja_exp_cbm ja_JP - Japanese, same as generic Unicode casing All Unicode codepoints in range 0000-FFFF
utf8_km_exp km_KH - Cambodian, same as generic Unicode casing All Unicode codepoints in range 0000-FFFF
utf8_ko_cs_uca ko_KR - Korean, same as generic Unicode casing All Unicode codepoints in range 0000-FFFF
utf8_tr_cs_uca tr_TR - Turkish, generic Unicode casing customized with Turkish rules All Unicode codepoints in range 0000-FFFF
utf8_vi_cs vi_VN - Vietnamese, same as generic Unicode casing All Unicode codepoints in range 0000-FFFF
binary none (invariant to casing operations) any byte value (zero is nul-terminator)

The Turkish casing rules changes the casing for character i,I,ı,İ. The German casing rules changes the casing for ß.

On the above collations, 9 collations like iso88591_bin, iso88591_en_cs, iso88591_en_ci, utf8_bin, euckr_bin, utf8_en_cs, utf8_en_ci, utf8_tr_cs and utf8_ko_cs, are built in the CUBRID before running make_locale script.

If a collation is included in more than one locale (.ldml) file, the locale for casing (default locale of collation) is the locale in which it is first included. The order of loading is the locales order from $CUBRID/conf/cubrid_locales.txt. The above locale casing for collations utf8_gen, utf8_gen_ci, utf8_gen_ai_ci, assumes the default order (alphabetical) in cubrid_locales.txt, so the default locale for all generic LDML collations is de_DE (German).

Files For Locale Setting

CUBRID uses following directories and files to set the locales.

  • $CUBRID/conf/cubrid_locales.txt file: A configuration file containing the list of locales to be supported
  • $CUBRID/conf/cubrid_locales.all.txt file: A configuration file template with the same structure as cubrid_locales.txt. Contains the entire list of all the locales that the current version of CUBRID is capable of supporting without any efforts from the end user's side.
  • $CUBRID/locales/data directory: This contains files required to generate locale data.
  • $CUBRID/locales/loclib directory: contains a C header file, locale_lib_common.h and OS dependent makefile which are used in the process of creating / generating locales shared libraries.
  • $CUBRID/locales/data/ducet.txt file: Text file containing default universal collation information (codepoints, contractions and expansions, to be more specific) and their weights, as standardized by The Unicode Consortium, which is the starting point for the creation of collations. For more information, see http://unicode.org/reports/tr10/#Default_Unicode_Collation_Element_Table .
  • $CUBRID/locales/data/unicodedata.txt file: Text file containing information about each Unicode codepoint regarding casing, decomposition, normalization etc. CUBRID uses this to determine casing. For more information, see http://www.ksu.ru/eng/departments/ktk/test/perl/lib/unicode/UCDFF301.html .
  • $CUBRID/locales/data/ldml directory: common_collations.xml and XML files, name with the convention cubrid_<locale_name>.xml. common_collations.xml file contains shared collation information in all locale files, and each cubrid_<locale_name>.xml file contains a locale information for the supported language.
  • $CUBRID/locales/data/codepages directory: contains codepage console conversion for single byte codepages(8859-1.txt , 8859-15.txt, 8859-9.txt) and codepage console conversion for double byte codepages(CP1258.txt , CP923.txt, CP936.txt , CP949.txt).
  • $CUBRID/bin/make_locale.sh file or %CUBRID%\bin\make_locale.bat file: A script file used to generate shared libraries for locale data
  • $CUBRID/lib directory: Shared libraries for generated locales will be stored here.
Locale Setting

When you want to use a charset and collation of a specific language, the charset should be identical with a database which will be created newly. Supported CUBRID charsets are ISO-8859-1, EUC-KR and UTF-8 and the charset to be used is specified when creating a database.

For example, when you created a database with a locale ko_KR.utf8, you can use collations starting with "utf8_" like utf8_ja_exp. However, if you set the locale as ko_KR.euckr, you cannot use all collations which are related with other charset(see CUBRID Collation).

The following is an example which used utf8_ja_exp after creating a database with en_US.utf8.

  1. cd $CUBRID/conf

  2. cp cubrid_locales.all.txt cubrid_locales.txt

  3. make_locale.sh -t64 # 64 bit locale library creation

  4. cubrid createdb testdb en_US.utf8

  5. cubrid server start testdb

  6. csql -u dba testdb

  7. run below query on csql

    SET NAMES utf8;
    CREATE TABLE t1 (i1 INT , s1 VARCHAR(20) COLLATE utf8_ja_exp, a INT, b VARCHAR(20) COLLATE utf8_ja_exp);
    INSERT INTO t1 VALUES (1, 'いイ基盤',1,'いイ 繭');
    

For more details, see the following.

Step 1: Selecting a Locale

Configure locales to use on $CUBRID/conf/cubrid_locales.txt. You can select all or some of locales which are supported.

CUBRID supports locales as follows: en_US, de_DE, es_ES, fr_FR, it_IT, ja_JP, km_KH, ko_KR, tr_TR, vi_VN, zh_CN, ro_RO.

The language and country for each locale are shown in the following table.

Locale Name Language - Country
en_US English - U.S.A.
de_DE German - Germany
es_ES Spanish - Spain
fr_FR French - France
it_IT Italian - Italy
ja_JP Japanese - Japan
km_KH Khmer - Cambodia
ko_KR Korean - Korea
tr_TR Turkish - Turkey
vi_VN Vietnamese - Vietnam
zh_CN Chinese - China
ro_RO Romanian - Romania

Note

The LDML files for the supported locales are named cubrid_<locale_name>.xml and they can be found in the $CUBRID/locales/data/ldml directory. If only a subset of these locales are to be supported by CUBRID, one must make sure their corresponding LDML files are present in the $CUBRID/locales/data/ldml folder. A locale cannot be used by CUBRID, unless it has an entry in cubrid_locales.txt file and it has a corresponding cubrid_<locale_name>.xml.

Locale libraries are generated according to the contents of $CUBRID/conf/cubrid_locales.txt configuration file. This file contains the language codes of the wanted locales (all user defined locales are generated with UTF-8 charset). Also, in this file can be configured the file paths for each locale LDML file and libraries can be optionally configured.

<lang_name>  <LDML file>                                        <lib file>
ko_KR        /home/CUBRID/locales/data/ldml/cubrid_ko_KR.xml    /home/CUBRID/lib/libcubrid_ko_KR.so

By default, the LDML files are found in $CUBRID/locales/data/ldml and the locale libraries in $CUBRID/lib; the filenames for LDML are formatted like: cubrid_<lang_name>.ldml.

The filenames for libraries: libcubrid_<lang_name>.dll (.so for Linux).

Step 2: Compiling Locale

Once the requirements described above are met, the locales can be compiled.

Regarding the embedded locales in CUBRID, they can be used without compiling user locale library, so they can be used by skipping the step 2. But there are differences between the embedded locale and the library locale. Regarding this, see Built-in Locale and Library Locale.

To compile the locale libraries, one must use the make_locale (.bat for Windows and .sh for Linux) utility script from command console. The file is delivered in $CUBRID/bin folder so it should be resolved by $PATH environment variable. Here $CUBRID, $PATH are the environment variables of Linux, %CUBRID%, %PATH% are the environment variables of Windows.

Note

To run a make_locale script in Windows, it requires Visual C++ 2005, 2008 or 2010.

Usage can be displayed by running make_locale.sh -h. (make_locale /h in Windows.)

make_locale.sh [options] [locale]

options ::= [-t 32|64 ] [-m debug|release]
locale ::= [de_DE|es_ES|fr_FR|it_IT|ja_JP|km_KH|ko_KR|tr_TR|vi_VN|zh_CN|ro_RO]
  • options
    • -t: Selects 32bit or 64bit (default value: 64).
    • -m: Selects release or debug. In general, release is selected (default value: release). The debug mode is provided for developers who would like to write the locale library themselves. Selects release or debug. In general, release is selected (default value: release). The debug mode is provided for developers who would like to write the locale library themselves.
  • locale: The locale name of the library to build. If locale is not specified, the build includes data from all configured locales. In this case, library file is stored in $CUBRID/lib directory with the name of libcubrid_all_locales.so (.dll for Windows).

To create user defined locale shared libraries, two choices are available:

  • Creating a single lib with all locales to be supported.

    make_locale.sh -t64                        # Build and pack all locales (64/release)
    
  • Creating one lib for each locale to be supported.

    make_locale.sh -t 64 -m release ko_KR
    

The first choice is recommended. In this scenario, some data may be shared among locales. If you choose the first one, a lib supporting all locales has less than 15 MB; in the second one, consider for each locale library from 1 MB to more than 5 MB. Also the first one is recommended because it has no runtime overhead during restarting the servers when you choose the second one.

Warning

Limitations and Rules

  • Do not change the contents of $CUBRID/conf/cubrid_locales.txt after locales generation; once the locales libraries are generated, the contents of $CUBRID/conf/cubrid_locales.txt should not be changed (order of languages within the file must also be preserved). During locale compiling, the generic collation uses the first one as default locale; changing the order may cause different results with casing for such collation (utf8_gen_*).
  • Do not change the contents for $CUBRID/locales/data/*.txt files.

Note

Procedure of Executing make_locale.sh(.bat) Script

The processing in make_locale.sh(.bat) script

  1. Reads the .ldml file corresponding to a language, along with some other installed common data files like $CUBRID/locales/data/ducet.txt, $CUBRID/locales/data/unicodedata.txt, and $CUBRID/locales/data/codepages/*.txt
  2. After processing of raw data, it writes in a temporary $CUBRID/locales/loclib/locale.c file C constants values and arrays consisting of locales data.
  3. The temporary file locale.c is passed to the platform compiler to build a .dll/.so file. This step assumes that the machines has an installed C/C++ compiler and linker. Currently, only the MS Visual Studio for Windows and gcc for Linux compilers are supported.
  4. Temporary files are removed.
Step 3: Setting CUBRID to Use a Specific Locale

Only one locale can be selected as the default locale when you create DB.

In addition to the possibility of specifying a default locale, one can override the default calendar settings with the calendar settings from another locale, using the intl_date_lang system parameter.

  • The locale will be in the format: <locale_name>.[utf8 | iso] (e.g. tr_TR.utf8, en_EN.ISO, ko_KR.utf8)
  • intl_date_lang: <locale_name>. The possible values for <locale_name> are listed on Step 1: Selecting a Locale.

Note

Setting the Month/Day in Characters, AM/PM, and Number Format

For the function that inputs and outputs the day/time, you can set the month/day in characters, AM/PM, and number format by the locale in the intl_date_lang system parameter.

Also for the function that converts a string to numbers or the numbers to a string, you can set the string format by the locale in intl_number_lang system parameter.

Built-in Locale and Library Locale

Regarding the embedded locales in CUBRID, they can be used without compiling user locale library, so they can be used by skipping the step 2. But there are two differences between the embedded locale and the library locale.

  • Embedded(built-in) locale(and collation) are not aware of Unicode data For instance, casing (lower, upper) of (Á, á) is not available in embedded locales. The LDML locales provide data for Unicode codepoints up to 65535.
  • Also, the embedded collations deals only with ASCII range, or in case of 'utf8_tr_cs' - only ASCII and letters from Turkish alphabet. Embedded UTF-8 locales are not Unicode compatible, while compiled (LDML) locales are.

Currently, the built-in locales which can be set during creating DB are as follows:

  • en_US.iso88591
  • en_US.utf8
  • ko_KR.utf8
  • ko_KR.euckr
  • ko_KR.iso88591: Will have Romanized Korean names for month, day names.
  • tr_TR.utf8
  • tr_TR.iso88591: Will have Romanized Turkish names for month, day names.

The order stated above is important; if no charset is defined while creating DB, the charset is the charset of the locale shown first. For example, if the locale is set as ko_KR(e.g. cubrid createdb testdb ko_KR), the charset is specified as ko_KR.utf8, the first locale among the ko_KR in the above list. Locales of the other languages except the built-in locales should end with .utf8. For example, specify the locale as de_DE.utf8 for German.

The names of month and day for ko_KR.iso88591 and tr_TR.iso88591 should be Romanized. For example, "일요일" for Korean (Sunday in English) is Romanized to "Iryoil". Providing ISO-8859-1 characters only is required. For more information, see The Month/Day in Korean and Turkish Characters for ISO-8859-1 Charset.

The Month/Day in Korean and Turkish Characters for ISO-8859-1 Charset

In Korean or Turkish which have charset UTF-8 or in Korean which have charset EUC-KR, the month/day in characters and AM/PM are encoded according to the country. However, for ISO-8859-1 charset, if the month/day in characters and AM/PM in Korean or Turkish is used as its original encoding, an unexpected behavior may occur in the server process because of its complex expression. Therefore, the name should be Romanized. The default charset of CUBRID is ISO-8859-1 and the charset can be used for Korean and Turkish. The Romanized output format is as follows:

Day in Characters

Day in Characters Long/Short Format Long/Short Romanized Korean Long/Short Romanized Turkish
Sunday / Sun Iryoil / Il Pazar / Pz
Monday / Mon Woryoil / Wol Pazartesi / Pt
Tuesday / Tue Hwayoil / Hwa Sali / Sa
Wednesday / Wed Suyoil / Su Carsamba / Ca
Thursday / Thu Mogyoil / Mok Persembe / Pe
Friday / Fri Geumyoil / Geum Cuma / Cu
Saturday / Sat Toyoil / To Cumartesi / Ct

Month in Characters

Month in Characters Long/Short Format Long/Short Romanized Korean (Not Classified) Long/Short Romanized Turkish
January / Jan 1wol Ocak / Ock
February / Feb 2wol Subat / Sbt
March / Mar 3wol Mart / Mrt
April / Apr 4wol Nisan / Nsn
May / May 5wol Mayis / Mys
June / Jun 6wol Haziran / Hzr
July / Jul 7wol Temmuz / Tmz
August / Aug 8wol Agustos / Ags
September / Sep 9wol Eylul / Eyl
October / Oct 10wol Ekim / Ekm
November / Nov 11wol Kasim / Ksm
December / Dec 12wol Aralik / Arl

AM/PM in Characters

AM/PM in Characters Long/Short Format Romanized in Korean Romanized in Turkish
AM ojeon AM
PM ohu PM
Step 4: Creating a Database with the Selected Locale Setting

When issuing the command "cubrid createdb <db_name> <locale_name.charset>", a database will be created using the settings in the variables described above.

Once the database is created a locale setting which was given to the database cannot be changed. The charset and locale name are stored in "db_root" system catalog table.

Step 5 (optional): Manually Verifying the Locale File

The contents of locales libraries may be displayed in human readable form using the dumplocale CUBRID utility. Execute cubrid dumplocale -h to output the usage. The used syntax is as follows.

cubrid dumplocale [options] [language-string]

options ::= -i|--input-file <shared_lib>
            -d|--calendar
            -n|--numeric
            {-a |--alphabet=}{l|lower|u|upper|both}
            -c|--codepoint-order
            -w|--weight-order
            {-s|--start-value} <starting_codepoint>
            {-e|--end-value} <ending_codepoint>
            -k
            -z

language-string ::= de_DE|es_ES|fr_FR|it_IT|ja_JP|km_KH|ko_KR|tr_TR|vi_VN|zh_CN|ro_RO
  • dumplocale: A command which dumps the contents of locale shared library previously generated using LDML input file.
  • language-string: One of de_DE, es_ES, fr_FR, it_IT, ja_JP, km_KH, ko_KR, tr_TR, vi_VN, zh_CN and ro_RO. Configures the locale language to dump the locale shared library. If it's not set, all languages which are configured on cubrid_locales.txt are given.

The following are [options] for cubrid dumplocale.

-i, --input-file=FILE

The name of the locale shared library file (< shared_lib>) created previously. It includes the directory path.

-d, --calendar

Dumps the calendar and date/time data. Default value: No

-n, --numeric

Dumps the number data. Default value: No

-a, --alphabet=l|lower|u|upper|both

Dumps the alphabet and case data. Default value: No

--identifier-alphabet=l|lower|u|upper

Dumps the alphabet and case data for the identifier. Default value: No

-c, --codepoint-order

Dumps the collation data sorted by the codepoint value. Default value: No (displayed data: cp, char, weight, next-cp, char and weight)

-w, --weight-order

Dumps the collation data sorted by the weight value. Default value: No (displayed data: weight, cp, char)

-s, --start-value=CODEPOINT

Specifies the dump scope. Starting codepoint for -a, --identifier-alphabet, -c, -w options. Default value: 0

-e, --end-value=CODEPOINT

Specifies the dump scope. Ending codepoint for -a, --identifier-alphabet, -c, -w options. Default value: Max value read from the locale shared library.

-k, --console-conversion

Dumps the data of console conversion. Default value: No

-z, --normalization

Dumps the normalization data. Default value: No

The following example shows how to dump the calendar, number formatting, alphabet and case data, alphabet and case data for the identifier, collation sorting based on the codepoint order, collation sorting based on the weight, and the data in ko_KR locale into ko_KR_dump.txt by normalizing:

% cubrid dumplocale -d -n -a both -c -w -z ko_KR > ko_KR_dump.txt

It is highly recommended to redirect the console output to a file, as it can be very big data, and seeking information could prove to be difficult.

Synchronization of Database Collations with System Collations

CUBRID's normal operation requires that the system collation and the database collation must be the same. The system locale means that the locale which include built-in locales and library locales created through cubrid_locales.txt (see Locale Setting), and it includes the system collation information. The database collation information is stored on the _db_collation system catalog table.

cubrid synccolldb utility checks if the database collation is the same with the system collation, and synchronize into the system collation if they are different. However, note that this utility doesn't transform the data itself stored on the database.

This utility can be used when the existing database collation should be changed after the system locale is changed. However, there are operations which the user have to do manually.

The user should do this operations before the synchronization. These operations can be done by running CSQL with cubrid_synccolldb_<database_name>.sql file, which is created by cubrid synccolldb -c.

  • Change collation using ALTER TABLE .. MODIFY statement.
  • Remove any views, indexes, triggers or partitions containing the collation.

Run synchrization with cubrid synccolldb. After then, do the following operations.

  • Recreate views, indexes, triggers, or partitions
  • Update application statements to use new collations

This utility should work only in offline mode.

synccolldb syntax is as follows.

cubrid synccolldb [options] database_name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • synccolldb: A command to synchronize collations of a database with collations from the system(according to contents of locales libraries and $CUBRID/conf/cubrid_locales.txt).
  • database_name: A database name to be synchronized with collations from the system.

If [options] is omitted, synccolldb checks the collation differences between the system and the database, synchronize the database collation with the system collation, and create the cubrid_synccolldb_<database_name>.sql file including the queries of objects to be dropped before the synchronization.

The following are [options] which are used on cubrid synccolldb.

-c, --check-only

This option prints out the collation information which is different between the database collation and the system collation.

-f, --force-only

This option doesn't ask when updating the database collation with the system collation.

The following shows that how it works when the system collation and the database collation are different.

Firstly, make locale library about ko_KR locale.

$ echo ko_KR > $CUBRID/conf/cubrid_locales.txt
$ make_locale.sh -t 64

Next, create the database.

$ cubrid createdb --db-volume-size=20M --log-volume-size=20M xdb en_US

Create a schema. At this time, specify the needed collation in each table.

$ csql -S -udba xdb -i in.sql
CREATE TABLE dept(depname STRING PRIMARY KEY) COLLATE utf8_ko_cs_uca;
CREATE TABLE emp(eid INT PRIMARY KEY, depname STRING,address STRING) COLLATE utf8_ko_cs_uca;
ALTER TABLE emp ADD CONSTRAINT FOREIGN KEY (depname) REFERENCES dept(depname);

Change the locale setting of the system. If you do not any values on cubrid_locales.txt, the database consider that only built-in locales exist

$ echo "" > $CUBRID/conf/cubrid_locales.txt

Check the difference between system and database by running cubrid synccolldb -c command.

$ cubrid synccolldb -c xdb

----------------------------------------
----------------------------------------
Collation 'utf8_ko_cs_uca' (Id: 133) not found in database or changed in new system configuration.
----------------------------------------
----------------------------------------
Collation 'utf8_gen_ci' (Id: 44) not found in database or changed in new system configuration.
----------------------------------------
----------------------------------------
Collation 'utf8_gen_ai_ci' (Id: 37) not found in database or changed in new system configuration.
----------------------------------------
----------------------------------------
Collation 'utf8_gen' (Id: 32) not found in database or changed in new system configuration.
----------------------------------------
----------------------------------------
There are 4 collations in database which are not configured or are changed compared to system collations.
Synchronization of system collation into database is required.
Run 'cubrid synccolldb -f xdb'

If the indexes exist, firstly you should remove the indexes, and change the collation of each table, then recreate the indexes directly. The process to remove indexes and change the collation of tables can be executed by using cubrid_synccolldb_xdb.sql file which was created by synccolldb command. On the below example, a foreign key is the index which you should recreate.

$ cat cubrid_synccolldb_xdb.sql

ALTER TABLE [dept] COLLATE utf8_bin;
ALTER TABLE [emp] COLLATE utf8_bin;
ALTER TABLE [emp] DROP FOREIGN KEY [fk_emp_depname];
ALTER TABLE [dept] MODIFY [depname] VARCHAR(1073741823) COLLATE utf8_bin;
ALTER TABLE [emp] MODIFY [address] VARCHAR(1073741823) COLLATE utf8_bin;
ALTER TABLE [emp] MODIFY [depname] VARCHAR(1073741823) COLLATE utf8_bin;

$ csql -S -u dba -i cubrid_synccolldb_xdb.sql xdb

Removing the obsolete collations by executing the above cubrid_synccolldb_xdb.sql script file must be performed before forcing the synchronization of system collations into database.

Run cubrid synccolldb command. If the option is omitted, the message is shown to ask to run this command or not; if the -f option is given, the synchronization is run without checking message.

$ cubrid synccolldb xdb
Updating system collations may cause corruption of database. Continue (y/n) ?
Contents of '_db_collation' system table was updated with new system collations.

Recreate the dropped foreign key.

$ csql -S -u dba xdb

ALTER TABLE emp ADD CONSTRAINT FOREIGN KEY fk_emp_depname(depname) REFERENCES dept(depname);

Note

In CUBRID, collations are identified by the ID number on the CUBRID server, and its range is from 0 to 255. LDML file is compiled with shared library, which offers the mapping information between the ID and the collation(name, attribute).

  • The system collation is the collation which is loaded from the locale library, by the CUBRID server and the CAS module.
  • The database collation is the collation which is stored into the _db_collation system table.
Collation

A collation is an assembly of information which defines an order for characters and strings. One common type of collation is called alphabetization.

If not explicitly set otherwise at column creation, the charset and collation of columns are charset and collation of table. The charset and collation are taken (in order in is found first) from the client. If the result of an expression is a character data type, gets the collation and charset by the collation inference with the operands of the expression.

Note

In CUBRID, collations are supported for a number of languages, including European and Asian. In addition to the different alphabets, some of these languages may require the definition of expansions or contractions for some characters or character groups. Most of these aspects have been put together by the Unicode Consortium into The Unicode Standard (up to version 6.1.0 in 2012). Most of the information is stored in the DUCET file http://www.unicode.org/Public/UCA/latest/allkeys.txt which contains all characters required by most languages.

Most of the codepoints represented in DUCET, are in range 0 - FFFF, but codepoints beyond this range are included. However, CUBRID will ignore the latest ones, and use only the codepoints in range 0 - FFFF (or a lower value, if configured).

Each codepoint in DUCET has one or more 'collation elements' attached to it. A collation element is a set of four numeric values, representing weights for 4 levels of comparison. Weight values are in range 0 - FFFF.

In DUCET, a character is represented on a single line, in the form:

< codepoint_or_multiple_codepoints >   ; [.W1.W2.W3.W4][....].... # < readable text explanation of the symbol/character >

A Korean character kiyeok is represented as follows:

1100  ; [.313B.0020.0002.1100] # HANGUL CHOSEONG KIYEOK

For example, 1100 is a codepoint, [.313B.0020.0002.1100] is one collation element, 313B is the weight of Level 1, 0020 is the weight of Level 2, 0002 is the weight of Level 3, and 1100 is the weight of Level 4.

Expansion support, defined as a functional property, means supporting the interpretation of a composed character as a pair of the same characters which it's made of. A rather obvious example is interpreting the character ''æ'' in the same way as the two character string ''ae''. This is an expansion. In DUCET, expansions are represented by using more than one collation element for a codepoint or contraction. By default, CUBRID has expansions disabled. Handling collations with expansions requires when comparing two strings several passes (up to the collation strength/level).

Charset and Collation of Column

Charset and Collation apply to string data types: VARCHAR (STRING), CHAR and ENUM. By default, all string data types inherit the default database collation and character set, but CUBRID supports two modifiers which affect collation and character set.

Charset

Character set may be specified as character string literal or as non-quoted identifier. Supported character sets:

  • ISO-8859-1
  • UTF-8 (with maximum 4 bytes per characters, which means it supports codepoints from 0 to 0x10FFFF)
  • EUC-KR (the support for this character set is only for backward compatibility reasons, its usage is not recommended)

Note

Previous versions of CUBRID 9.0 supported EUC-KR characters when ISO-8859-1 charset (the single one available) was set. From CUBRID 9.0 Beta, this is no longer available. EUC-KR characters should be used only with EUC-KR charset.

String Check

By default, all input data is assumed to be in the server character specified when creating DB. This may be overridden by SET NAMES or charset introducer (or COLLATE string literal modifier) (For more information, see Charset and Collation of String Literals.

Invalid data may lead to undefined behavior or even crashes if string checking is disabled (by default is disabled). This can be enabled by intl_check_input_string system parameter. However, if you are sure that only valid data is input, you can obtain better performance by disabling string check. Only UTF-8 and EUC-KR text data is checked for valid encodings. Since ISO-8859-1 is single byte encoding and all byte values are valid, there is no checking on this charset.

Charset Conversion

When collation / charset modifiers or normal collation inference requires it, character conversion may occur. Conversions are not reversible. Generally, charset conversion is character transcoding (the bytes representing a character in one charset are replaced with other bytes representing the same character but in the destination charset).

With any conversion, losses may occur. If a character from source charset cannot be encoded in destination charset, it is replaced with a '?' character. This also applies to conversions from binary charset to any other charset. The widest character support is with UTF-8 charset, and since it encodes Unicode, one expects that all character can be encoded. However, during conversion from ISO-8859-1 to UTF-8 some "losses" occur: bytes range 80-A0 are not valid ISO-8859-1 characters but may appear in strings. After conversion to UTF-8 these characters are replaced with '?'.

Rules for conversion of values from one charset to another:

Source \ Destination Binary ISO-8859-1 UTF-8 EUC-KR
Binary No change No change The byte size unchanged. Character length unchanged. No change. Validation per character. Invalid char replace with '?' No change. Validation per character. Invalid char replace with '?'
ISO-8859-1 No change No change Byte conversion. The byte size increases. No loss of useful characters. Byte conversion. Byte size increase. No loss of useful characters.
UTF-8 No change. The byte size unchanged. Character length increases. Byte conversion. Byte size may decrease. Expect loss of characters. No change Byte conversion. Byte size may decrease. Expect loss of characters.
EUC-KR No change. The byte size unchanged. Character length increases Byte conversion. Byte size may decrease. Expect loss of characters Byte conversion. Byte size may increase. No loss of useful characters. No change

Note

Previous versions of CUBRID 9.x didn't supported binary charset. The ISO-8859-1 charset had the role of existing binary charset. Conversions from UTF-8 and EUC-KR charsets to ISO-8859-1 were performed by reinterpreting the byte content of source, not by character translation.

Collation

Collation may be specified as character string literal or as non-quoted identifier.

The following is a query(SELECT * FROM db_collation WHERE is_builtin='Yes') on the db_collation system table.

coll_id  coll_name        charset_name    is_builtin  has_expansions  contractions  uca_strength
================================================================================================
0        'iso88591_bin'   'iso88591'     'Yes'        'No'            0             'Not applicable'
1        'utf8_bin'       'utf8'         'Yes'        'No'            0             'Not applicable'
2        'iso88591_en_cs' 'iso88591'     'Yes'        'No'            0             'Not applicable'
3        'iso88591_en_ci' 'iso88591'     'Yes'        'No'            0             'Not applicable'
4        'utf8_en_cs'     'utf8'         'Yes'        'No'            0             'Not applicable'
5        'utf8_en_ci'     'utf8'         'Yes'        'No'            0             'Not applicable'
6        'utf8_tr_cs'     'utf8'         'Yes'        'No'            0             'Not applicable'
7        'utf8_ko_cs'     'utf8'         'Yes'        'No'            0             'Not applicable'
8        'euckr_bin'      'euckr'        'Yes'        'No'            0             'Not applicable'
9        'binary'         'binary'       'Yes'        'No'            0             'Not applicable'

Built-in collations are available without requiring additional user locale libraries.

Each collation has an associated charset. For this reason, it is not allowed to set incompatible pair to character set and collation.

When COLLATE modifier is specified without CHARSET modifier, then the default charset of collation is set. When CHARSET modifier is specified without COLLATE modifier, then the default collation is set. The default collation for character sets are the bin collation:

  • ISO-8859-1: iso88591_bin
  • UTF-8: utf8_bin
  • EUC-KR: euckr_bin
  • Binary: binary

Binary is the name of both the collation and its associated charset.

For more information on how to determine the collation among the expression parameters (operands) with different collations (and charsets), see How to Determine Collation among Columns with Different Collation.

CHARSET and COLLATE modifier

CUBRID supports two modifiers which affect collation and character set without following the default database collation and character set.

  • CHARACTER_SET (alias CHARSET) changes the columns character set
  • COLLATE changes the collation
<data_type> ::= <column_type> [<charset_modifier_clause>] [<collation_modifier_clause>]

<charset_modifier_clause> ::= {CHARACTER_SET | CHARSET} {<char_string_literal> | <identifier> }

<collation_modifier_clause> ::= {COLLATE } {<char_string_literal> | <identifier> }

The following example shows how to set the charset of the VARCHAR type column to UTF-8

CREATE TABLE t1 (s1 VARCHAR (100) CHARSET utf8);

The following example shows how to change the name of column s1 to c1 and the type to CHAR(10) with the collation of utf8_en_cs (the charset is the default charset of the collation, UTF-8).

ALTER TABLE t1 CHANGE s1 c1 CHAR(10) COLLATE utf8_en_cs;

The value of the c1 column is changed to the VARCHAR(5) type whose collation is iso88591_en_ci. It is performed by using the collation iso88591_en_ci for the type of column selected first or by using sorting.

SELECT CAST (c1 as VARCHAR(5) COLLATE 'iso88591_en_ci') FROM t1 ORDER BY 1;

The following query (same sorting) is similar to the above but the output column result is the original value.

SELECT c1 FROM t1 ORDER BY CAST (c1 as VARCHAR(5) COLLATE iso88591_en_ci);
How to Determine Collation among Columns with Different Collation
CREATE TABLE t (
    s1 STRING COLLATE utf8_en_cs,
    s2 STRING COLLATE utf8_tr_cs
);

-- insert values into both columns

SELECT s1, s2 FROM t WHERE s1 > s2;
ERROR: '>' requires arguments with compatible collations.

In the above example, column s1 and column s2 have different collations. Comparing s1 with s2 means comparing the strings to determine which column value is "larger" among the records on the table t. In this case, an error will occur because the comparison between the collation utf8_en_cs and the collation utf8_tr_cs cannot be done.

The rules to determine the types of arguments for an expression are also applied to the rules to determine the collations.

  1. A common collation and a characterset are determined by considering all arguments of an expression.
  2. If an argument has a different collation(and a characterset) with a common collation(and a characterset) decided in No. 1., it is changed into the common collation(and a characterset).
  3. To change the collation, CAST() operator can be used.

Collation coercibility is used to determine the result collation of comparison expression. It expresses how easily the collation can be converted to the collation of the opposite argument. High collation coercibility when comparing two operands of an expression means that the collation can be easily converted to the collation of the opposite argument. That is, an argument with high collation coercibility can be changed to the collation of an argument with lower collation coercibility.

When an expression has various arguments with different collation, a common collation is computed based on each arguments collation and coercibility. The rules for collation inference are:

  1. Arguments with higher coercibility are coerced (or casted) to collation of arguments with lower coercibility.
  2. When arguments have different collation but same coercibility, the expression's collation cannot be resolved and an error is returned. However, when comparing two operands of which collation coercibility level is 11(session variable, host variable) and charset is the same, one of their collation is changed as non-bin collation if one of them is bin collation(utf8_bin, iso88591_bin, euckr_bin). See Converting Collation of Session Variable and/or Host Variable.

Below table shows the collation coercibility about arguments of the expression

Collation Coercibility Arguments of the Expression(Operands)
-1 As an expression which has arguments with only host variables, this coercibility cannot be determined before the execution step.
0 Operand having COLLATE modifier
1 Columns with non-binary and non-bin collation
2 Columns with binary collation and binary charset
3 Columns with bin collation (iso88591_bin, utf8_bin, euckr_bin)
4 SELECT values, Expression With non-binary and non-bin collation
5 SELECT values, Expression With binary collation and binary charset
6 SELECT values, Expression With bin collation (iso88591_bin, utf8_bin, euckr_bin)
7 Special functions (SYSTEM_USER(), DATABASE(), SCHEMA(), VERSION())
8 Constants(string literals) With non-binary and non-bin collation
9 Constants(string literals) With binary collation and binary charset
10 Constants(string literals) With bin collation (iso88591_bin, utf8_bin, euckr_bin)
11 host variables, session variables

Note

In 9.x versions, the binary collation was not available. The iso85891_bin collation had the role of existing binary collation. Since version 10.0, the coercibility of columns with iso88591_bin was demoted from 2 to 3, that of expressions with iso88591_bin from 5 to 6, and of constants with iso88591_bin from 9 to 10.

Regarding an expression which has arguments with only host variables, (e.g. UPPER(?) as the below) this coercibility can be determined on the execution step. That is, the coercibility like this expression cannot be determined on the parsing step; therefore, COERCIBILITY function returns -1.

SET NAMES utf8
PREPARE st FROM 'SELECT COLLATION(UPPER(?)) col1, COERCIBILITY(UPPER(?)) col2';
EXECUTE st USING 'a', 'a';
  col1                         col2
===================================
  'utf8_bin'                     -1

For expressions having all arguments with coercibility 11 and with different collations, the common collation is resolved at run-time (this is an exception from the coercibility value-based rule for inference which would require to raise an error).

PREPARE st1 FROM 'SELECT INSERT(?,2,2,?)';
EXECUTE st1 USING _utf8'abcd', _binary'ef';
 insert( ?:0 , 2, 2,  ?:1 )
======================
 'aefd'

The following shows converting two parameters with different collation to one collation.

  • Converting into the Wanted Collation

    The SELECT statement, failing to execute in the above example, is successfully executed by specifying a collation on one column by using the CAST operator as shown in the following query; then the two operands have the same collation.

    SELECT s1, s2 FROM t WHERE s1 > CAST (s2 AS STRING COLLATE utf8_en_cs);
    

    Also, by CAST s2 to bin collation, the collation coercibility of CAST (6) is higher then coercibility of s1 (1).

    SELECT s1, s2 FROM t WHERE s1 > CAST (s2 AS STRING COLLATE utf8_bin);
    

    In the following query, the second operand "CAST (s2 AS STRING COLLATE utf8_tr_cs)" is a sub-expression. The sub-expression has higher coercibility than the column (s1) so "CAST (s2 AS STRING COLLATE utf8_tr_cs)" is converted to the collation of s1.

    SELECT s1, s2 FROM t WHERE s1 > CAST (s2 AS STRING COLLATE utf8_tr_cs);
    

    Any expression has higher coercibility than any column. So "CONCAT (s2,'')" is converted to the collation of s1 in the following query and the query is successfully performed.

    SELECT s1, s2 FROM t WHERE s1 > CONCAT (s2,'');
    
  • Converting Collation of Constant and Column

    In the following case, comparison is made by using the collation of s1.

    SELECT s1, s2 FROM t WHERE s1 > 'abc';
    
  • When a Column is Created with Bin Collation

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE utf8_bin
    );
    SELECT s1, s2 FROM t WHERE s1 > s2;
    

    In this case, s2 column's coercibility is 6(bin collation) and s2 can be "fully convertible" to the collation of s1. utf8_en_cs is used.

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE iso88591_bin
    );
    SELECT s1, s2 FROM t WHERE s1 > s2;
    

    In this case, utf8_en_cs is used as collation, too. However, some overhead occurs to convert the charset to UTF-8 since s2 is the ISO charset.

    In the following query, the charset is not converted (UTF-8 byte data in s2 is easily reinterpreted to the ISO-8859-1 charset) but character comparison is made by using the iso88591_en_cs collation.

    CREATE TABLE t (
        s1 STRING COLLATE iso88591_en_cs,
        s2 STRING COLLATE utf8_bin
    );
    SELECT s1, s2 FROM t WHERE s1 > s2;
    
  • Converting Collation of Sub-Expression and Column

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE utf8_tr_cs
    );
    SELECT s1, s2 FROM t WHERE s1 > s2 + 'abc';
    

    In this case, the second operand is the expression, so the collation of s1 is used.

    In the following example, an error occurs. An error occurs because '+' operation is tried for s2 and s3 where the collation is different.

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE utf8_tr_cs,
        s3 STRING COLLATE utf8_en_ci
    );
    
    SELECT s1, s2 FROM t WHERE s1 > s2 + s3;
    
    ERROR: '+' requires arguments with compatible collations.
    

    In the following example, the collation of s2 and s3 is utf8_tr_cs. Therefore, the collation of '+' expression is utf8_tr_cs, too. Expressions have higher coercibility than columns. Therefore, comparison operation is made by using the utf8_en_cs collation.

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE utf8_tr_cs,
        s3 STRING COLLATE utf8_tr_cs
    );
    
    SELECT s1, s2 FROM t WHERE s1 > s2 + s3;
    
  • Converting Collation of Number, Date

    Number or date constant which is convertible into string during operation always coercible into the other string's collation.

  • Converting Collation of Session Variable and/or Host Variable

    When comparing the two operands of which collation coercibility level is 11(session variable, host variable) and charset is the same, one of their collation is changed as non-bin collation.

    SET NAMES utf8;
    SET @v1='a';
    PREPARE stmt FROM 'SELECT COERCIBILITY(?), COERCIBILITY(@v1), COLLATION(?), COLLATION(@v1), ? = @v1';
    SET NAMES utf8 COLLATE utf8_en_ci;
    EXECUTE stmt USING 'A', 'A', 'A';
    

    When comparing @v1 and 'A', @v1's collation will be changed as utf8_en_ci, non-bin collation; therefore, @v1's value and 'A' will be the same and the result of "? = @v1" will be 1 as below.

       coercibility( ?:0 )   coercibility(@v1)   collation( ?:1 )      collation(@v1)          ?:2 =@v1
    ===================================================================================================
                        11                  11  'utf8_en_ci'          'utf8_bin'                      1
    
    SET NAMES utf8 COLLATE utf8_en_cs;
    EXECUTE stmt USING 'A', 'A', 'A';
    

    When comparing @v1 and 'A', @v1's collation will be changed as utf8_en_cs, non-bin collation; therefore, @v1's value and 'A' will be different and "? = @v1"'s result will be 0 as below.

       coercibility( ?:0 )   coercibility(@v1)   collation( ?:1 )      collation(@v1)          ?:2 =@v1
    ===================================================================================================
                        11                  11  'utf8_en_cs'          'utf8_bin'                      0
    

    However, if collations of @v1 and 'A' are different as below and the two collations are different, an error occurs.

    DEALLOCATE PREPARE stmt;
    SET NAMES utf8 COLLATE utf8_en_ci;
    SET @v1='a';
    PREPARE stmt FROM 'SELECT COERCIBILITY(?), COERCIBILITY(@v1), COLLATION(?), COLLATION(@v1), ? = @v1';
    SET NAMES utf8 COLLATE utf8_en_cs;
    EXECUTE stmt USING 'A', 'A', 'A';
    
    ERROR: Context requires compatible collations.
    
Charset and Collation of an ENUM type column

Charset and Collation of an ENUM type column follow the locale specified when creating DB.

For example, create the below table after creating DB with en_US.iso88591.

CREATE TABLE tbl (e ENUM (_utf8'a', _utf8'b'));

a column 'e' of the above table has ISO88591 charset and iso88591_bin collation even if the charset of the element is defined as UTF8. If the user want to apply the other charset or collation, it should be specified to the column of the table.

Below is an example to specify the collation about the column of the table.

CREATE TABLE t (e ENUM (_utf8'a', _utf8'b') COLLATE utf8_bin);
CREATE TABLE t (e ENUM (_utf8'a', _utf8'b')) COLLATE utf8_bin;
Charset and Collation of Tables

The charset and the collation can be specified after the table creation syntax.

CREATE TABLE table_name (<column_list>)  [CHARSET charset_name] [COLLATE collation_name]

If the charset and the collation of a column are omitted, the charset and the collation of a table is used. If the charset and the collation of a table are omitted, the charset and the collation of a system is used.

The following shows how to specify the collation on the table.

CREATE TABLE tbl(
    i1 INTEGER,
    s STRING
) CHARSET utf8 COLLATE utf8_en_cs;

If the charset of a column is specified and the collation of a table is specified, the collation of this column is specified as the default collation(<collation_name>_bin) about this column's charset.

CREATE TABLE tbl (col STRING CHARSET utf8) COLLATE utf8_en_ci;

On the above query, the collation of the column col becomes utf8_bin, the default collation about this column.

csql> ;sc tbl

 <Class Name>

  tbl                  COLLATE utf8_en_ci

 <Attributes>

  col                  CHARACTER VARYING(1073741823) COLLATE utf8_bin
Charset and Collation of String Literals

The charset and the collation of a string literal are determined based on the following priority.

  1. Charset Introducer introducer or COLLATE modifier of string literal
  2. The charset and the collation defined by the SET NAMES Statement
  3. System charset and collation(Default collation by the locale specified when creating DB)
SET NAMES Statement

The SET NAMES statement changes the default client charset and the collation. Therefore, all sentences in the client which has executed the statement have the specified charset and collation. The syntax is as follows.

SET NAMES [ charset_name ] [ COLLATE collation_name]
  • charset_name: Valid charset name is iso88591, utf8, euckr and binary.
  • collation_name: Collation setting can be omitted and all available collations can be set. The collation should be compatible with the charset; otherwise, an error occurs. To find the available collation names, look up the db_collation catalog VIEW (see Charset and Collation of Column).

Specifying a collation with SET NAMES statement is the same as specifying a system parameter intl_collation. Therefore, the following two statements are the same behavior.

SET NAMES utf8;
SET SYSTEM PARAMETERS 'intl_collation=utf8_bin';

The following example shows how to create the string literal with the default charset and collation.

SELECT 'a';

The following example shows how to create the string literal with the utf8 charset and utf8_bin collation(the default collation is the bin collation of the charset)

SET NAMES utf8;
SELECT 'a';
Charset Introducer

In front of the constant string, the charset introducer and the COLLATE modifier can be positioned. The charset introducer is the charset name starting with a underscore (_), coming before the constant string. The syntax to specify the CHARSET introducer and the COLLATE modifier for a string is as follows.

[charset_introducer]'constant-string' [ COLLATE collation_name ]
  • charset_introducer: a charset name starting with an underscore (_), can be omitted. One of _utf8, _iso88591, _euckr and _binary can be entered.
  • constant-string: a constant string value.
  • collation_name: the name of a collation, which can be used in the system, can be omitted.

The default charset and collation of the constant string is determined based on the current database connected (the SET NAMES statement executed last or the default value).

  • When the string charset introducer is specified and the COLLATE modifier is omitted, the collation is:
    • if the charset introducer is the same as client charset (from a previous SET NAMES), then the client collation is applied.
    • if the charset introducer does not match the client charset, then the bin collation(one of euckr_bin, iso88591_bin and utf8_bin) corresponding to charset introducer is applied.
  • When the charset introducer is omitted and the COLLATE modifier is specified, the character is determined based on collation.

The following example shows how to specify the charset introducer and the COLLATE modifier.

SELECT 'cubrid';
SELECT _utf8'cubrid';
SELECT _utf8'cubrid' COLLATE utf8_en_cs;

The following example shows how to create the string literal with utf8 charset and utf8_en_cs collation. The COLLATE modifier of SELECT statement overrides the collation specified by SET NAMES syntax.

SET NAMES utf8 COLLATE utf8_en_ci;
SELECT 'a' COLLATE utf8_en_cs;
Charset and Collation of Expressions

The charset and collation of expression's result are inferred from charset and collation of arguments in the expression. Collation inference in CUBRID is based on coercibility. For more information, see How to Determine Collation among Columns with Different Collation.

All string matching function(LIKE, REPLACE, INSTR, POSITION, LOCATE, SUBSTRING_INDEX, FIND_IN_SET, etc) and comparison operators(<, >, =, etc) take collation into account.

Charset and Collation of System Data

The system charset is taken from the locale specified when creating DB. The system collation is always the bin collation (<charset>_bin) of system charset. CUBRID supports three charset(iso88591, euckr, utf8), and accordingly three system collations(iso88591_bin, euckr_bin, utf8_bin).

Impact of Charset Specified When Creating DB

The locale specified when creating DB affects the following.

  • Character supported in identifiers and casing rules (called "alphabet")
  • Default locale for date - string conversion functions
  • Default locale for number - string conversion functions
  • Console conversion in CSQL
Casing and identifiers

In CUBRID, identifiers are cases insensitive. Tables, columns, session variables, triggers, stored procedures are stored in lower case. Authentication identifiers (user and group names) are stored in upper case.

The ISO-8859-1 charset contains only 255 characters, so the primitives are able to use built-in data. Also the EUC-KR charset, from which only the ASCII compatible characters are considered for casing (and are handled in the code), is built-in.

The UTF-8 charset is a special case: There are built-in variants of UTF-8 locales (like en_US.utf8, tr_TR.utf8 and ko_KR.utf8) and LDML locales.

The built-in variant implement only the characters specific to the locale (ASCII characters for en_US.utf8 and ko_KR.utf8, ASCII + Turkish glyphs [1] for tr_TR.utf8). This means that while all UTF-8 characters encoded on maximum 4 bytes are still supported and accepted as identifiers, most of them are not handled as letters, and treated as any normal Unicode character by casing primitives. For instance, character "È" (Unicode codepoint 00C8) is allowed, but an identifier containing it will not be normalized to "è" (lower case).

CREATE TABLE ÈABC;

Therefore, after running above query, it will have a table name with "Èabc" into the system table, _db_class.

Using a LDML locale (built-in variants can also be overridden with a LDML variant), extends the supported Unicode characters up to codepoint FFFF. For instance, if the locale is set by es_ES.utf8 when creating DB and the corresponding locale library is loaded, the previous statement will create a table with the name "èabc".

As previously mentioned, a set of casing rules and supported characters (letters) forms an "alphabet" in CUBRID (this is actually a tag in LDML). Some locales, like tr_TR and de_DE have specific casing rules: - in Turkish: lower('I')='ı' (dot-less lower i); upper ('i') = 'İ' (capital I with dot). - in German: upper ('ß')='SS' (two capital S letters).

Because of this, such locales have two sets of alphabets: one which applies to system data (identifiers) and one which applies to user data. The alphabet applying to user data include the special rules, while the system (identifiers) alphabet do not, thus making the system alphabets compatible between locales. This is required to avoid issues with identifiers (like in Turkish, where casing of the group name "public" results in errors -> "PUBLİC" != "PUBLIC").

It also provides a compatibility between databases with different locales (should be able to export - import schema and data).

String literal input and output

String literals data may be entered to CUBRID by various ways:

  • API interface (CCI)
  • language dependent interface - JDBC, Perl driver, etc.
  • CSQL - command line from console or input file

When receiving character data through drivers, CUBRID cannot be aware of the charset of those strings. All text data contained between quotes (string literals) are handled by CUBRID as raw bytes; the charset meta-information must be provided by client. CUBRID provides a way for the client to instruct it about which type of encoding is using for its character data. This is done with the SET NAMES statement or with charset introducer.

Text Conversion for CSQL

Text console conversion works in CSQL console interface. Most locales have associated character set (or codepage in Windows) which make it easy to write non-ASCII characters from console. For example in LDML for tr_TR.utf8 locale, there is a line:

<consoleconversion type="ISO88599" windows_codepage="28599" linux_charset="iso88599,ISO_8859-9,ISO8859-9,ISO-8859-9">

If the user set its console in one of the above settings (chcp 28599 in Windows, or export LANG=tr_TR.iso88599 in Linux), CUBRID assumes all input is encoded in ISO-8859-9 charset, and converts all data to UTF-8. Also when printing results, CUBRID performs the reverse conversion (from UTF-8 to ISO-8859-9). In Linux, to prevent this transform, using UTF-8(ex: export LANG=tr_TR.utf8) directly is recommended.

The setting is optional in the sense that the XML tag is not required in LDML locale file. For example, the locale km_KH.utf8 does not have an associated codepage.

Example for configuring French language and inputting French characters

Enable fr_FR in cubrid_locales.txt, compile the locales(see Locale Setting) and set fr_FR.utf8 when you create DB.

In Linux:

  • Set console to receive UTF-8; set LANG=fr_FR.utf8 or en_US.utf8 (any locale with UTF-8). This setting will allow to input any UTF-8 character (not only French specific)
  • or, set console to receive ISO-8859-15; set LANG=fr_FR.iso885915; in LDML <consoleconversion> tag, set linux_charset="iso885915". This will receive only ISO-8859-15 characters which will be converted by CSQL to UTF-8 encoding.

In Windows:

  • Set windows codepage to 28605 (chcp 28605 in a command prompt); in LDML <consoleconversion> tag, set windows_codepage="28605". Codepage 28605 is the corresponding for ISO-8859-15 charset.

Example for configuring Romanian and inputting Romanian characters

Enable ro_RO in cubrid_locales.txt, compile the locales(see Locale Setting) and set ro_RO.utf8 when you create DB.

In Linux:

  • Set console to receive UTF-8; set LANG=ro_RO.utf8 or en_US.utf8 (any locale with UTF-8). This setting will allow to input any UTF-8 character (not only Romanian specific)
  • or, set console to receive ISO-8859-2; set LANG=ro_RO.iso88592; in LDML <consoleconversion> tag, set linux_charset="iso88592". This will receive only ISO-8859-15 characters which will be converted by CSQL to UTF-8 encoding.

In Windows:

  • Set windows codepage to 1250 (chcp 1250 in a command prompt); in LDML <consoleconversion> tag, set windows_codepage="1250". Codepage 1250 is the corresponding for ISO-8859-2 charset. Codepage 1250 contains characters specific to some Central and Eastern European languages, including Romanian. Please note that characters outside codepage 1250 will not be properly displayed.

    To use special characters which exist on Romanian alphabet(e.g. "S" and "T" with cedilla bellow), the Romanian legacy keyboard setting of "Control Panel" on Windows is required.

  • ISO8859-2 contains some characters which codepage 1250 does not have, so you cannot input or output all characters of ISO8859-2 with CSQL.

At input, the console conversion process takes all input (including statements) and performs the conversion (only if it is required - if it contains characters that needs conversion). At output (printing results, error messages), CSQL is more selective and does not convert all texts. For instance, printing of numeric values is not filtered through console conversion (since number text contains only ASCII characters).

Unicode Normalization

Glyphs [1] can be written in various forms using Unicode characters/codepoints. Most known are the decomposed and composed forms. For instance, the glyph 'Ä' is written in composed form with a single codepoint: 00C4, in UTF-8 these has two bytes: C3 84. In (fully) decomposed form, it written with two codepoints: 0041 ('A') and 0308 (COMBINING DIAERESIS), and in UTF-8 is encode using 3 bytes: 41 CC 88. Most text editors are able to handle both forms, so both encodings will appear as the same glyph: 'Ä'. Internally, CUBRID "knows" to work only with "fully composed" text.

For clients working with "fully decomposed" text, CUBRID can be configured to convert such text to "fully composed" and serve them back as "fully decomposed". Normalization is not a locale specific feature, it does not depend on locale.

unicode_input_normalization system parameter controls the composition at system level. For more details, see unicode_input_normalization.

The main use case is with both enabled (unicode_input_normalization, unicode_output_normalization): this ensures that a string from a client knowing only decomposed Unicode is still properly handled by CUBRID. A second use case is with unicode_input_normalization = yes and unicode_output_normalization = no, for a client able to handle both types of Unicode writing.

Contraction and Expansion of Collation

CUBRID supports contraction and expansion for collation. Contraction and expansion are available for UTF-8 charset collation. You can see the contraction and expansion of collation in the collation setting in the LDML file. Using contraction and expansion affects the size of locale data (shared library) and server performance.

Contraction

A contraction is a sequence consisting of two or more codepoints, considered a single letter in sorting. For example, in the traditional Spanish sorting order, "ch" is considered a single letter. All words that begin with "ch" sort after all other words beginning with "c", but before words starting with "d". Other examples of contractions are "ch" in Czech, which sorts after "h", and "lj" and "nj" in Croatian and Latin Serbian, which sort after "l" and "n" respectively. See http://userguide.icu-project.org/collation/concepts for additional information. There are also some contractions defined in http://www.unicode.org/Public/UCA/latest/allkeys.txt DUCET.

Contractions are supported in both collation variants: with expansions and without expansions. Contractions support requires changes in a significant number of key areas. It also involves storing a contraction table inside the collation data. The handling of contractions is controlled by LDML parameters DUCETContractions="ignore/use" TailoringContractions="ignore/use" in <settings> tag of collation definition. The first one controls if contractions in DUCET file are loaded into collation, the second one controls if contractions defined by rules in LDML are ignore or not (easier way then adding-deleting all rules introducing contractions).

Expansion

Expansions refer to codepoints which have more than one collation element. Enabling expansions in CUBRID radically changes the collation's behavior as described below. The CUBRIDExpansions="use" parameter controls the this behavior.

Collation without Expansion

In a collation without expansions, each codepoint is treated independently. Based on the strength of the collation, the alphabet may or may not be fully sorted. A collation algorithm will sort the codepoints by comparing the weights in a set of levels, and then will generate a single value, representing the weight of the codepoint. String comparison will be rather straight-forward. Comparing two strings in an expansion-free collation means comparing codepoint by codepoint using the computed weight values.

Collation with Expansion

In a collation with expansions, some composed characters (codepoints) are to be interpreted as an ordered list of other characters (codepoints). For example, 'æ' might require to be interpreted the same way as 'ae', or 'ä' as ''ae'' or ''aa''. In DUCET, the collation element list of 'æ' will be the concatenation of collation element lists of both 'a' and 'e', in this order. Deciding a particular order for the codepoints is no longer possible, and neither is computing new weight values for each character/codepoint.

In a collation with expansions, string comparison is done by concatenating the collation elements for the codepoints/contractions in two lists (for the two strings) and then comparing the weights in those lists for each level.

Example 1

The purpose of these examples is to show that under different collation settings (with or without expansion support), string comparison might yield different results.

Here there are the lines from DUCET which correspond to a subset of codepoints to be used for comparisons in the examples below.

0041  ; [.15A3.0020.0008.0041] # LATIN CAPITAL LETTER A
0052  ; [.1770.0020.0008.0052] # LATIN CAPITAL LETTER R
0061  ; [.15A3.0020.0002.0061] # LATIN SMALL LETTER A
0072  ; [.1770.0020.0002.0072] # LATIN SMALL LETTER R
00C4  ; [.15A3.0020.0008.0041][.0000.0047.0002.0308] # LATIN CAPITAL LETTER A WITH DIAERESIS;
00E4  ; [.15A3.0020.0002.0061][.0000.0047.0002.0308] # LATIN SMALL LETTER A WITH DIAERESIS;

Three types of settings for the collation will be illustrated:

  • Primary strength, no casing (level 1 only)
  • Secondary strength, no casing (levels 1 and 2)
  • Tertiary strength, uppercase first (levels 1, 2 and 3)

From now on, sorting of the strings "Ar" and "Är" will be attempted.

Collation without Expansions Support

When expansions are disabled, each codepoint is reassigning a new single valued weight. Based on the algorithms described above the weights for A, Ä, R and their lowercase correspondents, the order of the codepoints for these characters, for each collation settings example above, will be as follows.

  • Primary strength: A = Ä < R = r
  • Secondary strength: A < Ä < R = r
  • Tertiary strength: A < Ä < R < r

The sort order for the chosen strings is easy to decide, since there are computed weights for each codepoint.

  • Primary strength: "Ar" = "Är"
  • Secondary strength: "Ar" < "Är"
  • Tertiary strength: "Ar" < "Är"

Collation with Expansions

The sorting order is changed for collation with expansion. Based on DUCET, the concatenated lists of collation elements for the strings from our samples are provided below:

Ar [.15A3.0020.0008.0041][.1770.0020.0002.0072]
Är [.15A3.0020.0008.0041][.0000.0047.0002.0308][.1770.0020.0002.0072]

It is rather obvious that on the first pass, for level 1 weights, 0x15A3 will be compared with 0x15A3. In the second iteration, the 0x0000 weight will be skipped, and 0x1770 will be compared with 0x1770. Since the strings are declared identical so far, the comparison will continue on the level 2 weights, first comparing 0x0020 with 0x0020, then 0x0020 with 0x0047, yielding "Ar" < "Är". The example above was meant to show how strings comparison is done when using a collation with expansion support.

Let us change the collation settings, and show how one may obtain a different order for the same strings when using a collation for German, where "Ä" is supposed to be interpreted as the character group "AE". The codepoints and collation elements of the characters involved in this example are as follows.

0041  ; [.15A3.0020.0008.0041] # LATIN CAPITAL LETTER A
0045  ; [.15FF.0020.0008.0045] # LATIN CAPITAL LETTER E
0072  ; [.1770.0020.0002.0072] # LATIN SMALL LETTER R
00C4  ; [.15A3.0020.0008.0041][.15FF.0020.0008.0045] # LATIN CAPITAL LETTER A WITH DIAERESIS; EXPANSION

When comparing the strings "Är" and "Ar", the algorithm for string comparison when using a collation with expansion support will involve comparing the simulated concatenation of collation element lists for the characters in the two strings.

Ar [.15A3.0020.0008.0041][.1770.0020.0002.0072]
Är [.15A3.0020.0008.0041][.15FF.0020.0008.0045][.1770.0020.0002.0072]

On the first pass, when comparing level 1 weights, 0x15A3 will be compared with 0x15A3, then 0x1770 with 0x15FF, where a difference is found. This comparison yields "Ar" > "Är", a result completely different than the one for the previous example.

Example 2

In Canadian French sorting by the collation with expansion, accent is compared from end of string towards the beginning.

  • Normal Accent Ordering: cote < coté < côte < côté
  • Backward Accent Ordering: cote < côte < coté < côté
Operations Requiring Collation and Charset
Charset

Charset information is required for functions which use character primitives. There are exceptions: OCTET_LENGTH() and BIT_LENGTH() do not require charset internally to return the length in bytes and bits. However, for the same glyph (character symbol) stored in different charset, they return different values:

CREATE TABLE t (s_iso STRING CHARSET iso88591, s_utf8 STRING CHARSET utf8);
SET NAMES iso88591;
INSERT INTO t VALUES ('È','È');

-- the first returns 1, while the second does 2
SELECT OCTET_LENGTH(s_iso), OCTET_LENGTH(s_utf8) FROM t;

The previous example should be run from console (or a client) with ISO-8859-1 charset.

Collation

Collation is required in functions and operators which involves a comparison between two strings or matching two strings. These includes functions like: STRCMP(), POSITION(), LIKE condition, and operators (<,= , >=, etc.). Also clauses like ORDER BY, GROUP BY and aggregates(MIN(), MAX(), GROUP_CONCAT()) use collation.

Also, collation is considered in UPPER() and LOWER() functions, in the following manner:

  • Each collation has a default (parent) locale.
  • UPPER and LOWER functions are performed using the user alphabet of the default locale of the collation.

For most collations, the default locale is obvious (is embedded in the name):

  • utf8_tr_cs → tr_TR.utf8
  • iso88591_en_ci → en_US (ISO-8859-1 charset)

The bin collations have the following default locales:

  • iso88591_bin → en_US (ISO-8859-1 charset)
  • utf8_bin (en_US.utf8 - built-in locale - and handles ASCII characters only)
  • euckr_bin (ko_KR.euckr - built-in locale - and handles ASCII characters only)

There are some generic collations available in LDML. These collations have as default locale, the locale in which they are first found. The order of loading is the locales order from $CUBRID/conf/cubrid_locales.txt. Assuming the default order (alphabetical), the default locale for all generic LDML collations is de_DE (German).

Charset conversion

For the three charsets supported by CUBRID the conversion rules are:

  • General rules is that character transcoding occurs (representation of bytes is changed to the destination charset) - precision is kept, while byte size may change (for variable character data). When changing charset of a column with fixed precision (ALTER..CHANGE), the size in bytes always changes (size = precision x charset multiplier).
  • Exceptions are: utf8 and euckr to iso88591 - the precision is kept and data can be truncated.

The following is an example that you run queries by changing the charset as utf8 in the database that the locale specified when creating DB is en_US(.iso88591).

SET NAMES utf8;
CREATE TABLE t1(col1 CHAR(1));
INSERT INTO t1 VALUES ('Ç');

When you run above queries, the data of col1 is truncated because 'Ç' is two bytes character and col1's size is one byte. The charset of database is iso88591, and the charset of input data is utf8; it converts utf8 to iso88591.

Collation settings impacting CUBRID features
LIKE Conditional Optimization

The LIKE conditional expression compares patterns between string data, and returns TRUE if a string whose pattern matches the search word is found.

As already proven above, when using a "collation without expansion support", each codepoint will receive a single integer value, representing its weight in the comparison process. This weight value is computed based on collation settings (strength, casing etc.). Due to the fact that characters can always be regarded as single entities, trying to match a string with a pattern using the LIKE predicate is equivalent to checking if the string can be found in a certain range of strings. For example in order to process a predicate such as ''s LIKE 'abc%' '', CUBRID will first rewrite it as a range restriction for the string "s". "s LIKE 'abc%'" means that "s" must start with the string "abc". In terms of string comparison, this is equivalent, in expansion-free collations, with "s" being greater than "abc", but smaller than its successor (using the English alphabet, the successor of "abc" would be "abd").

s LIKE 'abc%' → s ≥ 'abc' AND s < 'abd' (if using strictly the English alphabet)

This way, the actual interpretation of LIKE is replaced with simple comparisons, but "Collations with expansion support" behave differently.

To compare strings when using such a collation means comparing the concatenated lists of collation elements for each codepoint or expansion, level by level. For more information about comparing strings on the collation with expansion, see Expansion.

If the LIKE predicate rewrite method is kept the same as in a collation with no expansion support as above example, the comparison result can be wrong. To ensure the right query result, the LIKE predicate rewrite method is ran differently as the below example. That is, the LIKE predicate is added as a filter to exclude the wrong data which can be added in a collation with expansion.

s LIKE 'abc%' → s ≥ 'abc' AND s < 'abd' and s LIKE 'abc%' (if using strictly the English alphabet)
Index Covering

Covering index scan is query optimization, in which if all values in query can be computed using only the values found in the index, without requiring additional row lookup in heap file. For more information, see Covering Index.

In the collation without casing, for two strings values, 'abc' and 'ABC', only one value is stored in the index(this is either 'abc' or 'ABC' depending which one was inserted first). As a result, the incorrect result may happen when at least two different strings produce the same sort key in a given collation. For this reason, for all UTF-8 collations with strength level less than 4 (quaternary), the index covering query optimization is disabled.

This is controlled by strength="tertiary/quaternary" in <strength> tag of collation definition in LDML. It should be considered to set this level as maximum strength, because the quaternary strength level requires not only more memory space and bigger size of the shared library file, but also string-comparison time.

For more information about collations, see Collation.

Summary of CUBRID Features for Each Collation
Collation LIKE condition kept after rewrite to range Allows index covering
iso88591_bin No Yes
iso88591_en_cs No Yes
iso88591_en_ci Yes No
utf8_bin No Yes
euckr_bin No Yes
utf8_en_cs No Yes
utf8_en_ci Yes No
utf8_tr_cs No Yes
utf8_ko_cs No Yes
utf8_gen No Yes
utf8_gen_ai_ci Yes No
utf8_gen_ci Yes No
utf8_de_exp_ai_ci Yes No
utf8_de_exp Yes No
utf8_ro_cs No Yes
utf8_es_cs No Yes
utf8_fr_exp_ab Yes No
utf8_ja_exp Yes No
utf8_ja_exp_cbm Yes No
utf8_km_exp Yes No
utf8_ko_cs_uca No Yes
utf8_tr_cs_uca No Yes
utf8_vi_cs No Yes
binary No Yes
Viewing Collation Information

To view the collation information, use CHARSET(), COLLATION() and COERCIBILITY() functions.

The information of the database collation can be shown on db_collation system view or SHOW COLLATION.

Using i18n characters with JDBC

CUBRID JDBC stores string type values received from server using String and CUBRIDBinaryString objects. String objects uses UTF-16 internally to store each character. It should be used to store any string DB value except those having binary charset. CUBRIDBinaryString uses byte array and should be used to store database string values of binary charset. The data buffer of each string value received from server is accompanied by the charset of the value from server. The charset is either the charset of column or expression's result or system charset for any other string without correspondent in database.

Note

In previous versions, the connection charset was used to instantiate JDBC String objects from database values.

Create table with one column having UTF-8 charset and the other of binary charset:

CREATE TABLE t1(col1 VARCHAR(10) CHARSET utf8, col2 VARCHAR(10) CHARSET binary);

Insert one row (the second column has random value bytes):

Connection conn = getConn(null);
PreparedStatement st = conn.prepareStatement("insert into t1 values( ?, ? )");
byte[] b = new byte[]{(byte)161, (byte)224};
CUBRIDBinaryString cbs = new CUBRIDBinaryString(b);
String utf8_str = new String("abc");
st.setObject(1, utf8_str);
st.setObject(2, cbs);
st.executeUpdate();

Query the table and show contents (for binary string - we display a hex dump, for other charsets - the String value):

ResultSet rs = null;
Statement stmt = null;
rs = stmt.executeQuery("select col1, col2 from t1;");
ResultSetMetaData rsmd = null;
rsmd = rs.getMetaData();
int numberofColumn = rsmd.getColumnCount();
while (rs.next()) {
        for (int j = 1; j <= numberofColumn; j++) {
                String columnTypeName = rsmd.getColumnTypeName(j);
                int columnType = rsmd.getColumnType(j);
                if (((CUBRIDResultSetMetaData) rsmd).getColumnCharset(j).equals("BINARY")) {
                        // database string with binary charset
                        Object res;
                        byte[] byte_array = ((CUBRIDBinaryString) res).getBytes();
                        res = rs.getObject(j);
                        System.out.println(res.toString());
                } else {
                        // database string with any other charset
                        String res;
                        res = rs.getString(j);
                        System.out.print(res);
                }
        }
}
Timezone Setting

Timezone can be set by system parameters; a timezone parameter which is set on a session, and a server_timezone parameter which is set on a database server. For details, see Timezone Parameter.

A timezone parameter is a parameter about a session. This setting value can be kept by session unit.

SET SYSTEM PARAMETERS 'timezone=Asia/Seoul';

If this value is not set, it follows server_timezone's setting as default.

A server_timezone parameter is a parameter about a database server.

SET SYSTEM PARAMETERS 'server_timezone=Asia/Seoul';

If this value is not set, it follows OS's setting.

To use timezone information, timezone type should be used. For details, see Date/Time Types with Timezone.

When timezone is set by a region name, it requires a separate timezone library, To use an updated library which has a changed timezone information, not an installed timezone information, timezone library should be compiled after timezone information is changed.

The following is an example to compile a timezone library after updating a timezone information through IANA (http://www.iana.org/time-zones).

For details, see the following description.

Compiling Timezone Library

To use a timezone by specifying a timezone region name, timezone library is required. This is provided as default when CUBRID is installed. By the way, to update a timezone region information as a latest one, timezone library should be compiled after updating a recent code which can be downloaded in IANA (http://www.iana.org/time-zones).

The following is a process to update timezone library as a recent one.

At first, stop cubrid service and operate the following process.

Windows
  1. Download the recent data from http://www.iana.org/time-zones .

    Download the linked file in "Latest version"'s "Time Zone Data".

  2. Decompress the compressed file to %CUBRID%/timezones/tzdata directory.

  3. Run %CUBRID%/bin/make_tz.bat.

    libcubrid_timezones.dll is created at the %CUBRID%/lib directory.

    make_tz.bat
    

Note

To run make_locale script in Windows, one of Visual C++ 2005, 2008 or 2010 should be installed.

Linux
  1. Download the recent data from http://www.iana.org/time-zones .

    Download the linked file in "Latest version"'s "Time Zone Data".

  2. Decompress the compressed file to $CUBRID/timezones/tzdata directory.

  3. Run make_tz.sh.

    libcubrid_timezones.so is created at the $CUBRID/lib directory.

    make_tz.sh
    
Timezone library and database compatibility

The timezone library build by CUBRID includes an MD5 checksum of the timezone data it contains. This hash is stored in all databases which are created with that library, into column timezone_checksum of db_root system table. If timezone library is changed (recompiled with newer timezone data) and the checksum changes, the CUBRID server, nor any other CUBRID tool cannot be started with existing databases. To avoid such incompatibility, one option is to use /extend argument of the make_tz tool. When this option is provided, the timezone_checksum value of database is also changed with the new MD5 checksum of the new timezone library.

In Linux:

make_tz.sh -g extend -d basic

In Windows:

make_tz.bat /extend basic
Usage of timezone data types with JDBC

JDBC CUBRID driver is completely dependent on CUBRID server for timezone information. Although, Java and CUBRID uses the same primary source of information for timezone (IANA), the names of regions and timezone information should be considered as incompatible.

All CUBRID data types having timezone are mapped to CUBRIDTimestamptz Java objects.

Using JDBC to insert value with timezone:

String datetime = "2000-01-01 01:02:03.123";
String timezone = "Europe/Kiev";
CUBRIDTimestamptz dt_tz = CUBRIDTimestamptz.valueOf(datetime, false, timezone);
PreparedStatement  pstmt = conn.prepareStatement("insert into t values(?)");
pstmt.setObject(1, ts);
pstmt.executeUpdate();

Using JDBC to retrieve value with timezone:

String sql = "select * from tz";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
CUBRIDTimestamptz object1 = (CUBRIDTimestamptz) rs.getObject(1);
System.out.println("object: " + object1.toString());

Internally, CUBRID JDBC stores the date/time parts of CUBRIDTimestamptz object into a 'long' value (inheritanted through Date object) which holds the number of milliseconds elapsed since 1st January 1970 (Unix epoch). The internal encoding is performed in UTC time reference, which is different from Timestamp objects which uses local timezone. For this reason, a CUBRIDTimestamptz object created with the same timezone as Java local timezone will not hold the same internal epoch value. In order to provide the Unix epoch, the getUnixTime() method may be used:

String datetime = "2000-01-01 01:02:03.123";
String timezone = "Asia/Seoul";
CUBRIDTimestamptz dt_tz = CUBRIDTimestamptz.valueOf(datetime, false, timezone);
System.out.println("dt_tz.getTime: " + dt_tz.getTime());
System.out.println("dt_tz.getUnixTime: " + dt_tz.getUnixTime ());
Configuration Guide for Characters

Database designers should take into account character data properties when designing the database structure. The following is the summarized guide when configuring aspects related to CUBRID character data.

Locale
  • By default, en_US gives best performance. If you have a plan to use only English, this is recommended.
  • Using UTF-8 locale will increase storage requirement of fixed char(CHAR) by 4 times; using EUC-KR increases storage 3 times.
  • If user string literals have different charset and collation from system, query strings will grow as the string literals are decorated with them.
  • If localized (non-ASCII) characters will be used for identifiers, then use an .utf8 locale
  • Once established the UTF-8 charset for DB, it is best to use a LDML locale (this ensures that identifier names containing most Unicode characters are correctly cased) than a system locale.
  • Setting a locale affects also conversion functions(intl_date_lang, intl_number_lang).
  • When you set the locale during creating DB, there should be no concern on charset and collation of string-literals or user tables columns; all of them can be changed at run-time (with CAST() in queries) or ALTER .. CHANGE for a permanent change.
CHAR and VARCHAR
  • Generally, use VARCHAR if there are large variations in actual number of characters in user data.
  • CHAR type is fixed length type. Therefore, Even if you store only English character in CHAR type, it requires 4 bytes storage in UTF-8 and 3 bytes in EUC-KR.
  • The precision of columns refers to the number of characters (glyphs).
  • After choosing precision, charset and collation should be set according to most used scenarios.
Choosing Charset
  • Even if your text contains non-ASCII character, use utf8 or euckr charsets only if application requires character counting, inserting, replacing.
  • For CHAR data, the main concern should be storage requirement (4x or utf8, 3x for euckr).
  • For both CHAR and VARCHAR data, there is some overhead when inserting/updating data: counting the precision (number of characters) of each instance is more consuming for non-ISO charsets.
  • In queries, charset of expressions may be converted using CAST() operator.
Choosing Collation
  • If no collation dependent operations are performed (string searching, sorting, comparisons, casing), than choose bin collation for that charset or binary collation
  • Collation may be easily overridden using CAST() operator, and COLLATE modifier (in 9.1 version) if charset is unchanged between original charset of expression and the new collation.
  • Collation controls also the casing rules of strings
  • Collations with expansions are slower, but are more flexible and they perform whole-word sorting
Normalization
  • If your client applications send text data to CUBRID in decomposed form, then configure unicode_input_normalization = yes, so that CUBRID re-composes it and handles it in composed form
  • If your client "knows" to handle data only in decomposed form, than set unicode_output_normalization = yes, so that CUBRID always sends in decomposed form.
  • If the client "knows" both forms, then leave unicode_output_normalization = no
CAST vs COLLATE
Remark
  • Query plans printing: collation is not displayed in plans for results with late binding.
  • Only the Unicode code-points in range 0000-FFFF (Basic Multilingual Plan) are normalized.
  • Some locales use space character as separator for digit grouping (thousands, millions, ..). Space is allowed but not working properly in some cases of localized conversion from string to number.

Note

  • In 9.2 or lower version, user defined variable cannot be changed into the different collation from the system collation. For example, "set @v1='a' collate utf8_en_cs;" syntax cannot be executed when the system collation is iso88591.
  • In 9.3 or higher version, the above constraint no more exists.
Guide for Adding Locales and Collations

Most new locales and/or collations can be added by user simply by adding (or changing) a new (existing) LDML file. The LDML files format used by CUBRID are derived from generic Unicode Locale Data Markup Language (http://www.unicode.org/reports/tr35/). The tags and attributes which are specific only to CUBRID can be easily identified (they contain a "cubrid" into the naming).

The best approach to add a new locale is to copy existing LDML file and tweak various setting until desired results are obtained. The filename must be formatted like cubrid_<language>.xml and be placed in the folder $CUBRID/locales/data/ldml. The <language> part should be a ASCII string (normally five characters) in IETF format (http://en.wikipedia.org/wiki/BCP_47). After creating the LDML file, the <language> part string must be added into CUBRID configuration file $CUBRID/conf/cubrid_locales.txt. Note that the order in this file is the order of generating (compiling) locale library and loading locales at start-up.

The make_locale script must be used to compile the new added locale and add its data into the CUBRID locales library (locale in $CUBRID/lib/).

The LDML file is expected in UTF-8 encoding, and it is not possible to add more than one locale into the same LDML file.

Adding a new locale in LDML file requires:

  • to specify calendar information (CUBRID date formats, name of months and week days in various forms, names for AM/PM day periods). CUBRID supports only Gregorian calendar (generic LDML specifies other calendar types which are not supported by CUBRID).
  • to specify number settings (digit grouping symbols)
  • providing an alphabet (set of rules for how letters are upper-cased and lower-cased)
    • optionally, some collations can be added
    • also optionally, console conversion rules for Windows CSQL application can be defined
LDML Calendar Information
  • The first part consists in providing default CUBRID formats for DATE, DATETIME, TIME, TIMESTAMP, DATETIME WITH TIME ZONE and TIMESTAMP WITH TIME ZONE data type conversion to/from string. This formats are used by functions TO_DATE(), TO_TIME(), TO_DATETIME(), TO_TIMESTAMP(), TO_CHAR(), TO_DATETIME_TZ(), TO_TIMESTAMP_TZ(). The formats elements allowed depend on data type and are the ones used for TO_CHAR() function (Date/Time Format 1). Only ASCII characters are allowed in the format strings. The allowed size are 30 bytes (characters) for DATE and TIME formats, 48 characters for DATETIME and TIMESTAMP formats and 70 characters for DATETIME WITH TIME ZONE and TIMESTAMP WITH TIME ZONE.
  • The <months> requires to specify the names for months in both long form and abbreviated form. The allowed size are 15 (or 60 bytes) for abbreviated form and 25 characters (or 100 bytes) for normal form.
  • The <days> requires week day names in both long and abbreviated form. The allowed size are 10 characters (or 40 bytes) for abbreviated form and 15 characters (or 60 bytes) for full day name.
    • The <dayperiods> sub-tree requires to define the string for AM/PM format varints (according to type attribute). The allowed size is 10 characters (or 40 bytes).

The months and week-days names (in both long and abbreviated form) must be specified in Camel case format (first letter upper case, the rest in lower case). CUBRID checks only the maximum allowed size in bytes; the size in characters is computed only for full-width UTF-8 characters (4 bytes), so it would be possible to set a month name having 100 ASCII-only characters (the 25 characters limit is when each character from month name is encoded on 4 bytes in UTF-8).

LDML Numbers information
  • The <symbols> tag defines the characters used as symbols for splitting decimal part from integer part in numbers and for grouping the digits. CUBRID expects only ASCII characters for these symbols. Empty of space character is not allowed. CUBRID performs grouping for 3 digits.
LDML Alphabet

These allow to define casing rules for alphabet of the locale. The 'CUBRIDAlphabetMode' attribute defines the primary source of data for characters. Normally, this should be set to "UNICODEDATAFILE", values which instructs CUBRID to use the Unicode data file ($CUBRID/locales/data/unicodedata.txt).

This file must not be modified, any customization on certain characters should be done in LDML file. If such value is configured, all Unicode characters up to codepoint 65535 are loaded with casing information. The other allowed value for CUBRIDAlphabetMode is "ASCII" which will lead to only ASCII character can be lower case, upper case or case-insenstive compare in matching functions.

This does not affect CUBRID's ability to support all UTF-8 4 bytes encoded Unicode characters, it just limits the casing ability for characters not included.

The casing rules are optional and apply on top of the primary source of character information (UNICODEDATAFILE or ASCII).

CUBRID allows to define upper casing rules (<u> tag) and lower casing rules (<l> tag).Each of upper and lower casing rules set consists for pairs of source-destination (<s> = source, <d> = destination). For instance, the following defines a rule that each character "A" is lower cased to "aa" (two character "a").

<l>
    <s>A</s>
    <d>aa</d>
</l>
LDML Console Conversion

In Windows, the console does not support UTF-8 encoding, so CUBRID allows to translate characters from their UTF-8 encoding to a desired encoding. After configuring console conversion for a locale, the user must set prior to starting CSQL application the codepage of the console using 'chcp' command (the codepage argument must match the 'windows_codepage' attribute in LDML). Conversion will work bidirectionally (input and output in CSQL), but is only limited to Unicode characters which can be converted in the configured codepage.

The <consoleconversion> element is optional and allows to instruct CSQL how to print (in which character encoding) the text in interactive command. The 'type' attribute defines the conversion scheme. The allowed values are:

  • ISO: is a generic scheme in which the destination codepage is a single byte charset
  • ISO88591: is a predefined single byte scheme for ISO-8859-1 charset (the 'file' attribute is not required, is ignored)
  • ISO88599: is a predefined single byte scheme for ISO-8859-9 charset (also the 'file' attribute is not required)
  • DBCS: Double Byte Code-Set; it is a generic scheme in which the destination codepage is a double byte charset

The 'windows_codepage' is the value for Windows codepage which CUBRID automatically activates console conversion. The 'linux_charset' is corresponding value for charset part in LANG environment variable from UNIX system. It is recommended to use native CUBRID charset in Linux console.

The 'file' attribute is required only for "ISO" and "DBCS" values of 'type' attribute and is the file containing the translation information ($CUBRID/locales/data/codepages/).

LDML Collation

Configuring a collation is the most complex task for adding LDML locale in CUBRID. Only collation having UTF-8 codeset can be configured. CUBRID allows to configure most constructs specified by UCA - Unicode Collation Algorithm (http://www.unicode.org/reports/tr10/) including contractions and expansions, but the properties for the collation are mostly controlled via the 'settings' attribute.

A LDML file can contain multiple collations. Collations can be included from external file using the 'include' tag. The 'validSubLocales' attribute of 'collations' tag is a filter allowing to control locale compilation when external collations (from external files) are included. Its values can be either a list of locales or "*" in which case the collations in sub-tree are added in all locales from which the file is included.

One collation is defined using the 'collation' tag and its sub-tree. The 'type' attribute indicates the name for the collation as it will be added in CUBRID. The 'settings' tag defines the properties of the collation:

  • 'id' is the (internal) numeric identifier used by CUBRID. It is integer value in range (32 - 255) and is optional, but is strongly recommended that an explicit unassigned values is set. Please see Collation Naming Rules.
  • 'strength' is a measure of how strings compare. See Collation Properties. The allowed values are :
    • "quaternary": different graphic symbols of the same character compare differently, but different Unicode codepoints may compare equal.
    • "tertiary": graphic symbols of the same character are equal, case-sensitive collation.
    • "secondary": case insensitive collation, characters with accents compare different
    • "primary": accents are ignored, all characters compare as the base character.
  • 'caseLevel': special setting to enable case sensitive compare for collations having strength < tertiary. Valid values are "on" or "off".
  • 'caseFirst': order of casing. Valid values are "lower", "upper" and "off". The "upper" values means upper case letters are ordered before the corresponding lower case letter.
  • 'CUBRIDMaxWeights': it is the number of codepoints (or last codepoint + 1) which are customized in the collation. Maximum value is 65536. Increasing this value increases the size of collation data.
  • 'DUCETContractions': valid values are "use" or "ignore". When "use" - enable CUBRID to use in the collation the contractions defined by DUCET file ($CUBRID/locales/data/ducet.txt) or ignoring them.
  • 'TailoringContractions': same as previous but refers to the contractions defined or derived from explicit collation rules. Enabling contractions leads to a more complex collation (slower string compares).
  • 'CUBRIDExpansions': allowed values are "use" or "ignore" (default) and refers to usage of collation expansions from both the DUCET file and tailoring rules; This has the most influence on collation properties. Enabling it will result in a compare with multiple passes (up to collation strength) when comparing strings. Also it greatly increases collation data, with the benefit of obtaining a more "natural" sort order. See Expansion.
  • 'backwards': "on" or "off": used to obtain "french" order by performing an end-to-start compare on secondary level (for accents). It has effect only when 'CUBRIDExpansions' are enabled.
  • 'MatchContractionBoundary': "true" or "false". This is used in collation having expansions and contractions to configure behavior at string matching when a contraction is found.

The main data for a collation is loaded from the DUCET file. After this step, the collation may be customized using "tailoring rules". These are the "<rules>" (LDML) and "<cubridrules>" (CUBRID specific).

The 'cubridrules' tag is optional and can be used to explicitely set weight values for a codepoint or a range of codepoints. The cubridrules apply after loading the primary collation data from DUCET file and before applying the UCA rules (from '<rules>' tag). Each of these rule is enclosed in '<set>' tag. If the rule refers to only one Unicode codepoint, then a '<scp>' tag is provided which contains the hexadecimal value of codepoint.

All available CUBRID collations contain this cubrid-rule:

<cubridrules>
    <set>
        <scp>20</scp>
        <w>[0.0.0.0]</w>
    </set>
</cubridrules>

This rule says that weight values (UCA defines four weight values per collation element) of the codepoints starting with 20 (which is ASCII space character) are all set to zero. Since there is no '<ecp>' tag, the only codepoint affected is 20. In CUBRID, space character compares as zero. The allowed tags inside of a '<set>' rule are:

  • '<cp>': rule to set the weights for single codepoint.
  • '<ch>': rule to set the weights for single character. Similar to previous one, but instead of codepoint it expects a Unicode character (in UTF-8 encoding).
  • '<scp>': rule to set the weights for a range of codepoints. This is the starting codepoint.
  • '<sch>': rule to set the weights for a range of characters. This is the starting character. In this context, the order of characters is given by their Unicode codepoints.
  • '<ecp>': end codepoint for a range rule.
  • '<ech>': end character for a range rule.
  • '<w>': weight values to set (single value). The weight values are expected in hexadecimal. Each collation element has four values which are delimited by point and enclosed by square brackets([]). There can be up to 10 collation elements.
  • '<wr>': starting weight values to set for a range. Optionally, there is 'step' attribute of this tag, which sets the increasing step after each codepoint. By default the step is [0001.0000.0000.0000], which means that after setting the first weight values for the starting codepoint, one value is added to primary level weight and set to the next codepoint in range, and the process is repeated until end codepoint.

Examples:

<cubridrules>
    <set>                            <!-- Rule 1 -->
        <scp>0</scp>
        <ecp>20</ecp>
        <w>[0.0.0.0]</w>
    </set>

    <set>                            <!-- Rule 2 -->
        <scp>30</scp>
        <ecp>39</ecp>
        <wr step="[1.0.0.0][1.0.0.0]">[30.0.0.0][30.0.0.0]</wr>
    </set>

</cubridrules>

The Rule 1, sets for codepoints ranging from 0 to 20 (including) the weight values 0. The Rule 2, sets for codepoints ranging from 30 to 39 (which are the digits), a set of two collation elements with increasing weights; In this example, codepoint 39 (character "9") will have the weights with two collation elements [39.0.0.0][39.0.0.0].

The '<rules>' tag is also optional but is according to LDML and UCA specifications. The meanings of sub-ordinates tags are :

  • '<reset>': anchor collation element. It defines the reference to which subsequent rules (up to next <reset>) are tailored. It can be a single characters or multiple characters in which case is either a contraction or an expansion. By default, all the tailoring rules after the anchor are sort "after" (element from first rule is after the anchor, element from second rule sorts after element in first rule); if the optional attribute "before" is present, then only the first rule after the <reset> sorts before the anchor, while the second and the following rules resumes the normal "after" sort (element in second rule sorts after element in first rule).
  • '<p>': the character comes after (or before, if the anchor had the before attribute) the previously tailored one at primary level.
  • '<s>': the character comes after (or before, if the anchor had the before attribute) the previously tailored one at secondary level.
  • '<t>': the character comes after (or before, if the anchor had the before attribute) the previously tailored one at tertiary level.
  • '<i>': the character sorts identically to previous one
  • '<pc>', '<sc>', '<tc>', '<ic>': same as '<p>', '<s>', '<t>', '<i>' but applies to a range of characters
  • '<x>': specifies the expansion character
  • '<extend>': specifies the second character of expansion.
  • '<context>': specifies the context in which a rule applies. A variant to specify contractions and expansions.

For more information on UCA tailoring with LDML rules see http://www.unicode.org/reports/tr35/tr35-collation.html.

Footnotes

[1](1, 2) glyph: an element for the shape of a character; a graphic symbol which indicates a shape or a form for a character. Because a glyph specifies the shape which is shown, several glyphs about one character can exist.

Transaction and Lock

This chapter covers issues relating to concurrency and restore, as well as how to commit or rollback transactions.

In multi-user environment, controlling access and update is essential to protect database integrity and ensure that a user's transaction will have accurate and consistent data. Without appropriate control, data could be updated incorrectly in the wrong order.

To control parallel operations on the same data, data must be locked during transaction, and unacceptable access to the data by another transaction must be blocked until the end of the transaction. In addition, any updates to a certain class must not be seen by other users before they are committed. If updates are not committed, all queries entered after the last commit or rollback of the update can be invalidated.

CUBRID uses Multiversion Concurrency Control to optimize data access. Data being modified is not overwritten, old data is instead marked as deleted and a newer version is added elsewhere. Other transactions can continue to read the old version without locking it. Each transaction sees its own snapshot of the database that is defined at the start of transaction or statement execution. Furthermore, the snapshot is only affected by own changes and remains consistent throughout the execution.

All examples introduced here were executed by csql.

Database Transaction

A database transaction groups CUBRID queries into a unit of consistency (for ensuring valid results in multi-user environment) and restore (for making the results of committed transactions permanent and ensuring that the aborted transactions are canceled in the database despite any failure, such as system failure). A transaction is a collection of one or more queries that access and update the database.

CUBRID allows multiple users to access the database simultaneously and manages accesses and updates to prevent inconsistency of the database. For example, if data is updated by one user, the changes made by this transaction are not seen to other users or the database until the updates are committed. This principle is important because the transaction can be rolled back without being committed.

You can delay permanent updates to the database until you are confident of the transaction result. Also, you can remove (ROLLBACK) all updates in the database if an unsatisfactory result or failure occurs in the application or computer system during the transaction. The end of the transaction is determined by the COMMIT WORK or ROLLBACK WORK statement. The COMMIT WORK statement makes all updates permanent while the ROLLBACK WORK statement cancels all updates entered in the transaction.

Transaction Commit

Updates that occurred in the database are not permanently stored until the COMMIT WORK statement is executed. "Permanently stored" means that storing the updates in the disk is completed; The WORK keyword can be omitted. In addition, other users of the database cannot see the updates until they are permanently applied. For example, when a new row is inserted into a class, only the user who inserted the row can access it until the database transaction is committed.

All locks obtained by the transaction are released after the transaction is committed.

COMMIT [WORK];
-- ;autocommit off
-- AUTOCOMMIT IS OFF

SELECT name, seats
FROM stadium WHERE code IN (30138, 30139, 30140);
    name                                seats
=============================================
    'Athens Olympic Tennis Centre'      3200
    'Goudi Olympic Hall'                5000
    'Vouliagmeni Olympic Centre'        3400

The following UPDATE statement changes three column values of seats from the stadium. To compare the results, check the current values and names before the update is done. Since csql runs in an autocommit mode by default, the following example is executed after setting the autocommit mode to off.

UPDATE stadium
SET seats = seats + 1000
WHERE code IN (30138, 30139, 30140);

SELECT name, seats FROM stadium WHERE code in (30138, 30139, 30140);
    name                                seats
============================================
    'Athens Olympic Tennis Centre'      4200
    'Goudi Olympic Hall'                6000
    'Vouliagmeni Olympic Centre'        4400

If the update is properly done, the changes can be permanently fixed. In this time, use the COMMIT WORK as below:

COMMIT [WORK];

Note

In CUBRID, an auto-commit mode is set by default for transaction management.

An auto-commit mode is a mode that commits or rolls back all SQL statements. The transaction is committed automatically if the SQL is executed successfully, or is rolled back automatically if an error occurs. Such auto commit modes are supported in any interfaces.

In CCI, PHP, ODBC and OLE DB interfaces, you can configure auto-commit mode by using CCI_DEFAULT_AUTOCOMMIT upon startup of an application. If configuration on broker parameter is omitted, the default value is set to ON. To change auto-commit mode, use the following functions by interface: cci_set_autocommit () for CCI interface and cubrid_set_autocommit () for PHP interface.

For session command (;AUtocommit) which enables auto-commit configuration in CSQL Interpreter, see Session Commands.

Transaction Rollback

The ROLLBACK WORK statement removes all updates to the database since the last transaction. The WORK keyword can be omitted. By using this statement, you can cancel incorrect or unnecessary updates before they are permanently applied to the database. All locks obtained during the transaction are released.

ROLLBACK [WORK];

The following example shows two commands that modify the definition and the row of the same table.

-- csql> ;autocommit off
CREATE TABLE code2 (
    s_name  CHAR(1),
    f_name  VARCHAR(10)
);
COMMIT;

ALTER TABLE code2 DROP s_name;
INSERT INTO code2 (s_name, f_name) VALUES ('D','Diamond');
ERROR: s_name is not defined.

The INSERT statement fails because the s_name column has been dropped in the definition of code. The data intended to be entered to the code table is correct, but the s_name column is wrongly removed. At this point, you can use the ROLLBACK WORK statement to restore the original definition of the code table.

ROLLBACK WORK;

Later, remove the s_name column by entering the ALTER TABLE again and modify the INSERT statement. The INSERT command must be entered again because the transaction has been aborted. If the database update has been done as intended, commit the transaction to make the changes permanent.

ALTER TABLE code DROP s_name;
INSERT INTO code (f_name) VALUES ('Diamond');

COMMIT WORK;
Savepoint and Partial Rollback

A savepoint is established during the transaction so that database changes made by the transaction are rolled back to the specified savepoint. Such operation is called a partial rollback. In a partial rollback, database operations (insert, update, delete, etc.) after the savepoint are rolled back, and transaction operations before it are not rolled back. The transaction can proceed with other operations after the partial rollback is executed. Or the transaction can be terminated with the COMMIT WORK or ROLLBACK WORK statement. Note that the savepoint does not commit the changes made by the transaction.

A savepoint can be created at a certain point of the transaction, and multiple savepoints can be used for a certain point. If a partial rollback is executed to a savepoint before the specified savepoint or the transaction is terminated with the COMMIT WORK or ROLLBACK WORK statement, the specified savepoint is removed. The partial rollback after the specified savepoint can be performed multiple times.

Savepoints are useful because intermediate steps can be created and named to control long and complicated utilities. For example, if you use a savepoint during the update operation, you don't need to perform all statements again when you made a mistake.

SAVEPOINT mark;
mark:
_ a SQL identifier
_ a host variable (starting with :)

If you make mark all the same value when you specify multiple savepoints in a single transaction, only the latest savepoint appears in the partial rollback. The previous savepoints remain hidden until the rollback to the latest savepoint is performed and then appears when the latest savepoint disappears after being used.

ROLLBACK [WORK] [TO [SAVEPOINT] mark] ;
mark:
_ a SQL identifier
_ a host variable (starting with :)

Previously, the ROLLBACK WORK statement canceled all database changes added since the latest transaction. The ROLLBACK WORK statement is also used for the partial rollback that rolls back the transaction changes after the specified savepoint.

If mark value is not given, the transaction terminates canceling all changes including all savepoints created in the transaction. If mark value is given, changes after the specified savepoint are canceled and the ones before it are remained.

The below example shows how to rollback a part of a transaction. Firstly, specify savepoints SP1, SP2.

-- csql> ;autocommit off

CREATE TABLE athlete2 (name VARCHAR(40), gender CHAR(1), nation_code CHAR(3), event VARCHAR(30));
INSERT INTO athlete2(name, gender, nation_code, event)
VALUES ('Lim Kye-Sook', 'W', 'KOR', 'Hockey');
SAVEPOINT SP1;

SELECT * from athlete2;
INSERT INTO athlete2(name, gender, nation_code, event)
VALUES ('Lim Jin-Suk', 'M', 'KOR', 'Handball');

SELECT * FROM athlete2;
SAVEPOINT SP2;

RENAME TABLE athlete2 AS sportsman;
SELECT * FROM sportsman;
ROLLBACK WORK TO SP2;

In the example above, the name change of the athlete2 table is rolled back by the partial rollback. The following example shows how to execute the query with the original name and examining the result.

SELECT * FROM athlete2;
DELETE FROM athlete2 WHERE name = 'Lim Jin-Suk';
SELECT * FROM athlete2;
ROLLBACK WORK TO SP2;

In the example above, deleting 'Lim Jin-Suk' is discarded by rollback work to SP2 command. The following example shows how to roll back to SP1.

SELECT * FROM athlete2;
ROLLBACK WORK TO SP1;
SELECT * FROM athlete2;
COMMIT WORK;
Cursor Holdability

Cursor holdability is when an application holds the record set of the SELECT query result to fetch the next record even after performing an explicit commit or an automatic commit. In each application, cursor holdability can be specified as Connection level or Statement level. If it is not specified, the cursor is held by default. Therefore, HOLD_CURSORS_OVER_COMMIT is the default setting.

The following code shows how to set cursor holdability in JDBC:

// set cursor holdability at the connection level
conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);

// set cursor holdability at the statement level which can override the connection
PreparedStatement pStmt = conn.prepareStatement(sql,
                                    ResultSet.TYPE_SCROLL_SENSITIVE,
                                    ResultSet.CONCUR_UPDATABLE,
                                    ResultSet.HOLD_CURSORS_OVER_COMMIT);

To set cursor holdability to close the cursor when a transaction is committed, set ResultSet.CLOSE_CURSORS_AT_COMMIT, instead of ResultSet.HOLD_CURSORS_OVER_COMMIT, in the above example.

The default setting for applications that were developed based on CCI is to hold the cursor. If the cursor is set to 'not to hold a cursor' at connection level and you want to hold the cursor, define the CCI_PREPARE_HOLDABLE flag while preparing a query. The default setting for CCI drivers (PHP, PDO, ODBC, OLE DB, ADO.NET, Perl, Python, Ruby) is to hold the cursor. To check whether a driver supports the cursor holdability setting, refer to the PREPARE function of the driver.

Note

  • Note that versions lower than CUBRID 9.0 do not support cursor holdability. The default setting of those versions is to close all cursors at commit.
  • CUBRID currently does not support ResultSet.HOLD_CURSORS_OVER_COMMIT in java.sql.XAConnection interface.

Cursor-related Operation at Transaction Commit

When a transaction is committed, all statements and result sets that are closed are released even if you have set cursor holdability. After that, when the result sets are used for another transaction, some or all of the result sets should be closed as required.

When a transaction is rolled back, all result sets are closed. This means that all result sets held in the previous transaction are closed because you have set cursor holdability.

rs1 = stmt.executeQuery(sql1);
conn.commit();
rs2 = stmt.executeQuery(sql2);
conn.rollback();  // result sets rs1 and rs2 are closed and it will not be available to use them.

When the Result Sets are Closed

The result sets that hold the cursor are closed in the following cases:

  • Driver closes the result set, i.e. rs.close()
  • Driver closes the statement, i.e. stmt.close()
  • Driver disconnects the connection.
  • Transaction aborts, for instance, application explicitly calls rollback(), auto rollback due to a query failure under auto-commit mode.

Relationship with CAS

When the connection between an application and the CAS is closed, all result sets are automatically closed even if you have set cursor holdability in the application. The setting value of KEEP_CONNECTION, the broker parameter, affects cursor holdability of the result set.

  • KEEP_CONNECTION = ON: Cursor holdability is not affected.
  • KEEP_CONNECTION = AUTO: The CAS cannot be restarted while the result set with cursor holdability is open.

Warning

Usage of memory will increase in the status of result set opened. Thus, you should close the result set after completion.

Note

Note that CUBRID versions lower than 9.0 do not support cursor holdability and the cursor is automatically closed when a transaction is committed. Therefore, the recordset of the SELECT query result is not kept.

Database Concurrency

If there are multiple users with read and write authorization to a database, possibility exists that more than one user will access the database simultaneously. Controlling access and update in multi-user environment is essential to protect database integrity and ensure that users and transactions should have accurate and consistent data. Without appropriate control, data could be updated incorrectly in the wrong order.

The transaction must ensure database concurrency, and each transaction must guarantee appropriate results. When multiple transactions are being executed at once, an event in transaction T1 should not affect an event in transaction T2. This means isolation. Transaction isolation level is the degree to which a transaction is separated from all other concurrent transactions. The higher isolation level means the lower interference from other transactions. The lower isolation level means the higher the concurrency. A database determines whether which lock is applied to tables and records based on these isolation levels. Therefore, can control the level of consistency and concurrency specific to a service by setting appropriate isolation level.

The read operations that allow interference between transactions with isolation levels are as follows:

  • Dirty read : A transaction T2 can read D' before a transaction T1 updates data D to D' and commits it.
  • Non-repeatable read : A transaction T1 can read changed value, if a transaction T2 updates or deletes data and commits while data is retrieved in the transaction T1 multiple times.
  • Phantom read : A transaction T1 can read E, if a transaction T2 inserts new record E and commits while data is retrieved in the transaction T1 multiple times.

Based on these interferences, the SQL standard defines four levels of transaction isolation:

  • READ UNCOMMITTED allows dirty read, unrepeatable read and phantom read.
  • READ COMMITTED does not allow dirty read but allows unrepeatable read and phantom read.
  • REPEATABLE READ does not allow dirty read and unrepeatable read but allows phantom read.
  • SERIALIZABLE does not allow interrupts between transactions when doing read operation.

Isolation Levels Provided by CUBRID

On the below table, the number wrapped with parenthesis right after the isolation level name is a number which can be used instead of the isolation level name when setting an isolation level.

You can set an isolation level by using the SET TRANSACTION ISOLATION LEVEL statement or system parameters provided by CUBRID. For details, see Concurrency/Lock-Related Parameters.

(O: YES, X: NO)

CUBRID Isolation Level (isolation_level) DIRTY READ UNREPEATABLE READ PHANTOM READ Schema Changes of the Table Being Retrieved
SERIALIZABLE Isolation Level (6) X X X X
REPEATABLE READ Isolation Level (5) X X O X
READ COMMITTED Isolation Level (4) X O O X

The default value of CUBRID isolation level is READ COMMITTED Isolation Level.

Multiversion Concurrency Control

CUBRID previous versions managed isolation levels using the well known two phase locking protocol. In this protocol, a transaction obtains a shared lock before it reads an object, and an exclusive lock before it updates the object so that conflicting operations are not executed simultaneously. If transaction T1 requires a lock, the system checks if the requested lock conflicts with the existing one. If it does, transaction T1 enters a standby state and delays the lock. If another transaction T2 releases the lock, transaction T1 resumes and obtains it. Once the lock is released, the transaction do not require any new locks.

CUBRID 10.0 replaced the two phase locking protocol with a Multiversion Concurrency Control (MVCC) protocol. Unlike two phase locking, MVCC does not block readers to access objects being modified by concurrent transactions. MVCC duplicates rows, creating multiple versions on each update. Never blocking readers is important for workloads involving mostly value reads from the database, commonly used in read-world scenarios. Exclusive locks are still required before updating objects.

MVCC is also known for providing point in time consistent view of the database and for being particularly adept at implementing true snapshot isolation with less performance costs than other methods of concurrency.

Versioning, visibility and snapshot

MVCC maintains multiple versions for each database row. Each version is marked by its inserter and deleter with MVCCID's - unique identifiers for writer transactions. These markers are useful to identify the author of a change and to place the change on a timeline.

When a transaction T1 inserts a new row, it creates its first version and sets its unique identifier MVCCID1 as insert id. The MVCCID is stored as meta-data in record header:

_images/transaction_inserted_record.png

Until T1 commits, other transactions should not see this row. The MVCCID helps identifying the authors of database changes and place them on a time line, so others can know if the change is valid or not. In this case, anyone checking this row find the MVCCID1, find out that the owner is still active, hence the row must be (still) invisible.

After T1 commits, a new transaction T2 finds the row and decides to remove it. T2 does not remove this version, allowing others to access it, instead it gets an exclusive lock, to prevent others from changing it, and marks the version as deleted. It adds another MVCCID so others can identify the deleter:

_images/transaction_deleted_record.png

If T2 decides instead to update one of the record values, it must create a new version. Both versions are marked with transaction MVCCID, old version for delete and new version for insert. Old version also stores a link to the location of new version, and the row representations looks like this:

_images/transaction_updated_record.png

Currently, only T2 can see second row version, while all other transaction will continue to access the first version. The property of a version to be seen or not to be seen by running transactions is called visibility. The visibility property is relative to each transaction, some can consider it true, whereas others can consider it false.

A transaction T3 that starts after T2 executes row update, but before T2 commits, will not be able to see its new version, not even after T2 commits. The visibility of one version towards T3 depends on the state of its inserter and deleter when T3 started and preserves its status for the lifetime of T3.

As a matter of fact, the visibility of all versions in database towards on transaction does not depend on the changes that occur after transaction is started. Moreover, any new version added is also ignored. Consequently, the set of all visible versions in the database remains unchanged and form the snapshot of the transaction. Hence, snapshot isolation is provided by MVCC and it is a guarantee that all read queries made in a transaction see a consistent view of the database.

In CUBRID 10.0, snapshot is a filter of all invalid MVCCID's. An MVCCID is invalid if it is not committed before the snapshot is taken. To avoid updating the snapshot filter whenever a new transaction starts, the snapshot is defined using two border MVCCID's: the lowest active MVCCID and the highest committed MVCCID. Only a list of active MVCCID values between the border is saved. Any transaction starting after snapshot is guaranteed to have an MVCCID bigger than highest committed and is automatically considered invalid. Any MVCCID below lowest active must be committed and is automatically considered valid.

The snapshot filter algorithm that decides a version visibility queries the MVCCID markers used for insert and delete:

  Delete MVCCID
Valid Invalid
Insert MVCCID Valid Not visible Visible
Invalid Impossible Not visible

Table explained:

  • Valid insert MVCCID, valid delete MVCCID: Version was inserted and deleted (and both committed) before snapshot, hence it is not visible.
  • Valid insert MVCCID, invalid delete MVCCID: Version was inserted and committed, but it was not deleted or it was recently deleted, hence it is visible.
  • Invalid insert MVCCID, invalid delete MVCCID: Inserter did not commit before snapshot, and record is not deleted or delete was also not committed, hence version is not visible.
  • Invalid insert MVCCID, valid delete MVCCID: Inserter did not commit and deleter did - impossible case. If deleter is not the same as inserter, it could not see the version, and if it is, both insert and delete MVCCID must be valid or invalid.

Let's see how snapshot works (REPEATABLE READ isolation will be used to keep same snapshot during entire transaction):

Example 1: Inserting a new row

session 1 session 2
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> set transaction isolation level REPEATABLE READ;

Isolation level set to:
REPEATABLE READ
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> set transaction isolation level REPEATABLE READ;

Isolation level set to:
REPEATABLE READ
csql> CREATE TABLE tbl(host_year integer, nation_code char(3));
csql> COMMIT WORK;
 
-- insert a row without committing
csql> INSERT INTO tbl VALUES (2008, 'AUS');

-- current transaction sees its own changes
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2008  'AUS'
 
 
-- this snapshot should not see uncommitted row
csql> SELECT * FROM tbl;

There are no results.
csql> COMMIT WORK;
 
 
-- even though inserter did commit, this snapshot still can't see the row
csql> SELECT * FROM tbl;

There are no results.

-- commit to start a new transaction with a new snapshot
csql> COMMIT WORK;

-- the new snapshot should see committed row
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2008  'AUS'

Example 2: Deleting a row

session 1 session 2
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> set transaction isolation level REPEATABLE READ;

Isolation level set to:
REPEATABLE READ
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> set transaction isolation level REPEATABLE READ;

Isolation level set to:
REPEATABLE READ
csql> CREATE TABLE tbl(host_year integer, nation_code char(3));
csql> INSERT INTO tbl VALUES (2008, 'AUS');
csql> COMMIT WORK;
 
-- delete the row without committing
csql> DELETE FROM tbl WHERE nation_code = 'AUS';

-- this transaction sees its own changes
csql> SELECT * FROM tbl;

There are no results.
 
 
-- delete was not committed, so the row is visible to this snapshot
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2008  'AUS'
csql> COMMIT WORK;
 
 
-- delete was committed, but the row is still visible to this snapshot
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2008  'AUS'

-- commit to start a new transaction with a new snapshot
csql> COMMIT WORK;

-- the new snapshot can no longer see deleted row
csql> SELECT * FROM tbl;

There are no results.

Example 3: Updating a row

session 1 session 2
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> set transaction isolation level REPEATABLE READ;

Isolation level set to:
REPEATABLE READ
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> set transaction isolation level REPEATABLE READ;

Isolation level set to:
REPEATABLE READ
csql> CREATE TABLE tbl(host_year integer, nation_code char(3));
csql> INSERT INTO tbl VALUES (2008, 'AUS');
csql> COMMIT WORK;
 
-- delete the row without committing
csql> UPDATE tbl SET host_year = 2012 WHERE nation_code = 'AUS';

-- this transaction sees new version, host_year = 2012
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2012  'AUS'
 
 
-- update was not committed, so this snapshot sees old version
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2008  'AUS'
csql> COMMIT WORK;
 
 
-- update was committed, but this snapshot still sees old version
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2008  'AUS'

-- commit to start a new transaction with a new snapshot
csql> COMMIT WORK;

-- the new snapshot can see new version, host_year = 2012
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2012  'AUS'

Example 4: Different versions can be visible to different transactions

session 1 session 2 session 3
csql> INSERT INTO tbl VALUES (2008, 'AUS');
csql> COMMIT WORK;
   
-- update row
csql> UPDATE tbl SET host_year = 2012 WHERE nation_code = 'AUS';

csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2012  'AUS'
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2008  'AUS'
 
csql> COMMIT WORK;
   
csql> UPDATE tbl SET host_year = 2016 WHERE nation_code = 'AUS';

csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2016  'AUS'
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2008  'AUS'
csql> SELECT * FROM tbl;

    host_year  nation_code
===================================
         2012  'AUS'
VACUUM

Creating new versions for each update and keeping old versions on delete could lead to unlimited database size growth, definitely a major issue for a database. Therefore, a clean up system is necessary, to remove obsolete data and reclaim the occupied space for reuse.

Each row version goes through same stages:

  1. newly inserted, not committed, visible only to its inserter.
  2. committed, invisible to preceding transactions, visible to future transactions.
  3. deleted, not committed, visible to other transactions, invisible to the deleter.
  4. committed, still visible to preceding transactions, invisible to future transactions.
  5. invisible to all active transactions.
  6. removed from database.

The role of the clean up system is to get versions from stage 5 to 6. This system is called VACUUM in CUBRID.

VACUUM system was developed with the guidance of three principles:

  • VACUUM must be correct and complete. VACUUM should never remove data still visible to some and it should not miss any obsolete data.
  • VACUUM must be discreet. Since clean-up process changes database content, there may be some interference in the activity of live transactions, but it must be kept to the minimum possible.
  • VACUUM must be fast and efficient. If VACUUM is too slow and if it starts lagging, the database state can deteriorate, thus the overall performance can be affected.

With these principles in mind, VACUUM implementation uses existing recovery logging, because:

  • The address is kept among recovery data for both heap and index changes. This allows VACUUM go directly to target, rather than scanning the database.
  • Processing log data rarely interferes with the work of active workers.

Log recovery was adapted to VACUUM needs by adding MVCCID information to logged data. VACUUM can decide based on MVCCID if the log entry is ready to be processed. MVCCID's that are still visible to active transactions cannot be processed. In due time, each MVCCID becomes old enough and all changes using the MVCCID become invisible.

Each transaction keeps the oldest MVCCID it considers active. The oldest MVCCID considered active by all running transactions is determined by the smallest oldest MVCCID of all transactions. Anything below this value is invisible and VACUUM can clean.

VACUUM Parallel Execution

According to the third principle of VACUUM it must be fast and it should not fall behind active workers. It is obvious that one thread cannot handle all the VACUUM works if system workload is heavy, thus it had to be parallelized.

To achieve parallelization, the log data was split into fixed size blocks. Each block generates one vacuum job, when the time is right (the most recent MVCCID can be vacuumed, which means all logged operations in the block can be vacuumed). Vacuum jobs are picked up by multiple VACUUM Workers that clean the database based on relevant log entries found in the log block. The tracking of log blocks and generating vacuum jobs is done by the VACUUM Master.

VACUUM Data

Aggregated data on log blocks is stored in vacuum data file. Since the vacuum job generated by an operations occurs later in time, the data must be saved until the job can be executed, and it must also be persistent even if the server crashes. No operation is allowed to leak and not be vacuumed. If the server crashes, some jobs may be executed twice, which is preferable to not being executed at all.

After a job has been successfully executed, the aggregated data on the processed log block is removed.

Aggregated log block data is not added directly to vacuum data. A latch-free buffer is used to avoid synchronizing active working threads (which generate the log blocks and their aggregated data) with the vacuum system. VACUUM Master wakes up periodically, dumps everything in buffer to vacuum data, removes data already process and generates new jobs (if available).

VACUUM jobs

Vacuum job execution steps:

  1. Log pre-fetch. Vacuum master or workers pre-fetch log pages to be processed by the job.
  2. Repeat for each log record:
  1. Read log record.
  2. Check dropped file. If the log record points to dropped file, proceed to next log record.
  3. Execute index vacuum and collect heap OID's
  • If log record belongs to index, execute vacuum immediately.
  • If log record belongs to heap, collect OID to be vacuumed later.
  1. Execute heap vacuum based on collected OID's.
  2. Complete job. Mark the job as completed in vacuum data.

Several measures were taken to ease log page reading and to optimize vacuum execution.

Tracking dropped files

When a transaction drops a table or an index, it usually locks the affected table(s) and prevents others from accessing it. Opposed to active workers, VACUUM Workers are not allowed to use locking system, for two reasons: interference with active workers must be kept to the minimum, and VACUUM system is never supposed to stop as long as it has data to clean. Moreover, VACUUM is not allowed to skip any data that needs cleaning. This has two consequences:

  1. VACUUM doesn't stop from cleaning a file belonging to a dropped table or a dropped index until the dropper commits. Even if a transaction drops a table, its file is not immediately destroyed and it can still be accessed. The actual destruction is postponed until after commit.
  2. Before the actual file destruction, VACUUM system must be notified. The dropper sends a notification to VACUUM system and then waits for the confirmation. VACUUM works on very short iterations and it checks for new dropped files frequently, so the dropper doesn't have to wait for a long time.

After a file is dropped, VACUUM will ignore all found log entries that belong to the file. The file identifier, paired with an MVCCID that marks the moment of drop, is stored in a persistent file until VACUUM decides it is safe to remove it (the decision is based on the smallest MVCCID not yet vacuumed).

Lock Protocol

In the two-phase locking protocol, a transaction obtains a shared lock before it reads an object, and an exclusive lock before it updates the object so that conflicting operations are not executed simultaneously. The MVCC locking protocol, which is now used by CUBRID, does not require shared locks before reading rows (however intent shared lock on table object is still used to read its rows). If transaction T1 requires a lock, CUBRID checks if the requested lock conflicts with the existing one. If it does, transaction T1 enters a standby state and delays the lock. If another transaction T2 releases the lock, transaction T1 resumes and obtains it. Once the lock is released, the transaction do not acquire any new locks.

Granularity Locking

CUBRID uses a granularity locking protocol to decrease the number of locks. In the granularity locking protocol, a database can be modelled as a hierarchy of lockable units: row lock, table lock and database lock. Coarser locks have more granular locks.

If the locking granularities overlap, effects of a finer granularity are propagated in order to prevent conflicts. That is, if a shared lock is required on an instance of a table, an intent shared lock will be set on the table. If an exclusive lock is required on an instance of a table, an intent exclusive lock will be set on the table. An intent shared lock on a table means that a shared lock can be set on an instance of the table. An intent exclusive lock on a table means that a shared/exclusive lock can be set on an instance of the table. That is, if an intent shared lock on a table is allowed in one transaction, another transaction cannot obtain an exclusive lock on the table (for example, to add a new column). However, the second transaction may obtain a shared lock on the table. If an intent exclusive lock on the table is allowed in one transaction, another transaction cannot obtain a shared lock on the table (for example, a query on an instance of the tables cannot be executed because it is being changed).

A mechanism called lock escalation is used to limit the number of locks being managed. If a transaction has more than a certain number of locks (a number which can be changed by the lock_escalation system parameter), the system begins to require locks at the next higher level of granularity. This escalates the locks to a coarser level of granularity. CUBRID performs lock escalation when no transactions have a higher level of granularity in order to avoid a deadlock caused by lock conversion.

Lock Mode Types And Compatibility

CUBRID determines the lock mode depending on the type of operation to be performed by the transaction, and determines whether or not to share the lock depending on the mode of the lock preoccupied by another transaction. Such decisions concerning the lock are made by the system automatically. Manual assignment by the user is not allowed. To check the lock information of CUBRID, use the cubrid lockdb db_name command. For details, see lockdb.

  • Shared lock (shared lock, S_LOCK, no longer used with MVCC protocol)

    This lock is obtained before the read operation is executed on the object.

    It can be obtained by multiple transactions for the same object. At this time, transaction T2 and T3 can perform the read operation on the object concurrently, but not the update operation.

    Note

    • Shared locks are rarely used in CUBRID 10.0, because of MVCC. It is still used, mostly in internal database operations, to protect rows or index keys from being modified.
  • Exclusive lock (exclusive lock, X_LOCK)

    This lock is obtained before the update operation is executed on the object.

    It can only be obtained by one transaction. Transaction T1 obtains the exclusive lock first before it performs the update operation on a certain object X, and does not release it until transaction T1 is committed even after the update operation is completed. Therefore, transaction T2 and T3 cannot perform the read operation as well on X before transaction T1 releases the exclusive lock.

  • Intent lock

    This lock is set inherently in a higher-level object than a certain object to protect the lock on the object of a certain level.

    For example, when a shared lock is requested for a certain row, prevent a situation from occurring in which the table is locked by another transaction by setting the intent shared lock as well on the table at the higher level in hierarchy. Therefore, the intent lock is not set on rows at the lowest level, but is set on higher-level objects. The types of intent locks are as follows:

    • Intent shared lock (IS_LOCK)

      If the intent shared lock is set on the table, which is the higher-level object, as a result of the shared lock set on a certain row, another transaction cannot perform operations such as changing the schema of the table (e.g. adding a column or changing the table name) or updating all rows. However updating some rows or viewing all rows is allowed.

    • Intent exclusive lock (IX_LOCK)

      If the intent exclusive lock is set on the table, which is the higher-level object, as a result of the exclusive lock set on a certain row, another transaction cannot perform operations such as changing the schema of the table, updating or viewing all rows. However updating some rows is allowed.

    • Shared with intent exclusive lock(SIX_LOCK)

      This lock is set on the higher-level object inherently to protect the shared lock set on all objects at the lower hierarchical level and the intent exclusive lock on some object at the lower hierarchical level.

      Once the shared intent exclusive lock is set on a table, another transaction cannot change the schema of the table, update all/some rows or view all rows. However, viewing some rows is allowed.

  • Schema Lock

    A schema lock is acquired when executing DDL work.

    • Schema stability lock, SCH_S_LOCK

      This lock is acquired during compiling a query and it guarantees that the schema which is included in this query is not changed.

    • Schema modification lock, SCH_M_LOCK

      This lock is acquired during running DDL(ALTER/CREATE/DROP) and it protects that other transactions access the modified schema.

    Some DDL operations like ALTER, CREATE INDEX do not acquire SCH_M_LOCK directly. For example, CUBRID operates type checking about filtering expression when you create a filtered index; during this term, the lock which is kept to the target table is SCH_S_LOCK like other type checking operations. The lock is then upgraded to SIX_LOCK (other transactions are prevented from modifying target table rows, but they can continue reading them), and finally SCH_M_LOCK is requested to change the table schema. The method has a strength to increase the concurrency by allowing other transaction's operation during DDL operation's compilation and execution.

    However, it also has a weakness not to avoid a deadlock when DDL operations are operated at the same table at the same time. A deadlock case by loading indexes is as follows.

    T1 T2
    CREATE INDEX i_t_i on t(i) WHERE i > 0;
    
    CREATE INDEX i_t_j on t(j) WHERE j > 0;
    
    SCH_S_LOCK during checking types of "i > 0" case.  
      SCH_S_LOCK during checking types of "j > 0" case."j > 0"
    SIX_LOCK during index loading.  
      requesting SIX_LOCK but waiting T1's SIX_LOCK is released
    requesting SCH_M_LOCK but waiting T2's SCH_S_LOCK is released  

Note

This is a summarized description about locking.

  • There are row(instance) and schema(class) about objects of locking targets. The locks grouped by the type of objects they're used:
    • row locks: S_LOCK, X_LOCK
    • intention/schema locks: IX_LOCK, IS_LOCK, SIX_LOCK, SCH_S_LOCK, SCH_M_LOCK
  • Row locks and intention/schema locks affect each other.

The following table briefly shows the lock compatibility between the locks described above. Compatibility means that the lock requester can obtain a lock while the lock holder is keeping the lock obtained for a certain object.

Lock Compatibility

  • NULL: The status that any lock exists.

(O: TRUE, X: FALSE)

  Lock holder
NULL SCH-S IS S IX SIX X SCH-M
Lock requester NULL O O O O O O O O
SCH-S O O O O O O O O
IS O O O O O O X X
S O O O O X X X X
IX O O O X O X X X
SIX O O O X X X X X
X O O X X X X X X
SCH-M O X X X X X X X

Lock Transformation Table

  • NULL: The status that any lock exists.
  Granted lock mode
NULL SCH-S IS S IX SIX X SCH-M
Requested lock mode NULL NULL SCH-S IS S IX SIX X SCH-M
SCH-S SCH-S SCH-S IS S IX SIX X SCH-M
IS IS IS IS S IX SIX X SCH-M
S S S S S SIX SIX X SCH-M
IX IX IX IX SIX IX SIX X SCH-M
SIX SIX SIX SIX SIX SIX SIX X SCH-M
X X X X X X X X SCH-M
SCH-M SCH-M SCH-M SCH-M SCH-M SCH-M SCH-M SCH-M SCH-M
Examples using locks

For next few examples, REPEATABLE READ(5) isolation level will be used. READ COMMITTED has different rules for updating rows and will be presented in next section (reference here). The examples will make use of lockdb utility to show existing locks.

Locking example: For next example REPEATABLE READ(5) isolation will be used and it will prove that read and write on same row are not blocked. Also conflicting updates will be tried, where the second updater is blocked. When transaction T1 commits, T2 is unblocked but update is not permitted because of isolation level restrictions. If T1 would rollback, then T2 can proceed with its update.

T1 T2 Description
csql> ;au off
csql> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
csql> ;au off
csql> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
AUTOCOMMIT OFF and REPEATABLE READ
csql> CREATE TABLE tbl(a INT PRIMARY KEY, b INT);

csql> INSERT INTO tbl
      VALUES (10, 10),
             (30, 30),
             (50, 50),
             (70, 70);
csql> COMMIT;
   
csql> UPDATE tbl SET a = 90 WHERE a = 10;
 

First version of row where a = 10 is locked and updated. A new version where row has a = 90 is created and also locked.

cubrid lockdb:

OID =  0|   623|   4
Object type: Class = tbl.
Total mode of holders =   IX_LOCK,
     Total mode of waiters = NULL_LOCK.
Num holders=  1, Num blocked-holders=  0,
    Num waiters=  0
LOCK HOLDERS:
    Tran_index =   1, Granted_mode =  IX_LOCK

OID =  0|   650|   5
Object type: Instance of class ( 0|   623|   4) = tbl.
MVCC info: insert ID = 5, delete ID = missing.
Total mode of holders =    X_LOCK,
    Total mode of waiters = NULL_LOCK.
Num holders=  1, Num blocked-holders=  0,
    Num waiters=  0
LOCK HOLDERS:
    Tran_index =   1, Granted_mode =   X_LOCK

OID =  0|   650|   1
Object type: Instance of class ( 0|   623|   4) = tbl.
MVCC info: insert ID = 4, delete ID = 5.
Total mode of holders =    X_LOCK,
    Total mode of waiters = NULL_LOCK.
Num holders=  1, Num blocked-holders=  0,
    Num waiters=  0
LOCK HOLDERS:
    Tran_index =   1, Granted_mode =   X_LOCK
 
csql> SELECT * FROM tbl WHERE a <= 20;


            a            b
 ==========================
            10           10

Transaction T2 reads all rows where a <= 20. Since T1 did not commit its update, T2 will continue to see the row with a = 10 and will not lock it.:

cubrid lockdb:

OID =  0|   623|   4
Object type: Class = tbl.
Total mode of holders =   IX_LOCK,
    Total mode of waiters = NULL_LOCK.
Num holders=  2, Num blocked-holders=  0,
    Num waiters=  0
LOCK HOLDERS:
    Tran_index =   1, Granted_mode =  IX_LOCK
    Tran_index =   2, Granted_mode =  IS_LOCK
 
csql> UPDATE tbl
      SET a = a + 100
      WHERE a <= 20;

Transaction T2 now tries to update all rows having a <= 20. This means T2 will upgrade its lock on class to IX_LOCK and will also try to update the row = 10 by first locking it. However, T1 has locked it already, so T2 will be blocked.

cubrid lockdb:
OID =  0|   623|   4
Object type: Class = tbl.
Total mode of holders =   IX_LOCK,
    Total mode of waiters = NULL_LOCK.
Num holders=  2, Num blocked-holders=  0,
    Num waiters=  0
LOCK HOLDERS:
    Tran_index =   1, Granted_mode =  IX_LOCK
    Tran_index =   2, Granted_mode =  IX_LOCK

OID =  0|   650|   5
Object type: Instance of class ( 0|   623|   4) = tbl.
MVCC info: insert ID = 5, delete ID = missing.
Total mode of holders =   X_LOCK,
    Total mode of waiters = NULL_LOCK.
Num holders=  1, Num blocked-holders=  0,
    Num waiters=  0
LOCK HOLDERS:
    Tran_index =   1, Granted_mode =   X_LOCK

OID =  0|   650|   1
Object type: Instance of class ( 0|   623|   4) = tbl.
MVCC info: insert ID = 4, delete ID = 5.
Total mode of holders =    X_LOCK,
    Total mode of waiters =    X_LOCK.
Num holders=  1, Num blocked-holders=  0,
    Num waiters=  1
LOCK HOLDERS:
    Tran_index =   1, Granted_mode =   X_LOCK
LOCK WAITERS:
    Tran_index =   2, Blocked_mode =   X_LOCK
csql> COMMIT;
  T1's locks are released.
 
ERROR: Serializable conflict due
to concurrent updates
T2 is unblocked and will try to update the object T1 already updated. This is however not allowed in REPEATABLE READ isolation level and an error is thrown.
Locking to protect unique constraint

Two phase locking protocol in older CUBRID versions used index key locks to protect unique constraints and higher isolation restrictions. In CUBRID 10.0, key locking was removed. Isolation level restrictions are solved by MVCC snapshot, however unique constraint still needed some type of protection.

With MVCC, unique index can keep multiple versions at the same time, similarly to rows, each visible to different transactions. One is the last version, while the other versions are kept temporarily until they become invisible and can be removed by VACUUM. The rule to protect unique constraint is that all transactions trying to modify a key has to lock key's last existing version.

The below example uses REPEATABLE READ isolation to show the way locking prevents unique constraint violations.

T1 T2 Description
csql> ;au off
csql> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
csql> ;au off
csql> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
AUTOCOMMIT OFF and REPEATABLE READ
csql> CREATE TABLE tbl(a INT PRIMARY KEY, b INT);

csql> INSERT INTO tbl
      VALUES (10, 10),
             (30, 30),
             (50, 50),
             (70, 70);
csql> COMMIT;
   
csql> INSERT INTO tbl VALUES (20, 20);
  T1 inserts a new row into table and also locks it. The key 20 is therefore protected.
 
INSERT INTO tbl VALUES (20, 120);

T2 also inserts a new row into table and locks it. However, when it tries to insert it in primary key, it discovers key 20 already exists. T2 has to lock existing object, that T1 inserted, and is blocked until T1 commits.

cubrid lockdb:

OID =  0|   623|   4
Object type: Class = tbl.
Total mode of holders =   IX_LOCK,
    Total mode of waiters = NULL_LOCK.
Num holders=  2, Num blocked-holders=  0,
    Num waiters=  0
LOCK HOLDERS:
    Tran_index =   1, Granted_mode =  IX_LOCK
    Tran_index =   2, Granted_mode =  IX_LOCK

OID =  0|   650|   5
Object type: Instance of class ( 0|   623|   4) = tbl.
MVCC info: insert ID = 5, delete ID = missing.
Total mode of holders =   X_LOCK,
    Total mode of waiters =    X_LOCK.
Num holders=  1, Num blocked-holders=  0,
    Num waiters=  1
LOCK HOLDERS:
    Tran_index =   1, Granted_mode =   X_LOCK
LOCK WAITERS:
    Tran_index =   1, Blocked_mode =   X_LOCK

OID =  0|   650|   6
Object type: Instance of class ( 0|   623|   4) = tbl.
MVCC info: insert ID = 6, delete ID = missing.
Total mode of holders =    X_LOCK,
    Total mode of waiters = NULL_LOCK.
Num holders=  1, Num blocked-holders=  0,
    Num waiters=  0
LOCK HOLDERS:
    Tran_index =   2, Granted_mode =   X_LOCK
COMMIT;
  T1's locks are released.
 
ERROR: Operation would have caused
one or more unique constraint violations.
INDEX pk_tbl_a(B+tree: 0|186|640)
ON CLASS tbl(CLASS_OID: 0|623|4).
key: 20(OID: 0|650|6).
T2 is unlocked, finds the key has been committed and throws unique constraint violation error.
Transaction Deadlock

A deadlock is a state in which two or more transactions wait at once for another transaction's lock to be released. CUBRID resolves the problem by rolling back one of the transactions because transactions in a deadlock state will hinder the work of another transaction. The transaction to be rolled back is usually the transaction which has made the least updates; it is usually the one that started more recently. As soon as a transaction is rolled back, the lock held by the transaction is released and other transactions in a deadlock are permitted to proceed.

It is impossible to predict such deadlocks, but it is recommended that you reduce the range to which lock is applied by setting the index, shortening the transaction, or setting the transaction isolation level as low in order to decrease such occurrences.

Note that if you configure the value of error_log_level, which indicates the severity level, to NOTIFICATION, information on lock is stored in error log file of server upon deadlock occurrences.

Compared to older versions, CUBRID 10.0 no longer uses index key locking to read and write in index, thus deadlock occurrences have been greatly reduced. Another reason that deadlocks do not occur as often is that reading a range in index could lock many objects with high isolation levels in previous CUBRID versions, whereas CUBRID 10.0 uses no locks.

However, deadlocks are still possible when two transaction update same objects, but in a different order.

Example

session 1 session 2
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> set transaction isolation level REPEATABLE READ;

Isolation level set to:
REPEATABLE READ
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> set transaction isolation level REPEATABLE READ;

Isolation level set to:
REPEATABLE READ
csql> CREATE TABLE lock_tbl(host_year INTEGER,
                            nation_code CHAR(3));
csql> INSERT INTO lock_tbl VALUES (2004, 'KOR');
csql> INSERT INTO lock_tbl VALUES (2004, 'USA');
csql> INSERT INTO lock_tbl VALUES (2004, 'GER');
csql> INSERT INTO lock_tbl VALUES (2008, 'GER');
csql> COMMIT;
 
csql> DELETE FROM lock_tbl WHERE nation_code = 'KOR';

/* The two transactions lock different objects
 * and they do not block each-other.
 */
csql> DELETE FROM lock_tbl WHERE nation_code = 'GER';
csql> DELETE FROM lock_tbl WHERE host_year=2008;

/* T1 want's to modify a row locked by T2 and is blocked */
 
 
csql> DELETE FROM lock_tbl WHERE host_year = 2004;

/* T2 now want to delete the row blocked by T1
 * and a deadlock is created.
 */
ERROR: Your transaction (index 1, dba@ 090205|4760)
       has been unilaterally aborted by the system.

/* System rolled back the transaction 1 to resolve a deadlock */
/* T2 is unblocked and proceeds on modifying its rows. */
Transaction Lock Timeout

CUBRID provides the lock timeout feature, which sets the waiting time for the lock until the transaction lock setting is allowed.

If the lock is allowed within the lock timeout, CUBRID rolls back the transaction and outputs an error message when the timeout has passed. If a transaction deadlock occurs within the lock timeout, CUBRID rolls back the transaction whose waiting time is closest to the timeout.

Setting the Lock Timeout

The system parameter lock_timeout in the $CUBRID/conf/cubrid.conf file or the SET TRANSACTION statement sets the timeout (in seconds) during which the application will wait for the lock and rolls back the transaction and outputs an error message when the specified time has passed. The default value of the lock_timeout parameter is -1, which means the application will wait indefinitely until the transaction lock is allowed. Therefore, the user can change this value depending on the transaction pattern of the application. If the lock timeout value has been set to 0, an error message will be displayed as soon as a lock occurs.

SET TRANSACTION LOCK TIMEOUT timeout_spec [ ; ]
timeout_spec:
- INFINITE
- OFF
- unsigned_integer
- variable
  • INFINITE : Wait indefinitely until the transaction lock is allowed. Has the same effect as setting the system parameter lock_timeout to -1.
  • OFF : Do not wait for the lock, but roll back the transaction and display an error message. Has the same effect as setting the system parameter lock_timeout to 0.
  • unsigned_integer : Set in seconds. Wait for the transaction lock for the specified time period.
  • variable : A variable can be specified. Wait for the transaction lock for the value stored by the variable.

Example 1

vi $CUBRID/conf/cubrid.conf
...
lock_timeout = 10s
...

Example 2

SET TRANSACTION LOCK TIMEOUT 10;

Checking the Lock Timeout

You can check the lock timeout set for the current application by using the GET TRANSACTION statement, or store this value in a variable.

GET TRANSACTION LOCK TIMEOUT [ { INTO | TO } variable ] [ ; ]

Example

GET TRANSACTION LOCK TIMEOUT;

         Result
===============
  1.000000e+001

Checking and Handling Lock Timeout Error Message

The following message is displayed if lock timeout occurs in a transaction that has been waiting for another transaction's lock to be released.

Your transaction (index 2, user1@host1|9808) timed out waiting on IX_LOCK lock on class tbl. You are waiting for
user(s) user1@host1|csql(9807), user1@host1|csql(9805) to finish.
  • Your transaction(index 2 ...): This means that the index of the transaction that was rolled back due to timeout while waiting for the lock is 2. The transaction index is a number that is sequentially assigned when the client connects to the database server. You can also check this number by executing the cubrid lockdb utility.
  • (... user1@host1|9808): cub_user is the login ID of the client and the part after @ is the name of the host where the client was running. The part after| is the process ID (PID) of the client.
  • IX_LOCK: This means the exclusive lock set on the object to perform data update. For details, see Lock Mode Types And Compatibility.
  • user1@host1|csql(9807), user1@host1|csql(9805): Another transactions waiting for termination to lock IX_LOCK

That is, the above lock error message can be interpreted as meaning that "Because another client is holding X_LOCK on a specific row in the participant table, transaction 3 which running on the host host1 waited for the lock and the timeout has passed". If you want to check the lock information of the transaction specified in the error message, you can do so by using the cubrid lockdb utility to search for the OID value (ex: 0|636|34) of a specific row where the X_LOCK is set currently to find the transaction ID currently holding the lock, the client program name and the process ID (PID). For details, see lockdb. You can also check the transaction lock information in the CUBRID Manager.

You can organize the transactions by checking uncommitted queries through the SQL log after checking the transaction lock information in the manner described above. For information on checking the SQL log, see Broker Logs.

Also, you can forcefully stop problematic transactions by using the cubrid killtran utility. For details, see killtran.

Transaction Isolation Level

The transaction isolation level is determined based on how much interference occurs. The higher isolation means the less interference from other transactions and more serializable. The lower isolation means the more interference from other transactions and higher level of concurrency. You can control the level of consistency and concurrency specific to a service by setting appropriate isolation level.

Note

A transaction can be restored in all supported isolation levels because updates are not committed before the end of the transaction.

SET TRANSACTION ISOLATION LEVEL

You can set the level of transaction isolation by using isolation_level and the SET TRANSACTION statement in the $CUBRID/conf/cubrid.conf. The level of READ COMMITTED is set by default, which indicates the level 4 through level 4 to 6 (levels 1 to 3 were used by older versions of CUBRID and are now obsolete). For details, see Database Concurrency.

SET TRANSACTION ISOLATION LEVEL isolation_level_spec ;

isolation_level_spec:
    SERIALIZABLE | 6
    REPETABLE READ | 5
    READ COMMITTED | CURSOR STABILITY | 4

Example 1

vi $CUBRID/conf/cubrid.conf
...

isolation_level = 4
...

-- or

isolation_level = "TRAN_READ_COMMITTED"

Example 2

SET TRANSACTION ISOLATION LEVEL 4;
-- or
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

Levels of Isolation Supported by CUBRID

Name Description
READ COMMITTED (4) Another transaction T2 cannot update the schema of table A while transaction T1 is viewing table A. Transaction T1 may experience R read (non-repeatable read) that was updated and committed by another transaction T2 when it is repeatedly retrieving the record R.
REPEATABLE READ (5) Another transaction T2 cannot update the schema of table A while transaction T1 is viewing table A. Transaction T1 may experience phantom read for the record R that was inserted by another transaction T2 when it is repeatedly retrieving a specific record.
SERIALIZABLE (6) Temporarily disabled - details in SERIALIZABLE Isolation Level

If the transaction level is changed in an application while a transaction is executed, the new level is applied to the rest of the transaction being executed. It is recommended that to modify the transaction isolation level when a transaction starts (after commit, rollback or system restart) because an isolation level which has already been set does not apply to the entire transaction, but can be changed during the transaction.

GET TRANSACTION ISOLATION LEVEL

You can assign the current isolation level to variable by using the GET TRANSACTION ISOLATION LEVEL statement. The following is a statement that verifies the isolation level.

GET TRANSACTION ISOLATION LEVEL [ { INTO | TO } variable ] [ ; ]
GET TRANSACTION ISOLATION LEVEL;
       Result
=============
  READ COMMITTED
READ COMMITTED Isolation Level

A relatively low isolation level (4). A dirty read does not occur, but non-repeatable or phantom read may. That is, transaction T1 can read another value because insert or update by transaction T2 is allowed while transaction T1 is repeatedly retrieving one object.

The following are the rules of this isolation level:

  • Transaction T1 cannot read or modify the record inserted by another transaction T2. The record is instead ignored.
  • Transaction T1 can read the record being updated by another transaction T2 and it sees the record's last committed version (but it cannot see uncommitted versions).
  • Transaction T1 cannot modify the record being updated by another transaction T2. T1 waits for T2 to commit and it re-evaluates record values. If the re-evaluation test is passed, T1 modifies the record, otherwise it ignores it.
  • Transaction T1 can modify the record being viewed by another transaction T2.
  • Transaction T1 can update/insert record to the table being viewed by another transaction T2.
  • Transaction T1 cannot change the schema of the table being viewed by another transaction T2.
  • Transaction T1 creates a new snapshot with each executed statement, thus phantom or non-repeatable read may occur.

This isolation level follows MVCC locking protocol for an exclusive lock. A shared lock on a row is not required; however, an intent lock on a table is released when a transaction terminates to ensure repeatable read on the schema.

Example

The following example shows that a phantom or non-repeatable read may occur because another transaction can add or update a record while one transaction is performing the object read but repeatable read for the table schema update is ensured when the transaction level of the concurrent transactions is READ COMMITTED.

session 1 session 2
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

Isolation level set to:
READ COMMITTED
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

Isolation level set to:
READ COMMITTED
csql> CREATE TABLE isol4_tbl(host_year integer, nation_code char(3));

csql> INSERT INTO isol4_tbl VALUES (2008, 'AUS');

csql> COMMIT;
 
 
csql> SELECT * FROM isol4_tbl;

    host_year  nation_code
===================================
         2008  'AUS'
csql> INSERT INTO isol4_tbl VALUES (2004, 'AUS');
csql> INSERT INTO isol4_tbl VALUES (2000, 'NED');
csql> COMMIT;
 
 
/* phantom read occurs because tran 1 committed */
csql> SELECT * FROM isol4_tbl;

    host_year  nation_code
===================================
         2008  'AUS'
         2004  'AUS'
         2000  'NED'
csql> UPDATE isol4_tbl
csql> SET nation_code = 'KOR'
csql> WHERE host_year = 2008;
csql> COMMIT;
 
 
/* unrepeatable read occurs because tran 1 committed */
csql> SELECT * FROM isol4_tbl;

    host_year  nation_code
===================================
         2008  'KOR'
         2004  'AUS'
         2000  'NED'
csql> ALTER TABLE isol4_tbl ADD COLUMN gold INT;

/* unable to alter the table schema until tran 2 committed */
 
 
/* repeatable read is ensured while
 * tran_1 is altering table schema
 */

csql> SELECT * FROM isol4_tbl;

    host_year  nation_code
===================================
         2008  'KOR'
         2004  'AUS'
         2000  'NED'
 
csql> COMMIT;
 
csql> SELECT * FROM isol4_tbl;

/* unable to access the table until tran_1 committed */
csql> COMMIT;
 
 
host_year  nation_code  gold
===================================
  2008  'KOR'           NULL
  2004  'AUS'           NULL
  2000  'NED'           NULL
READ COMMITTED UPDATE RE-EVALUATION

READ COMMITTED isolation treats concurrent row updates differently than higher isolation levels. In higher isolation levels, if T2 tries to modify a row already updated by concurrent transaction T1, it is blocked until T1 commits and rollbacks, and if T1 commits, T2 aborts its statement execution, throwing serialization error. Under READ COMMITTED isolation, after T1 commits, T2 does not immediately abort its statement execution and re-evaluates the new version, which is not considered committed and would not violate any restrictions for this isolation. If the predicate used to select previous version is still true for the new version, T2 goes ahead and modifies the new version. If the predicate is no longer true, T2 just ignores the record as if the predicate was never satisfied.

Example:

session 1 session 2
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> SET TRANSACTION ISOLATION LEVEL 4;

Isolation level set to:
READ COMMITTED
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> SET TRANSACTION ISOLATION LEVEL 4;

Isolation level set to:
READ COMMITTED
csql> CREATE TABLE isol4_tbl(host_year integer, nation_code char(3));
csql> INSERT INTO isol4_tbl VALUES (2000, 'KOR');
csql> INSERT INTO isol4_tbl VALUES (2004, 'USA');
csql> INSERT INTO isol4_tbl VALUES (2004, 'GER');
csql> INSERT INTO isol4_tbl VALUES (2008, 'GER');
csql> COMMIT;
 
csql> UPDATE isol4_tbl
csql> SET host_year = host_year - 4
csql> WHERE nation_code = 'GER';

/* T1 locks and modifies (2004, 'GER') to (2000, 'GER') */
/* T1 locks and modifies (2008, 'GER') to (2004, 'GER') */
 
 
csql> UPDATE isol4_tbl
csql> SET host_year = host_year + 4
csql> WHERE host_year >= 2004;

/* T2 snapshot will try to modify three records:
 * (2004, 'USA'), (2004, 'GER'), (2008, 'GER')
 *
 * T2 locks and modifies (2004, 'USA') to (2008, 'USA')
 * T2 is blocked on lock on (2004, 'GER').
 */
csql> COMMIT;

/* T1 releases locks on modified rows. */
 
 
/* T2 is unblocked and will do the next steps:
 *
 *   T2 finds (2004, 'GER') has a new version (2000, 'GER')
 *   that doesn't satisfy predicate anymore.
 *   T2 releases the lock on object and ingores it.
 *
 *   T2 finds (2008, 'GER') has a new version (2004, 'GER')
 *   that still satisfies the predicate.
 *   T2 keeps the lock and changes row to (2008, 'GER')
 */
 
csql> SELECT * FROM isol4_tbl;

    host_year  nation_code
===================================
         2000  'KOR'
         2000  'GER'
         2008  'USA'
         2008  'GER'
REPEATABLE READ Isolation Level

A relatively high isolation level (5). Dirty, non-repeatable, and phantom reads do not occur due to snapshot isolation. However, it's still not truly serializable, transaction execution cannot be defined as if there were no other transactions running at the same time. More complex anomalies, like write skews, that a serializable snapshot isolation level should not allow still occur.

In a write skew anomaly, two transactions concurrently read overlapping data sets and make disjoint updates on the overlapped data set, neither having seen the update performed by the other. In a serializable system, such anomaly would be impossible, since one transaction must occur first and the second transaction should see the update of the first transaction.

The following are the rules of this isolation level:

  • Transaction T1 cannot read or modify the record inserted by another transaction T2. The record is instead ignored.
  • Transaction T1 can read the record being updated by another transaction T2 and it will see the record's last committed version.
  • Transaction T1 cannot modify the record being updated by another transaction T2.
  • Transaction T1 can modify the record being viewed by another transaction T2.
  • Transaction T1 can update/insert record to the table being viewed by another transaction T2.
  • Transaction T1 cannot change the schema of the table being viewed by another transaction T2.
  • Transaction T1 creates a unique snapshot valid throughout the entire duration of the transaction.

Example

The following example shows that non-repeatable and phantom reads may not occur because of snapshot isolation. However, write skews are possible, which means the isolation level is not serializable.

session 1 session 2
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> SET TRANSACTION ISOLATION LEVEL 5;

Isolation level set to:
REPEATABLE READ
csql> ;autocommit off

AUTOCOMMIT IS OFF

csql> SET TRANSACTION ISOLATION LEVEL 5;

Isolation level set to:
REPEATABLE READ
csql> CREATE TABLE isol5_tbl(host_year integer, nation_code char(3));
csql> CREATE UNIQUE INDEX isol5_u_idx
          on isol5_tbl(nation_code, host_year);
csql> INSERT INTO isol5_tbl VALUES (2008, 'AUS');
csql> INSERT INTO isol5_tbl VALUES (2004, 'AUS');

csql> COMMIT;
 
 
csql> SELECT * FROM isol5_tbl WHERE nation_code='AUS';

    host_year  nation_code
===================================
         2004  'AUS'
         2008  'AUS'
csql> INSERT INTO isol5_tbl VALUES (2004, 'KOR');
csql> INSERT INTO isol5_tbl VALUES (2000, 'AUS');

/* able to insert new rows  */
csql> COMMIT;
 
 
csql> SELECT * FROM isol5_tbl WHERE nation_code='AUS';

/* phantom read connot occur due to snapshot isolation */

    host_year  nation_code
===================================
         2004  'AUS'
         2008  'AUS'
csql> UPDATE isol5_tbl
csql> SET host_year = 2012
csql> WHERE nation_code = 'AUS' and
csql> host_year=2008;

/* able to update rows viewed by T2 */
csql> COMMIT;
 
 
csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS';

/* non-repeatable read cannot occur due to snapshot isolation */

    host_year  nation_code
===================================
         2004  'AUS'
         2008  'AUS'
 
csql> COMMIT;
csql> SELECT * FROM isol5_tbl WHERE host_year >= 2004;

    host_year  nation_code
===================================
         2004  'AUS'
         2004  'KOR'
         2012  'AUS'

csql> UPDATE isol5_tbl
csql> SET nation_code = 'USA'
csql> WHERE nation_code = 'AUS' and
csql> host_year = 2004;

csql> COMMIT;
csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS';

    host_year  nation_code
===================================
         2000  'AUS'
         2004  'AUS'
         2012  'AUS'

csql> UPDATE isol5_tbl
csql> SET nation_code = 'NED'
csql> WHERE nation_code = 'AUS' and
csql> host_year = 2012;

csql> COMMIT;
/* T1 and T2 first have selected each 3 throws and rows (2004, 'AUS'), (2012, 'AUS') overlapped.
 * Then T1 modified (2004, 'AUS'), while T2 modified (2012, 'AUS'), without blocking each other.
 * In a serial execution, the result of select query for T1 or T2, whichever executes last, would be different.
 */
 
csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS';

    host_year  nation_code
===================================
         2000  'AUS'
csql> ALTER TABLE isol5_tbl ADD COLUMN gold INT;

/* unable to alter the table schema until tran 2 committed */
 
 
/* repeatable read is ensured while tran_1 is altering
 * table schema
 */

csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS';

    host_year  nation_code
===================================
         2000  'AUS'
 
csql> COMMIT;
 
csql> SELECT * FROM isol5_tbl WHERE nation_code = 'AUS';

/* unable to access the table until tran_1 committed */
csql> COMMIT;
 
 
host_year  nation_code  gold
===================================
  2000  'AUS'           NULL
SERIALIZABLE Isolation Level

CUBRID 10.0 SERIALIZABLE isolation level is identical to REPEATABLE READ isolation level. As explained in REPEATABLE READ Isolation Level section, even though SNAPSHOT isolation ensures non-repeatable read and phantom read anomalies do not happen, write skew anomalies are still possible. To protect against write skew, index key locks for read may be used. Alternatively, there are many works that describe complex systems to provide SERIALIZABLE SNAPSHOT ISOLATION, by aborting transactions with the potential of creating an isolation conflict. One such system will be provided in a future CUBRID version.

The keyword was not removed for backward compatibility reasons, but remember, it is similar to REPEATABLE READ.

How to Handle Dirty Record

CUBRID flushes dirty data (or dirty record) in the client buffers to the database (server) such as the following situations. In additions to those, there can be more situations where flushes can be performed.

  • Dirty data can be flushed to server when a transaction is committed.
  • Some of dirty data can be flushed to server when a lot of data is loaded into the client buffers.
  • Dirty data of table A can be flushed to server when the schema of table A is updated.
  • Dirty data of table A can be flushed to server when the table A is retrieved (SELECT)
  • Some of dirty data can be flushed to server when a server function is called.
Transaction Termination and Restoration

The restore process in CUBRID makes it possible that the database is not affected even if a software or hardware error occurs. In CUBRID, all read and update commands that are made during a transaction must be atomic. This means that either all of the transaction's commands are committed to the database or none are. The concept of atomicity is extended to the set of operations that consists of a transaction. The transaction must either commit so that all effects are permanently applied to the database or roll back so that all effects are removed. To ensure transaction atomicity, CUBRID applies the effects of the committed transaction again every time an error occurs without the updates of the transaction being written to the disk. CUBRID also removes the effects of partially committed transactions in the database every time the site fails (some transactions may have not committed or applications may have requested to cancel transactions). This restore feature eases the burden for the applications of maintaining the database consistency depending on the system error. The restore process used in CUBRID is based on the undo/redo logging mechanism.

CUBRID provides an automatic restore method to maintain the transaction atomicity when a hardware or software error occurs. You do not have to take the responsibility for restore since CUBRID's restore feature always returns the database to a consistent state even when an application or computer system error occurs. For this purpose, CUBRID automatically rolls back part of committed transactions when the application fails or the user requests explicitly. For example, a system error that occurred during the execution of the COMMIT WORK statement must be stopped if the transaction has not committed yet (it cannot be confirmed that the user's operation has been committed). Automatic stop prevents errors causing undesired changes to the database by canceling uncommitted updates.

Restarting Database

CUBRID uses log volumes/files and database backups to restore committed or uncommitted transactions when system or media (disk) error occurs. Logs are also used to support the user-specified rollback. A log consists of a collection of sequential files created by CUBRID. The most recent log is called the active log, and the rest are called archive logs. A log file refers to both the active and archive logs.

All updates of the database are written to the log. Actually, two copies of the updates are logged. The first one is called a before image (UNDO log) and used to restore data during execution of the user-specified ROLLBACK WORK statement or during media or system errors. The second copy is an after image (REDO log) and used to re-apply the updates when media or system error occurs.

When the active log is full, CUBRID copies it to an archive log to store in the disk. The archive log is needed to restore the database when a system failure occurs.

Normal Termination or Error

CUBRID restores the database if it restarts due to a normal termination or a device error. The restore process re-applies the committed changes that have not been applied to the database and removes the uncommitted changes stored in the database. The general operation of the database resumes after the restore is completed. This restore process does not use any archive logs or database backup.

In a client/server environment, the database can restart by using the cubrid server utility.

Media Error

The user's intervention is somewhat needed to restart the database after media error occurs. The first step is to restore the database by installing a backup of a known good state. In CUBRID, the most recent log file (the one after the last backup) must be installed. This specific log (archive or active) is applied to a backup copy of the database. As with normal termination, the database can restart after restoration is committed.

Note

To minimize the possibility of losing database updates, it is recommended to create a snapshot and store it in the backup media before it is deleted from the disk. The DBA can backup and restore the database by using the cubrid backupdb and cubrid restoredb utilities. For details on these utilities, see backupdb.

Trigger

CREATE TRIGGER
Guidelines for Trigger Definition

Trigger definition provides various and powerful functionalities. Before creating a trigger, you must consider the following:

  • Does the trigger condition expression cause unexpected results (side effect)?

    You must use the SQL statements within an expectable range.

  • Does the trigger action change the table given as its event target?

    While this type of design is not forbidden in the trigger definition, it must be carefully applied, because a trigger can be created that falls into an infinite loop. When the trigger action modifies the event target table, the same trigger can be called again. If a trigger occurs in a statement that contains a WHERE clause, there is no side effect in the table affected by the WHERE clause.

  • Does the trigger cause unnecessary overhead?

    If the desired action can be expressed more effectively in the source, implement it directly in the source.

  • Is the trigger executed recursively?

    If the trigger action calls a trigger and this trigger calls the previous trigger again, a recursive loop is created in the database. If a recursive loop is created, the trigger may not be executed correctly, or the current session must be forced to terminate to break the ongoing infinite loop.

  • Is the trigger definition unique?

    A trigger defined in the same table or the one started in the same action becomes the cause of an unrecoverable error. A trigger in the same table must have a different trigger event. In addition, trigger priority must be explicitly and unambiguously defined.

Trigger Definition

A trigger is created by defining a trigger target, condition and action to be performed in the CREATE TRIGGER statement. A trigger is a database object that performs a defined action when a specific event occurs in the target table.

CREATE TRIGGER trigger_name
[ STATUS { ACTIVE | INACTIVE } ]
[ PRIORITY key ]
<event_time> <event_type> [<event_target>]
[ IF condition ]
EXECUTE [ AFTER | DEFERRED ] action
[COMMENT 'trigger_comment'];

<event_time> ::=
    BEFORE |
    AFTER  |
    DEFERRED

<event_type> ::=
    INSERT |
    STATEMENT INSERT |
    UPDATE |
    STATEMENT UPDATE |
    DELETE |
    STATEMENT DELETE |
    ROLLBACK |
    COMMIT

<event_target> ::=
    ON table_name |
    ON table_name [ (column_name) ]

<condition> ::=
    expression

<action> ::=
    REJECT |
    INVALIDATE TRANSACTION |
    PRINT message_string |
    INSERT statement |
    UPDATE statement |
    DELETE statement
  • trigger_name: specifies the name of the trigger to be defined.
  • [ STATUS { ACTIVE | INACTIVE } ]: Defines the state of the trigger (if not defined, the default value is ACTIVE).
    • If ACTIVE state is specified, the trigger is executed every time the corresponding event occurs.
    • If INACTIVE state is specified, the trigger is not executed even when the corresponding event occurs. The state of the trigger can be modified. For details, see ALTER TRIGGER section.
  • [ PRIORITY key ]: specifies a trigger priority if multiple triggers are called for an event. key must be a floating point value that is not negative. If the priority is not defined, the lowest priority 0 is assigned. Triggers having the same priority are executed in a random order. The priority of triggers can be modified. For details, see ALTER TRIGGER section.
  • <event_time>: specifies the point of time when the conditions and actions are executed. BEFORE, AFTER or DEFERRED can be specified. For details, see the Event Time section.
  • <event_type>: trigger types are divided into a user trigger and a table trigger. For details, see the Trigger Event Type section.
  • <event_target>: An event target is used to specify the target for the trigger to be called. For details, see the Trigger Event Target section.
  • <condition>: specifies the trigger condition. For details, see the Trigger Condition section.
  • <action>: specifies the trigger action. For details, see the Trigger Action section.
  • trigger_comment: specifies a trigger's comment.

The following example shows how to create a trigger that rejects the update if the number of medals won is smaller than 0 when an instance of the participant table is updated. As shown below, the update is rejected if you try to change the number of gold (gold) medals that Korea won in the 2004 Olympic Games to a negative number.

CREATE TRIGGER medal_trigger
BEFORE UPDATE ON participant
IF new.gold < 0 OR new.silver < 0 OR new.bronze < 0
EXECUTE REJECT;

UPDATE participant SET gold = -5 WHERE nation_code = 'KOR'
AND host_year = 2004;
ERROR: The operation has been rejected by trigger "medal_trigger".
Event Time

Specifies the point of time when trigger conditions and actions are executed. The types of event time are BEFORE, AFTER and DEFERRED.

  • BEFORE: checks the condition before the event is processed.
  • AFTER: checks the condition after the event is processed.
  • DEFERRED: checks the condition at the end of the transaction for the event. If you specify DEFERRED, you cannot use COMMIT or ROLLBACK as the event type.
Trigger Type

User Trigger

  • A trigger relevant to a specific user of the database is called a user trigger.
  • A user trigger has no event target and is executed only by the owner of the trigger (the user who created the trigger).
  • Event types that define a user trigger are COMMIT and ROLLBACK.

Table Trigger

  • A trigger that has a table as the event target is called a table trigger (class trigger).
  • A table trigger can be seen by all users who have the SELECT authorization on a target table.
  • Event types that define a table trigger are instance and statement events.
Trigger Event Type
  • Instance events: An event type whose unit of operation is an instance. The types of instance (record) events are as follows:
    • INSERT
    • UPDATE
    • DELETE
  • Statement events: If you define a statement event as an event type, the trigger is called only once when the trigger starts even when there are multiple objects (instances) affected by the given statement (event). The types of statement events are as follows:
    • STATEMENT INSERT
    • STATEMENT UPDATE
    • STATEMENT DELETE
  • Other events: COMMIT and ROLLBACK cannot be applied to individual instances.
    • COMMIT
    • ROLLBACK

The following example shows how to use an instance event. The example trigger is called by each instance affected by the database update. For example, if the score values of five instances in the history table are modified, the trigger is called five times.

CREATE TABLE update_logs(event_code INTEGER, score VARCHAR(10), dt DATETIME);

CREATE TRIGGER example
BEFORE UPDATE ON history(score)
EXECUTE INSERT INTO update_logs VALUES (obj.event_code, obj.score, SYSDATETIME);

If you want the trigger to be called only once, before the first instance of the score column is updated, use the STATEMENT UPDATE type as the following example.

The following example shows how to use a statement event. If you define a statement event, the trigger is called only once before the first instance gets updated even when there are multiple instances affected by the update.

CREATE TRIGGER example
BEFORE STATEMENT UPDATE ON history(score)
EXECUTE PRINT 'There was an update on history table';

Note

  • You must specify the event target when you define an instance or statement event as the event type.
  • COMMIT and ROLLBACK cannot have an event target.
Trigger Event Target

An event target specifies the target for the trigger to be called. The target of a trigger event can be specified as a table or column name. If a column name is specified, the trigger is called only when the specified column is affected by the event. If a column is not specified, the trigger is called when any column of the table is affected. Only UPDATE and STATEMENT UPDATE events can specify a column as the event target.

The following example shows how to specify the score column of the history table as the event target of the example trigger.

CREATE TABLE update_logs(event_code INTEGER, score VARCHAR(10), dt DATETIME);

CREATE TRIGGER example
BEFORE UPDATE ON history(score)
EXECUTE INSERT INTO update_logs VALUES (obj.event_code, obj.score, SYSDATETIME);
Combination of Event Type and Target

A database event calling triggers is identified by the trigger event type and event target in a trigger definition. The following table shows the trigger event type and target combinations, along with the meaning of the CUBRID database event that the trigger event represents.

Event Type Event Target Corresponding Database Activity
UPDATE Table Trigger is called when the UPDATE statement for a table is executed.
INSERT Table Trigger is called when the INSERT statement for a table is executed.
DELETE Table Trigger is called when the DELETE statement for a table is executed.
COMMIT None Trigger is called when database transaction is committed.
ROLLBACK None Trigger is called when database transaction is rolled back.
Trigger Condition

You can specify whether a trigger action is to be performed by defining a condition when defining the trigger.

  • If a trigger condition is specified, it can be written as an independent compound expression that evaluates to true or false. In this case, the expression can contain arithmetic and logical operators allowed in the WHERE clause of the SELECT statement. The trigger action is performed if the condition is true; if it is false, action is ignored.
  • If a trigger condition is omitted, the trigger becomes an unconditional trigger, which refers to that the trigger action is performed whenever it is called.

The following example shows how to use a correlation name in an expression within a condition. If the event type is INSERT, UPDATE or DELETE, the expression in the condition can refer to the correlation names obj, new or old to access a specific column. This example prefixes obj to the column name in the trigger condition to show that the example trigger tests the condition based on the current value of the record column.

CREATE TRIGGER example
BEFORE UPDATE ON participant
IF new.gold < 0 OR new.silver < 0 OR new.bronze < 0
EXECUTE REJECT;

The following example shows how to use the SELECT statement in an expression within a condition. The trigger in this example uses the SELECT statement that contains an aggregate function COUNT (*) to compare the value with a constant. The SELECT statement must be enclosed in parentheses and must be placed at the end of the expression.

CREATE TRIGGER example
BEFORE INSERT ON participant
IF 1000 >  (SELECT COUNT(*) FROM participant)
EXECUTE REJECT;

Note

The expression given in the trigger condition may cause side effects on the database if a method is called while the condition is performed. A trigger condition must be constructed to avoid unexpected side effects in the database.

Correlation Name

You can access the column values defined in the target table by using a correlation name in the trigger definition. A correlation name is the instance that is actually affected by the database operation calling the trigger. A correlation name can also be specified in a trigger condition or action.

The types of correlation names are new, old and obj. These correlation names can be used only in instance triggers that have an INSERT, UPDATE or DELETE event.

As shown in the table below, the use of correlation names is further restricted by the event time defined for the trigger condition.

  BEFORE AFTER or DERERRED
INSERT new obj
UPDATE

obj

new

obj

old (AFTER)

DELETE obj N/A
Correlation Name Representative Attribute Value
obj Refers to the current attribute value of an instance. This can be used to access attribute values before an instance is updated or deleted. It is also used to access attribute values after an instance has been updated or inserted.
new Refers to the attribute value proposed by an insert or update operation. The new value can be accessed only before the instance is actually inserted or updated.
old
Refers to the attribute value that existed prior to the completion of an update operation. This value is maintained
only while the trigger is being performed. Once the trigger is completed, the old values get lost.
Trigger Action

A trigger action describes what to be performed if the trigger condition is true or omitted. If a specific point of time (AFTER or DEFERRED) is not given in the action clause, the action is executed at once as the trigger event.

The following is a list of actions that can be used for trigger definitions.

  • REJECT: discards the operation that initiated the trigger and keeps the former state of the database, if the condition is not true. Once the operation is performed, REJECT is allowed only when the action time is BEFORE because the operation cannot be rejected. Therefore, you must not use REJECT if the action time is AFTER or DERERRED.
  • INVALIDATE TRANSACTION: allows the event operation that called the trigger, but does not allow the transaction that contains the commit to be executed. You must cancel the transaction by using the ROLLBACK statement if it is not valid. Such action is used to protect the database from having invalid data after a data-changing event happens.
  • PRINT: displays trigger actions on the terminal screen in text messages, and can be used during developments or tests. The results of event operations are not rejected or discarded.
  • INSERT: inserts one or more new instances to the table.
  • UPDATE: updates one or more column values in the table.
  • DELETE: deletes one or more instances from the table.

The following example shows how to define an action when a trigger is created. The medal_trig trigger defines REJECT in its action. REJECT can be specified only when the action time is BEFORE.

CREATE TRIGGER medal_trig
BEFORE UPDATE ON participant
IF new.gold < 0 OR new.silver < 0 OR new.bronze < 0
EXECUTE REJECT;

Note

  • Trigger may fall into an infinite loop when you use INSERT in an action of a trigger where an INSERT event is defined.
  • If a trigger where an UPDATE event is defined runs on a partitioned table, you must be careful because the defined partition can be broken or unintended malfunction may occur. To prevent such situation, CUBRID outputs an error so that the UPDATE causing changes to the running partition is not executed. Trigger may fall into an infinite loop when you use UPDATE in an action of a trigger where an UPDATE event is defined.
Trigger's COMMENT

You can specify a trigger's comment as follows.

CREATE TRIGGER trg_ab BEFORE UPDATE on abc(c) EXECUTE UPDATE cube_ab SET sumc = sumc + 1
COMMENT 'test trigger comment';

You can see a trigger's comment by running the below statement.

SELECT name, comment FROM db_trigger;
SELECT trigger_name, comment FROM db_trig;

Or you can see a trigger's comment with ;sc command which displays a schema in the CSQL interpreter.

$ csql -u dba demodb

csql> ;sc tbl

To change the trigger's comment, refer to ALTER TRIGGER syntax on the below.

ALTER TRIGGER

In the trigger definition, STATUS and PRIORITY options can be changed by using the ALTER statement. If you need to alter other parts of the trigger (event targets or conditional expressions), you must delete and then re-create the trigger.

ALTER TRIGGER trigger_name <trigger_option> ;

<trigger_option> ::=
    STATUS { ACTIVE | INACTIVE } |
    PRIORITY key
  • trigger_name: specifies the name of the trigger to be changed.
  • STATUS { ACTIVE | INACTIVE }: changes the status of the trigger.
  • PRIORITY key: changes the priority.

The following example shows how to create the medal_trig trigger and then change its state to INACTIVE and its priority to 0.7.

CREATE TRIGGER medal_trig
STATUS ACTIVE
BEFORE UPDATE ON participant
IF new.gold < 0 OR new.silver < 0 OR new.bronze < 0
EXECUTE REJECT;

ALTER TRIGGER medal_trig STATUS INACTIVE;
ALTER TRIGGER medal_trig PRIORITY 0.7;

Note

  • Only one trigger_option can be specified in a single ALTER TRIGGER statement.
  • To change a table trigger, you must be the trigger owner or granted the ALTER authorization on the table where the trigger belongs.
  • A user trigger can only be changed by its owner. For details on trigger_option, see the CREATE TRIGGER section. The key specified together with the PRIORITY option must be a non-negative floating point value.
Trigger's COMMENT

You can change a trigger's comment by running ALTER TRIGGER syntax as below.

ALTER TRIGGER trigger_name [trigger_option]
[COMMENT ‘comment_string’];
  • comment_string: specifies a trigger's comment.

If you want to change only trigger's comment, you can omit trigger options (trigger_option).

For trigger_option, see ALTER TRIGGER on the above.

ALTER TRIGGER trg_ab COMMENT 'new trigger comment';
DROP TRIGGER

You can drop a trigger by using the DROP TRIGGER statement.

DROP TRIGGER trigger_name ;
  • trigger_name: specifies the name of the trigger to be dropped.

The following example shows how to drop the medal_trig trigger.

DROP TRIGGER medal_trig;

Note

  • A user trigger (i.e. the trigger event is COMMIT or ROLLBACK) can be seen and dropped only by the owner.
  • Only one trigger can be dropped by a single DROP TRIGGER statement. A table trigger can be dropped by a user who has an ALTER authorization on the table.
RENAME TRIGGER

You can change a trigger name by using the TRIGGER reserved word in the RENAME statement.

RENAME TRIGGER old_trigger_name AS new_trigger_name [ ; ]
  • old_trigger_name: specifies the current name of the trigger.
  • new_trigger_name: specifies the name of the trigger to be modified.
RENAME TRIGGER medal_trigger AS medal_trig;

Note

  • A trigger name must be unique among all trigger names. The name of a trigger can be the same as the table name in the database.
  • To rename a table trigger, you must be the trigger owner or granted the ALTER authorization on the table where the trigger belongs. A user trigger can only be renamed by its user.
Deferred Condition and Action

A deferred trigger action and condition can be executed later or canceled. These triggers include a DEFERRED time option in the event time or action clause. If the DEFERRED option is specified in the event time and the time is omitted before the action, the action is deferred automatically.

Executing Deferred Condition and Action

Executes the deferred condition or action of a trigger immediately.

EXECUTE DEFERRED TRIGGER <trigger_identifier> ;

<trigger_identifier> ::=
    trigger_name |
    ALL TRIGGERS
  • trigger_name: executes the deferred action of the trigger when a trigger name is specified.
  • ALL TRIGGERS: executes all currently deferred actions.
Dropping Deferred Condition and Action

Drops the deferred condition and action of a trigger.

DROP DEFERRED TRIGGER trigger_identifier [ ; ]

<trigger_identifier> ::=
    trigger_name |
    ALL TRIGGERS
  • trigger_name : Cancels the deferred action of the trigger when a trigger name is specified.
  • ALL TRIGGERS : Cancels currently deferred actions.
Granting Trigger Authorization

Trigger authorization is not granted explicitly. Authorization on the table trigger is automatically granted to the user if the authorization is granted on the event target table described in the trigger definition. In other words, triggers that have table targets (INSERT, UPDATE, etc.) are seen by all users. User triggers (COMMIT and ROLLBACK) are seen only by the user who defined the triggers. All authorizations are automatically granted to the trigger owner.

Note

  • To define a table trigger, you must have an ALTER authorization on the table.
  • To define a user trigger, the database must be accessed by a valid user.
Trigger on REPLACE and INSERT ... ON DUPLICATE KEY UPDATE

When the REPLACE statement and INSERT ... ON DUPLICATE KEY UPDATE statements are executed, the trigger is executed in CUBRID, while DELETE, UPDATE, INSERT jobs occur internally. The following table shows the order in which the trigger is executed in CUBRID depending on the event that occurred when the REPLACE or INSERT ... ON DUPLICATE KEY UPDATE statement is executed. Both the REPLACE statement and the INSERT ... ON DUPLICATE KEY UPDATE statement do not execute triggers in the inherited class (table).

Execution Sequence of Triggers in the REPLACE and the INSERT ... ON DUPLICATE KEY UPDATE statements

Event Execution Sequence of Triggers
REPLACE When a record is deleted and new one is inserted BEFORE DELETE > AFTER DELETE > BEFORE INSERT > AFTER INSERT
INSERT ... ON DUPLICATE KEY UPDATE When a record is updated BEFORE UPDATE > AFTER UPDATE
REPLACE, INSERT ... ON DUPLCATE KEY UPDATE Only when a record is inserted BEFORE INSERT > AFTER INSERT

The following example shows that INSERT ... ON DUPLICATE KEY UPDATE and REPLACE are executed in the with_trigger table and records are inserted to the trigger_actions table as a consequence of the execution.

CREATE TABLE with_trigger (id INT UNIQUE);
INSERT INTO with_trigger VALUES (11);

CREATE TABLE trigger_actions (val INT);

CREATE TRIGGER trig_1 BEFORE INSERT ON with_trigger EXECUTE INSERT INTO trigger_actions VALUES (1);
CREATE TRIGGER trig_2 BEFORE UPDATE ON with_trigger EXECUTE INSERT INTO trigger_actions VALUES (2);
CREATE TRIGGER trig_3 BEFORE DELETE ON with_trigger EXECUTE INSERT INTO trigger_actions VALUES (3);

INSERT INTO with_trigger VALUES (11) ON DUPLICATE KEY UPDATE id=22;

SELECT * FROM trigger_actions;
          va
==============
            2
REPLACE INTO with_trigger VALUES (22);

SELECT * FROM trigger_actions;
          va
==============
            2
            3
            1
Trigger Debugging

Once a trigger is defined, it is recommended to check whether it is running as intended. Sometimes the trigger takes more time than expected in processing. This means that it is adding too much overhead to the system or has fallen into a recursive loop. This section explains several ways to debug the trigger.

The following example shows a trigger that was defined to fall into a recursive loop_tgr when it is called. A loop_tgr trigger is somewhat artificial in its purpose; it can be used as an example of debugging trigger.

CREATE TRIGGER loop_tgr
BEFORE UPDATE ON participant(gold)
IF new.gold > 0
EXECUTE UPDATE participant
        SET gold = new.gold - 1
        WHERE nation_code = obj.nation_code AND host_year = obj.host_year;
Viewing Trigger Execution Log

You can view the execution log of the trigger from a terminal by using the SET TRIGGER TRACE statement.

SET TRIGGER TRACE <switch> ;

<switch> ::=
    ON |
    OFF
  • ON: executes TRACE until the switch is set to OFF or the current database session terminates.
  • OFF: stops the TRACE.

The following example shows how to execute the TRACE and the loop_tgr trigger to view the trigger execution logs. To identify the trace for each condition and action executed when the trigger is called, a message is displayed on the terminal. The following message appears 15 times because the loop_tgr trigger is executed until the gold value becomes 0.

SET TRIGGER TRACE ON;
UPDATE participant SET gold = 15 WHERE nation_code = 'KOR' AND host_year = 1988;
TRACE: Evaluating condition for trigger "loop".
TRACE: Executing action for trigger "loop".
Limiting Nested Trigger

With the MAXIMUM DEPTH keyword of the SET TRIGGER statement, you can limit the number of triggers to be initiated at each step. By doing so, you can prevent a recursively called trigger from falling into an infinite loop.

SET TRIGGER [ MAXIMUM ] DEPTH count ;
  • count: A positive integer value that specifies the number of times that a trigger can recursively start another trigger or itself. If the number of triggers reaches the maximum depth, the database request stops(aborts) and the transaction is marked as invalid. The specified DEPTH applies to all other triggers except the current session. The maximum value is 32.

The following example shows how to configure the maximum number of times of recursive trigger calling to 10. This applies to all triggers that start subsequently. In this example, the gold column value is updated to 15, so the trigger is called 16 times in total. This exceeds the currently set maximum depth and the following error message occurs.

SET TRIGGER MAXIMUM DEPTH 10;
UPDATE participant SET gold = 15 WHERE nation_code = 'KOR' AND host_year = 1988;
ERROR: Maximum trigger depth 10 exceeded at trigger "loop_tgr".
Trigger Example

This section covers trigger definitions in the demo database. The triggers created in the demodb database are not complex, but use most of the features available in CUBRID. If you want to maintain the original state of the demodb database when testing such triggers, you must perform a rollback after changes are made to the data.

Triggers created by the user in the own database can be as powerful as applications created by the user.

The following trigger created in the participant table rejects an update to the medal column (gold, silver, bronze) if a given value is smaller than 0. The evaluation time must be BEFORE because a correlation name new is used in the trigger condition. Although not described, the action time of this trigger is also BEFORE.

CREATE TRIGGER medal_trigger
BEFORE UPDATE ON participant
IF new.gold < 0 OR new.silver < 0 OR new.bronze < 0
EXECUTE REJECT;

The trigger medal_trigger starts when the number of gold (gold) medals of the country whose nation code is 'BLA' is updated. Since the trigger created does not allow negative numbers, the example below will not be updated.

UPDATE participant
SET gold = -10
WHERE nation_code = 'BLA';

The following trigger has the same condition as the one above except that STATUS ACTIVE is added. If the STATUS statement is omitted, the default value is ACTIVE. You can change STATUS to INACTIVE by using the ALTER TRIGGER statement.

You can specify whether or not to execute the trigger depending on the STATUS value.

CREATE TRIGGER medal_trig
STATUS ACTIVE
BEFORE UPDATE ON participant
IF new.gold < 0 OR new.silver < 0 OR new.bronze < 0
EXECUTE REJECT;

ALTER TRIGGER medal_trig
STATUS INACTIVE;

The following trigger shows how integrity constraint is enforced when a transaction is committed. This example is different from the previous ones, in that one trigger can have specific conditions for multiple tables.

CREATE TRIGGER check_null_first
BEFORE COMMIT
IF 0 < (SELECT count(*) FROM athlete WHERE gender IS NULL)
OR 0 < (SELECT count(*) FROM game WHERE nation_code IS NULL)
EXECUTE REJECT;

The following trigger delays the update integrity constraint check for the record table until the transaction is committed. Since the DEFERRED keyword is given as the event time, the trigger is not executed at the time.

CREATE TRIGGER deferred_check_on_record
DEFERRED UPDATE ON record
IF obj.score = '100'
EXECUTE INVALIDATE TRANSACTION;

Once completed, the update in the record table can be confirmed at the last point (commit or rollback) of the current transaction. The correlation name old cannot be used in the conditional clause of the trigger where DEFERRED UPDATE is used. Therefore, you cannot create a trigger as the following.

CREATE TABLE foo (n int);
CREATE TRIGGER foo_trigger
    DEFERRED UPDATE ON foo
    IF old.n = 100
    EXECUTE PRINT 'foo_trigger';

If you try to create a trigger as shown above, an error message is displayed and the trigger fails.

ERROR: Error compiling condition for 'foo_trigger' : old.n is not defined.

The correlation name old can be used only with AFTER.

Java Stored Function/Procedure

Stored functions and procedures are used to implement complicated program logic that is not possible with SQL. They allow users to manipulate data more easily. Stored functions/procedures are blocks of code that have a flow of commands for data manipulation and are easy to manipulate and administer.

CUBRID supports to develop stored functions and procedures in Java. Java stored functions/procedures are executed on the JVM (Java Virtual Machine) hosted by CUBRID.

You can call Java stored functions/procedures from SQL statements or from Java applications using JDBC.

The advantages of using Java stored functions/procedures are as follows:

  • Productivity and usability: Java stored functions/procedures, once created, can be reused anytime. They can be called from SQL statements or from Java applications using JDBC.
  • Excellent interoperability and portability: Java stored functions/procedures use the Java Virtual Machine. Therefore, they can be used on any system where the Java Virtual Machine is available.

Note

  • The other languages except Java do not support stored function/procedure. In CUBRID, only Java can implement stored function/procedure.
Environment Configuration for Java Stored Function/Procedure

To use Java-stored functions/procedures in CUBRID, you must have JRE (Java Runtime Environment) 1.6 or better installed in the environment where the CUBRID server is installed. You can download JRE from the Developer Resources for Java Technology (http://java.sun.com).

If the java_stored_procedure parameter in the CUBRID configuration file (cubrid.conf) is set to yes, CUBRID 64-bit needs a 64-bit Java Runtime Environment, and CUBRID 32-bit needs a 32-bit Java Runtime Environment. For example, when you run CUBRID 64-bit in the system in which a 32-bit JAVA Runtime Environment is installed, the following error may occur.

% cubrid server start demodb

This may take a long time depending on the amount of recovery works to do.
WARNING: Java VM library is not found : /usr/java/jdk1.6.0_15/jre/lib/amd64/server/libjvm.so: cannot open shared object file: No such file or directory.
Consequently, calling java stored procedure is not allowed

Execute the following command to check the JRE version if you have it already installed in the system.

% java -version Java(TM) SE Runtime Environment (build 1.6.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 10.0-b19, mixed mode)
Windows Environment

For Windows, CUBRID loads the jvm.dll file to run the Java Virtual Machine. CUBRID first locates the jvm.dll file from the PATH environment variable and then loads it. If it cannot find the file, it uses the Java runtime information registered in the system registry.

You can configure the JAVA_HOME environment variable and add the directory in which the Java executable file is located to Path, by executing the command as follows: For information on configuring environment variables using GUI, see Installing and Configuring JDBC.

  • An example of installing 64 Bit JDK 1.6 and configuring the environment variables

    % set JAVA_HOME=C:\jdk1.6.0
    % set PATH=%PATH%;%JAVA_HOME%\jre\bin\server
    
  • An example of installing 32 Bit JDK 1.6 and configuring the environment variables

    % set JAVA_HOME=C:\jdk1.6.0
    % set PATH=%PATH%;%JAVA_HOME%\jre\bin\client
    

To use other vendor's implementation instead of Sun's Java Virtual Machine, add the path of the jvm.dll file to the PATH variable during the installation.

Linux/UNIX Environment

For Linux/UNIX environment, CUBRID loads the libjvm.so file to run the Java Virtual Machine. CUBRID first locates the libjvm.so file from the LD_LIBRARY_PATH environment variable and then loads it. If it cannot find the file, it uses the JAVA_HOME environment variable. For Linux, glibc 2.3.4 or later versions are supported. The following example shows how to configure the Linux environment variable (e.g., .profile, .cshrc, .bashrc, .bash_profile, etc.).

  • An example of installing 64 Bit JDK 1.6 and configuring the environment variables in a bash shell

    % JAVA_HOME=/usr/java/jdk1.6.0_10
    % LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/amd64:$JAVA_HOME/jre/lib/amd64/server:$LD_LIBRARY_PATH
    % export JAVA_HOME
    % export LD_LIBRARY_PATH
    
  • An example of installing 32 Bit JDK 1.6 and configuring the environment variables in a bash shell

    % JAVA_HOME=/usr/java/jdk1.6.0_10
    % LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/i386/:$JAVA_HOME/jre/lib/i386/client:$LD_LIBRARY_PATH
    % export JAVA_HOME
    % export LD_LIBRARY_PATH
    
  • An example of installing 64 Bit JDK 1.6 and configuring the environment variables in a csh

    % setenv JAVA_HOME /usr/java/jdk1.6.0_10
    % setenv LD_LIBRARY_PATH $JAVA_HOME/jre/lib/amd64:$JAVA_HOME/jre/lib/amd64/server:$LD_LIBRARY_PATH
    % set path=($path $JAVA_HOME/bin .)
    
  • An example of installing 32 Bit JDK 1.6 and configuring the environment variables in a csh shell

    % setenv JAVA_HOME /usr/java/jdk1.6.0_10
    % setenv LD_LIBRARY_PATH $JAVA_HOME/jre/lib/i386:$JAVA_HOME/jre/lib/i386/client:$LD_LIBRARY_PATH
    % set path=($path $JAVA_HOME/bin .)
    

To use other vendor's implementation instead of Sun's Java Virtual Machine, add the path of the JVM (libjvm.so) to the library path during the installation. The path of the libjvm.so file can be different depending on the platform. For example, the path is the $JAVA_HOME/jre/lib/sparc directory in a SUN Sparc machine.

How to Write Java Stored Function/Procedure

The following is an example to write a Java stored function/procedure.

Check the cubrid.conf file

By default, the java_stored_procedure is set to no in the cubrid.conf file. To use a Java stored function/procedure, this value must be changed to yes. For details on this value, see Other Parameters in Database Server Configuration.

Write and compile the Java source code

Compile the SpCubrid.java file as follows:

public class SpCubrid{
    public static String HelloCubrid() {
        return "Hello, Cubrid !!";
    }

    public static int SpInt(int i) {
        return i + 1;
    }

    public static void outTest(String[] o) {
        o[0] = "Hello, CUBRID";
    }
}
javac SpCubrid.java

Here, the Java class method must be public static.

Load the compiled Java class into CUBRID

Load the compiled Java class into CUBRID.

% loadjava demodb SpCubrid.class
Publish the loaded Java class

Create a CUBRID stored function and publish the Java class as shown below.

CREATE FUNCTION hello() RETURN STRING
AS LANGUAGE JAVA
NAME 'SpCubrid.HelloCubrid() return java.lang.String';

Or with OR REPLACE syntax, you can replace the current stored function/procedure or create the new stored function/procedure.

CREATE OR REPLACE FUNCTION hello() RETURN STRING
AS LANGUAGE JAVA
NAME 'SpCubrid.HelloCubrid() return java.lang.String';
Call the Java stored function/procedure

Call the published Java stored function as follows:

CALL hello() INTO :Hello;
  Result
======================
'Hello, Cubrid !!'
Using Server-side Internal JDBC Driver

To access the database from a Java stored function/procedure, you must use the server-side JDBC driver. As Java stored functions/procedures are executed within the database, there is no need to make the connection to the server-side JDBC driver again. To acquire a connection to the database using the server-side JDBC driver, you can either use "jdbc:default:connection:" as the URL for JDBC connection, or call the getDefaultConnection () method of the cubrid.jdbc.driver.CUBRIDDriver class.

Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
Connection conn = DriverManager.getConnection("jdbc:default:connection:");

or

cubrid.jdbc.driver.CUBRIDDriver.getDefaultConnection();

If you connect to the database using the JDBC driver as shown above, the transaction in the Java stored function/procedure is ignored. That is, database operations executed in the Java stored function/procedure belong to the transaction that called the Java stored function/procedure. In the following example, conn.commit() method of the Athlete class is ignored.

import java.sql.*;

public class Athlete{
    public static void Athlete(String name, String gender, String nation_code, String event) throws SQLException{
        String sql="INSERT INTO ATHLETE(NAME, GENDER, NATION_CODE, EVENT)" + "VALUES (?, ?, ?, ?)";

        try{
            Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
            Connection conn = DriverManager.getConnection("jdbc:default:connection:");
            PreparedStatement pstmt = conn.prepareStatement(sql);

            pstmt.setString(1, name);
            pstmt.setString(2, gender);
            pstmt.setString(3, nation_code);
            pstmt.setString(4, event);;
            pstmt.executeUpdate();

            pstmt.close();
            conn.commit();
            conn.close();
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
}
Connecting to Other Database

You can connect to another outside database instead of the currently connected one even when the server-side JDBC driver is being used. Acquiring a connection to an outside database is not different from a generic JDBC connection. For details, see JDBC API.

If you connect to other databases, the connection to the CUBRID database does not terminate automatically even when the execution of the Java method ends. Therefore, the connection must be explicitly closed so that the result of transaction operations such as COMMIT or ROLLBACK will be reflected in the database. That is, a separate transaction will be performed because the database that called the Java stored function/procedure is different from the one where the actual connection is made.

import java.sql.*;

public class SelectData {
    public static void SearchSubway(String[] args) throws Exception {

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
            conn = DriverManager.getConnection("jdbc:CUBRID:localhost:33000:demodb:::","","");

            String sql = "select line_id, line from line";
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);

            while(rs.next()) {
                int host_year = rs.getString("host_year");
                String host_nation = rs.getString("host_nation");

                System.out.println("Host Year ==> " + host_year);
                System.out.println(" Host Nation==> " + host_nation);
                System.out.println("\n=========\n");
            }

            rs.close();
            stmt.close();
            conn.close();
        } catch ( SQLException e ) {
            System.err.println(e.getMessage());
        } catch ( Exception e ) {
            System.err.println(e.getMessage());
        } finally {
            if ( conn != null ) conn.close();
        }
    }
}

When the Java stored function/procedure being executed should run only on JVM located in the database server, you can check where it is running by calling System.getProperty ("cubrid.server.version") from the Java program source. The result value is the database version if it is called from the database; otherwise, it is NULL.

loadjava Utility

To load a compiled Java or JAR (Java Archive) file into CUBRID, use the loadjava utility. If you load a Java *.class or *.jar file using the loadjava utility, the file is moved to the specified database path.

loadjava [option] database-name java-class-file
  • database-name: The name of the database where the Java file is to be loaded.
  • java-class-file: The name of the Java class or jar file to be loaded.
  • [option]
    • -y: Automatically overwrites a class file with the same name, if any. The default value is no. If you load the file without specifying the -y option, you will be prompted to ask if you want to overwrite the class file with the same name (if any).
Loaded Java Class Publish

In CUBRID, it is required to publish Java classes to call Java methods from SQL statements or Java applications. You must publish Java classes by using call specifications because it is not known how a function in a class will be called by SQL statements or Java applications when Java classes are loaded.

Call Specifications

To use a Java stored function/procedure in CUBRID, you must write call specifications. With call specifications, Java function names, parameter types, return values and their types can be accessed by SQL statements or Java applications. To write call specifications, use CREATE FUNCTION or CREATE PROCEDURE statement. Java stored function/procedure names are not case sensitive. The maximum number of characters a Java stored function/procedure can have is 254 bytes. The maximum number of parameters a Java stored function/procedure can have is 64.

If there is a return value, it is a function; if not, it is a procedure.

CREATE [OR REPLACE] FUNCTION function_name[(param [COMMENT 'param_comment_string'] [, param [COMMENT 'param_comment_string']]...)] RETURN sql_type
{IS | AS} LANGUAGE JAVA
NAME 'method_fullname (java_type_fullname [,java_type_fullname]...) [return java_type_fullname]'
COMMENT 'sp_comment';

CREATE [OR REPLACE] PROCEDURE procedure_name[(param [COMMENT 'param_comment_string'][, param [COMMENT 'param_comment_string']] ...)]
{IS | AS} LANGUAGE JAVA
NAME 'method_fullname (java_type_fullname [,java_type_fullname]...) [return java_type_fullname]';
COMMENT 'sp_comment_string';

parameter_name [IN|OUT|IN OUT|INOUT] sql_type
   (default IN)
  • param_comment_string: specifies the parameter's comment string.
  • sp_comment_string: specifies the Java stored function/procedure's comment string.

If the parameter of a Java stored function/procedure is set to OUT, it will be passed as a one-dimensional array whose length is 1. Therefore, a Java method must store its value to pass in the first space of the array.

CREATE FUNCTION Hello() RETURN VARCHAR
AS LANGUAGE JAVA
NAME 'SpCubrid.HelloCubrid() return java.lang.String';

CREATE FUNCTION Sp_int(i int) RETURN int
AS LANGUAGE JAVA
NAME 'SpCubrid.SpInt(int) return int';

CREATE PROCEDURE Athlete_Add(name varchar,gender varchar, nation_code varchar, event varchar)
AS LANGUAGE JAVA
NAME 'Athlete.Athlete(java.lang.String, java.lang.String, java.lang.String, java.lang.String)';

CREATE PROCEDURE test_out(x OUT STRING)
AS LANGUAGE JAVA
NAME 'SpCubrid.outTest(java.lang.String[] o)';

When a Java stored function/procedure is published, it is not checked whether the return definition of the Java stored function/procedure coincides with the one in the declaration of the Java file. Therefore, the Java stored function/procedure follows the sql_type return definition provided at the time of registration. The return definition in the declaration is significant only as user-defined information.

Data Type Mapping

In call specifications, the data types SQL must correspond to the data types of Java parameter and return value. The following table shows SQL/Java data types allowed in CUBRID.

Data Type Mapping

SQL Type Java Type
CHAR, VARCHAR java.lang.String, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.lang.Byte, java.lang.Short, java.lang.Integer, java.lang.Long, java.lang.Float, java.lang.Double, java.math.BigDecimal, byte, short, int, long, float, double
NUMERIC, SHORT, INT, FLOAT, DOUBLE, CURRENCY java.lang.Byte, java.lang.Short, java.lang.Integer, java.lang.Long, java.lang.Float, java.lang.Double, java.math.BigDecimal, java.lang.String, byte, short, int, long, float, double
DATE, TIME, TIMESTAMP java.sql.Date, java.sql.Time, java.sql.Timestamp, java.lang.String
SET, MULTISET, SEQUENCE java.lang.Object[], java primitive type array, java.lang.Integer[] ...
OBJECT cubrid.sql.CUBRIDOID
CURSOR cubrid.jdbc.driver.CUBRIDResultSet
Checking the Published Java Stored Function/Procedure Information

You can check the information on the published Java stored function/procedure The db_stored_procedure system virtual table provides virtual table and the db_stored_procedure_args system virtual table. The db_stored_procedure system virtual table provides the information on stored names and types, return types, number of parameters, Java class specifications, and the owner. The db_stored_procedure_args system virtual table provides the information on parameters used in the stored function/procedure.

SELECT * FROM db_stored_procedure;
sp_name     sp_type   return_type    arg_count
sp_name               sp_type               return_type             arg_count  lang target                owner
================================================================================
'hello'               'FUNCTION'            'STRING'                        0  'JAVA''SpCubrid.HelloCubrid() return java.lang.String'  'DBA'

'sp_int'              'FUNCTION'            'INTEGER'                       1  'JAVA''SpCubrid.SpInt(int) return int'  'DBA'

'athlete_add'         'PROCEDURE'           'void'                          4  'JAVA''Athlete.Athlete(java.lang.String, java.lang.String, java.lang.String, java.lang.String)'  'DBA'
SELECT * FROM db_stored_procedure_args;
sp_name   index_of  arg_name  data_type      mode
=================================================
 'sp_int'                        0  'i'                   'INTEGER'             'IN'
 'athlete_add'                   0  'name'                'STRING'              'IN'
 'athlete_add'                   1  'gender'              'STRING'              'IN'
 'athlete_add'                   2  'nation_code'         'STRING'              'IN'
 'athlete_add'                   3  'event'               'STRING'              'IN'
Deleting Java Stored Functions/Procedures

You can delete published Java stored functions/procedures in CUBRID. To delete a Java function/procedure, use the DROP FUNCTION function_name or DROP PROCEDURE procedure_name statement. Also, you can delete multiple Java stored functions/procedures at a time with several function_names or procedure_names separated by a comma (,).

A Java stored function/procedure can be deleted only by the user who published it or by DBA members. For example, if a PUBLIC user published the 'sp_int' Java stored function, only the PUBLIC or DBA members can delete it.

DROP FUNCTION hello, sp_int;
DROP PROCEDURE Athlete_Add;
COMMENT of Java Stored Function/Procedure

A comment of stored function/procedure can be written at the end of the statement as follows.

CREATE FUNCTION Hello() RETURN VARCHAR
AS LANGUAGE JAVA
NAME 'SpCubrid.HelloCubrid() return java.lang.String'
COMMENT 'function comment';

A comment of a paramenter can be written as follows.

CREATE OR REPLACE FUNCTION test(i in number COMMENT 'arg i')
RETURN NUMBER AS LANGUAGE JAVA NAME 'SpTest.testInt(int) return int' COMMENT 'function test';

A comment of a stored function/procedure can be shown by running the following syntax.

SELECT sp_name, comment FROM db_stored_procedure;

A comment for a parameter of a function can be shown by running the following syntax.

SELECT sp_name, arg_name, comment FROM db_stored_procedure_args;
Java Stored Function/Procedure Call
Using CALL Statement

You can call the Java stored functions/procedures by using a CALL statement, from SQL statements or Java applications. The following shows how to call them by using the CALL statement. The name of the Java stored function/procedure called from a CALL statement is not case sensitive.

CALL {procedure_name ([param[, param]...]) | function_name ([param[, param]...]) INTO :host_variable
param {literal | :host_variable}
CALL Hello() INTO :HELLO;
CALL Sp_int(3) INTO :i;
CALL phone_info('Tom','016-111-1111');

In CUBRID, the Java functions/procedures are called by using the same CALL statement. Therefore, the CALL statement is processed as follows:

  • It is processed as a method if there is a target class in the CALL statement.
  • If there is no target class in the CALL statement, it is checked whether a Java stored function/procedure is executed or not; a Java stored function/procedure will be executed if one exists.
  • If no Java stored function/procedure exists in step 2 above, it is checked whether a method is executed or not; a method will be executed if one with the same name exists.

The following error occurs if you call a Java stored function/procedure that does not exist.

CALL deposit();
ERROR: Stored procedure/function 'deposit' does not exist.
CALL deposit('Tom', 3000000);
ERROR: Methods require an object as their target.

If there is no argument in the CALL statement, a message "ERROR: Stored procedure/function 'deposit' does not exist." appears because it can be distinguished from a method. However, if there is an argument in the CALL statement, a message "ERROR: Methods require an object as their target." appears because it cannot be distinguished from a method.

If the CALL statement is nested within another CALL statement calling a Java stored function/procedure, or if a subquery is used in calling the Java function/procedure, the CALL statement is not executed.

CALL phone_info('Tom', CALL sp_int(999));
CALL phone_info((SELECT * FROM Phone WHERE id='Tom'));

If an exception occurs during the execution of a Java stored function/procedure, the exception is logged and stored in the dbname_java.log file. To display the exception on the screen, change a handler value of the $CUBRID/java/logging.properties file to " java.lang.logging.ConsoleHandler." Then, the exception details are displayed on the screen.

Calling from SQL Statement

You can call a Java stored function from a SQL statement as shown below.

SELECT Hello() FROM db_root;
SELECT sp_int(99) FROM db_root;

You can use a host variable for the IN/OUT data type when you call a Java stored function/procedure as follows:

SELECT 'Hi' INTO :out_data FROM db_root;
CALL test_out(:out_data);
SELECT :out_data FROM db_root;

The first clause calls a Java stored procedure in out mode by using a parameter variable; the second is a query clause retrieving the assigned host variable out_data.

Calling from Java Application

To call a Java stored function/procedure from a Java application, use a CallableStatement object.

Create a phone class in the CUBRID database.

CREATE TABLE phone(
     name VARCHAR(20),
     phoneno VARCHAR(20)
);

Compile the following PhoneNumber.java file, load the Java class file into CUBRID, and publish it.

import java.sql.*;
import java.io.*;

public class PhoneNumber{
    public static void Phone(String name, String phoneno) throws Exception{
        String sql="INSERT INTO PHONE(NAME, PHONENO)"+ "VALUES (?, ?)";
        try{
            Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
            Connection conn = DriverManager.getConnection("jdbc:default:connection:");
            PreparedStatement pstmt = conn.prepareStatement(sql);

            pstmt.setString(1, name);
            pstmt.setString(2, phoneno);
            pstmt.executeUpdate();

            pstmt.close();
            conn.commit();
            conn.close();
        } catch (SQLException e) {
            System.err.println(e.getMessage());
        }
    }
}
create PROCEDURE phone_info(name varchar, phoneno varchar) as language java
name 'PhoneNumber.Phone(java.lang.String, java.lang.String)';

Create and run the following Java application.

import java.sql.*;

public class StoredJDBC{
    public static void main(){
        Connection conn = null;
        Statement stmt= null;
        int result;
        int i;

        try{
            Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
            conn = DriverManager.getConnection("jdbc:CUBRID:localhost:33000:demodb:::","","");

            CallableStatement cs;
            cs = conn.prepareCall("CALL PHONE_INFO(?, ?)");

            cs.setString(1, "Jane");
            cs.setString(2, "010-1111-1111");
            cs.executeUpdate();

            conn.commit();
            cs.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Retrieve the phone class after executing the program above; the following result would be displayed.

SELECT * FROM phone;
name                  phoneno
============================================
    'Jane'                '010-111-1111'
Caution
Returning Value of Java Stored Function/Procedure and Precision Type on IN/OUT

To limit the return value of Java stored function/procedure and precision type on IN/OUT, CUBRID processes as follows:

  • Checks the sql_type of the Java stored function/procedure.
  • Passes the value returned by Java to the database with only the type converted if necessary, ignoring the number of digits defined during creating the Java stored function/procedure. In principle, the user manipulates directly the data which is passed to the database.

Take a look at the following typestring () Java stored function.

public class JavaSP1{
    public static String typestring(){
        String temp = " ";
        for(int i=0 i< 1 i++)
            temp = temp + "1234567890";
        return temp;
    }
}
CREATE FUNCTION typestring() RETURN CHAR(5) AS LANGUAGE JAVA
NAME 'JavaSP1.typestring() return java.lang.String';

CALL typestring();
  Result
======================
  ' 1234567890'
Returning java.sql.ResultSet in Java Stored Procedure

In CUBRID, you must use CURSOR as the data type when you declare a Java stored function/procedure that returns a java.sql.ResultSet.

CREATE FUNCTION rset() RETURN CURSOR AS LANGUAGE JAVA
NAME 'JavaSP2.TResultSet() return java.sql.ResultSet'

Before the Java file returns java.sql.ResultSet, it is required to cast to the CUBRIDResultSet class and then to call the setReturnable () method.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import cubrid.jdbc.driver.CUBRIDConnection;
import cubrid.jdbc.driver.CUBRIDResultSet;

public class JavaSP2 {
    public static ResultSet TResultSet(){
        try {
            Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
            Connection conn = DriverManager.getConnection("jdbc:default:connection:");
            ((CUBRIDConnection)conn).setCharset("euc_kr");

            String sql = "select * from station";
            Statement stmt=conn.createStatement();
            ResultSet rs = stmt.executeQuery(sql);
            ((CUBRIDResultSet)rs).setReturnable();

            return rs;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

In the calling block, you must set the OUT argument with Types.JAVA_OBJECT, get the argument to the getObject () function, and then cast it to the java.sql.ResultSet type before you use it. In addition, the java.sql.ResultSet is only available to use in CallableStatement of JDBC.

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Types;

public class TestResultSet{
    public static void main(String[] args) {
        Connection conn = null;

        try {
            Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
            conn = DriverManager.getConnection("jdbc:CUBRID:localhost:31001:tdemodb:::","","");

            CallableStatement cstmt = conn.prepareCall("?=CALL rset()");
            cstmt.registerOutParameter(1, Types.JAVA_OBJECT);
            cstmt.execute();
            ResultSet rs = (ResultSet) cstmt.getObject(1);

            while(rs.next()) {
                System.out.println(rs.getString(1));
            }

            rs.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

You cannot use the ResultSet as an input argument. If you pass it to an IN argument, an error occurs. An error also occurs when calling a function that returns ResultSet in a non-Java environment.

IN/OUT of Set Type in Java Stored Function/Procedure

If the set type of the Java stored function/procedure in CUBRID is IN OUT, the value of the argument changed in Java must be applied to IN OUT. When the set type is passed to the OUT argument, it must be passed as a two-dimensional array.

CREATE PROCEDURE setoid(x in out set, z object) AS LANGUAGE JAVA
NAME 'SetOIDTest.SetOID(cubrid.sql.CUBRIDOID[][], cubrid.sql.CUBRIDOID';
public static void SetOID(cubrid.sql.CUBRID[][] set, cubrid.sql.CUBRIDOID aoid){
    Connection conn=null;
    Statement stmt=null;
    String ret="";
    Vector v = new Vector();

    cubrid.sql.CUBRIDOID[] set1 = set[0];

    try {
        if(set1!=null) {
            int len = set1.length;
            int i = 0;

            for (i=0 i< len i++)
                v.add(set1[i]);
        }

        v.add(aoid);
        set[0]=(cubrid.sql.CUBRIDOID[]) v.toArray(new cubrid.sql.CUBRIDOID[]{});

    } catch(Exception e) {
        e.printStackTrace();
        System.err.pirntln("SQLException:"+e.getMessage());
    }
}
Using OID in Java Stored Function/Procedure

In case of using the OID type value for IN/OUT in CUBRID, use the value passed from the server.

CREATE PROCEDURE tOID(i inout object, q string) AS LANGUAGE JAVA
NAME 'OIDtest.tOID(cubrid.sql.CUBRIDOID[], java.lang.String)';
public static void tOID(CUBRIDOID[] oid, String query)
{
    Connection conn=null;
    Statement stmt=null;
    String ret="";

    try {
        Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
        conn=DriverManager.getConnection("jdbc:default:connection:");

        conn.setAutoCommit(false);
        stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        System.out.println("query:"+ query);

        while(rs.next()) {
            oid[0]=(CUBRIDOID)rs.getObject(1);
            System.out.println("oid:"+oid[0].getTableName());
        }

        stmt.close();
        conn.close();

    } catch (SQLException e) {
        e.printStackTrace();
        System.err.println("SQLException:"+e.getMessage());
    } catch (Exception e) {
        e.printStackTrace();
        system.err.println("Exception:"+ e.getMessage());
    }
}

Method

The methods are written in C with built-in functions of CUBRID database system, and are called by the CALL statement. A method program is loaded and linked with the application currently running by the dynamic loader when the method is called. The return value created as a result of the method execution is passed to the caller.

Method Type

The CSQL language supports the following two types of methods: class and instance methods.

  • The class method is a method called by a class object. It is usually used to create a new class instance or to initialize it. It is also used to access or update class attributes.
  • The instance method is a method called by a class instance. It is used more often than the class method because most operations are executed in the instance. For example, an instance method can be written to calculate or update the instance attribute. This method can be called from any instance of the class in which the method is defined or of the sub class that inherits the method.

The method inheritance rules are similar to those of the attribute inheritance. The sub class inherits classes and instance methods from the super class. The sub class can follow the class or instance method definition from the super class.

The rules for resolving method name conflicts are same as those for attribute name conflicts. For details about attribute/method inheritance conflicts, see Class Conflict Resolution.

CALL Statement

The CALL statement is used to call a method defined in the database. Both class and instance methods can be called by the CALL statement. If you want to see example of using the CALL statement, see User Authorization Management METHOD.

CALL <method_call> ;

<method_call> ::=
    method_name ([<arg_value> [{, <arg_value> } ...]]) ON <call_target> [<to_variable>] |
    method_name (<call_target> [, <arg_value> [{, <arg_value>} ...]] ) [<to_variable>]

    <arg_value> ::=
        any CSQL expression

    <call_target> ::=
        an object-valued expression

    <to_variable> ::=
        INTO variable |
        TO variable
  • The method_name is either the method name defined in the table or the system-defined method name. A method requires one or more parameters. If there is no parameter for the method, a set of blank parentheses must be used.
  • <call_target> can use an object-valued expression that contains a class name, a variable, another method call (which returns an object). To call a class method for a class object, you must place the CLASS keyword before the <call_target>. In this case, the table name must be the name of the class where the table method is defined. To call a record method, you must specify the expression representing the record object. You can optionally store the value returned by the table or record method in the <to_variable>. This returned variable value can be used in the CALL statement just like the <call_target> or <arg_value> parameter.
  • Calling nested methods is possible when other method_call is the <call_target> of the method or given as one of the <arg_value> parameters.

Class Inheritance

To explain the concept of inheritance, a table is expressed as a class, a column is expressed as an attribute, and a type is expressed as a domain.

Classes in CUBRID database can have class hierarchy. Attributes and methods can be inherited through such hierarchy. As shown in the previous section, you can create a Manager class by inheriting attributes from an Employee class. The Manager class is called the sub class of the Employee class, and the Employee class is called the super class of the Manager class. Inheritance can simplify class creation by reusing the existing class hierarchy.

CUBRID allows multiple inheritances, which means that a class can inherit attributes and methods from more than one super class. However, inheritance can cause conflicts when an attribute or method of the super class is added or deleted.

Such conflict occurs in multiple inheritance if there are attributes or methods with the same name in different super classes. For example, if it is likely that a class inherits attributes of the same name and type from more than one super class, you must specify the attributes to be inherited. In such a case, if the inherited super class is deleted, a new attribute of the same name and type must be inherited from another super class. In most cases, the database system resolves such problems automatically. However, if you don't like the way that the system resolves a problem, you can resolve it manually by using the INHERIT clause.

When attributes are inherited from more than one super class, it is possible that their names are to be the same, while their domains are different. For example, two super classes may have the same attribute, whose domain is a class. In this case, a sub class automatically inherits attributes with more specialized (a lower in the class hierarchy) domains. If such conflict occurs between basic data types (e.g. STRING or INTEGER) provided by the system, inheritance fails.

Conflicts during inheritance and their resolutions will be covered in the Resolving Class Conflicts section.

Note

The following cautions must be observed during inheritance:

  • The class name must be unique in the database. An error occurs if you create a class that inherits another class that does not exist.
  • The name of a method/attribute must be unique within a class. The name cannot contain spaces, and cannot be a reserved keyword of CUBRID. Alphabets as well as '_', '#', '%' are allowed in the class name, but the first character cannot be '_'. Class names are not case-sensitive. A class name will be stored in the system after being converted to lowercase characters.

Note

A super class name can begin with the user name so that the owner of the class can be easily identified.

Class Attribute and Method

You can create class attributes to store the aggregate property of all instances in the class. When you define a CLASS attribute or method, you must precede the attribute or method name with the keyword CLASS. Because a class attribute is associated with the class itself, not with an instances of the class, it has only one value. For example, a class attribute can be used to store the average value determined by a class method or the timestamp when the class was created. A class method is executed in the class object itself. It can be used to calculate the aggregate value for the instances of the class.

When a sub class inherits a super class, each class has a separate storage space for class attributes, so that two classes may have different values of class attribute. Therefore, the sub class does not change even when the attributes of the super class are changed.

The name of a class attribute can be the same as that of an instance attribute of the same class. Likewise, the name of a class method can be the same as that of an instance method of the same class.

Order Rule for Inheritance

The following rules apply to inheritance. The term class is generally used to describe the inheritance relationship between classes and virtual classes in the database.

  • For an object without a super class, attributes are defined in the same order as in the CREATE statement (an ANSI standard).
  • If there is one super class, locally created attributes are placed after the super class attributes. The order of the attributes inherited from the super class follows the one defined during the super class definition. For multiple inheritance, the order of the super class attributes is determined by the order of the super classes specified during the class definition.
  • If more than one super class inherits the same class, the attribute that exists in both super classes is inherited to the sub class only once. At this time, if a conflict occurs, the attribute of the first super class is inherited.
  • If a name conflict occurs in more than one super class, you can inherit only the ones you want from the super class attributes by using the INHERIT clause in order to resolve the conflict.
  • If the name of the super class attribute is changed by the alias option of the INHERIT clause, its position is maintained.
INHERIT Clause

When a class is created as a sub class, the class inherits all attributes and methods of the super class. A name conflict that occurs during inheritance can be handled by either a system or a user. To resolve the name conflict directly, add the INHERIT clause to the CREATE CLASS statement.

CREATE CLASS
.
.
.
INHERIT resolution [ {, resolution }_ ]

resolution:
{ column_name | method_name } OF superclass_name [ AS alias ]

In the INHERIT clause, specify the name of the attribute or method of the super class to inherit. With the ALIAS clause, you can resolve a name conflict that occurs in multiple inheritance statements by inheriting a new name.

ADD SUPERCLASS Clause

To extend class inheritance, add a super class to a class. A relationship between two classes is created when a super class is added to an existing class. Adding a super class does not mean adding a new class.

ALTER CLASS
.
.
.
ADD SUPERCLASS [ user_name.]class_name [ { , [ user_name.]class_name }_ ]
[ INHERIT resolution [ {, resolution }_ ] ] [ ; ]
resolution:
{ column_name | method_name } OF superclass_name [ AS alias ]

For the first class_name, specify the name of the class where a super class is to be added. Attributes and methods of the super class can be inherited by using the syntax above.

Name conflicts can occur when adding a new super class. If a name conflict cannot be resolved by the database system, attributes or methods to inherit from the super class can be specified by using the INHERIT clause. You can use aliases to inherit all attributes or methods that cause the conflict. For details on super class name conflicts, see Class Conflict Resolution.

The following example shows how to create the female_event class by inheriting the event class included in demodb.

CREATE CLASS female_event UNDER event;
DROP SUPERCLASS Clause

Deleting a super class from a class means removing the relationship between two classes. If a super class is deleted from a class, it changes inheritance relationship of the classes as well as of all their sub classes.

ALTER CLASS
.
.
.
DROP SUPERCLASS class_name [ { , class_name }_ ]
[ INHERIT resolution [ {, resolution }_ ] ] [ ; ]

resolution:
{ column_name | method_name } OF superclass_name [ AS alias ]

For the first class_name, specify the name of the class to be modified. For the second class_name, specify the name of the super class to be deleted. If a name conflict occurs after deleting a super class, see the Class Conflict Resolution section for the resolution.

The following example shows how to inherit the female_event class from the event class.

CREATE CLASS female_event UNDER event

The following example shows how to delete the super class event from the f emale_event class. Attributes that the female_event class inherited from the even class no longer exist.

ALTER CLASS female_event DROP SUPERCLASS event;
Class Conflict Resolution

If you modify the schema of the database, conflicts can occur between attributes or methods of inheritance classes. Most conflicts are resolved automatically by CUBRID otherwise, you must resolve the conflict manually. Therefore, you need to examine the possibility of conflicts before modifying the schema.

Two types of conflicts can cause damage to the database schema. One is conflict with a sub class when the sub class schema is modified. The other is conflict with a super class when the super class is modified. The following are operations that may cause conflicts between classes.

  • Adding an attribute
  • Deleting an attribute
  • Adding a super class
  • Deleting a super class
  • Deleting a class

If a conflict occurs as a result of the above operations, CUBRID applies a basic resolution to the sub class where the conflict occurred. Therefore, the database schema can always maintain consistent state.

Resolution Specifier

Conflicts between the existing classes or attributes, and inheritance conflicts can occur if the database schema is modified. If the system fails to resolve a conflict automatically or if you don't like the way the system resolved the problem, you can suggest how to resolve the conflict by using the INHERIT clause of the ALTER statement (often referred to as resolution specifier).

When the system resolves the conflict automatically, basically, the existing inheritance is maintained (if any). If the previous resolution becomes invalid when the schema is modified, the system will arbitrarily select another one. Therefore, you must avoid excessive reuse of attributes or methods in the schema design stage because the way the system will resolve the conflict cannot always be predictable.

What will be discussed concerning conflicts is applied commonly to both attributes and methods.

ALTER [ class_type ] class_name alter_clause
[ INHERIT resolution [ {, resolution }_ ] ] [ ; ]

resolution:
{ column_name | method_name } OF superclass_name [ AS alias ]
Superclass Conflict
Adding a super class

The INHERIT clause of the ALTER CLASS statement is optional, but must be used when a conflict occurs due to class changes. You can specify more than one resolution after the INHERIT clause.

superclass_name specifies the name of the super class that has the new attribute(column) or method to inherit when a conflict occurs. column_name or method_name specifies the name of the attribute or method to inherit. You can use the AS clause when you need to change the name of the attribute or method to inherit.

The following example shows how to create the soccer_stadium class by inheriting the event and stadium classes in the olympic database of demodb. Because both event and stadium classes have the name and code attributes, you must specify the attributes to inherit using the INHERIT clause.

CREATE CLASS soccer_stadium UNDER event, stadium
INHERIT name OF stadium, code OF stadium;

When the two super classes (event and stadium) have the name attribute, if the soccer_stadium class needs to inherit both attributes, it can inherit the name unchanged from the stadium class and the name changed from the event class by using the alias clause of the INHERIT.

The following example shows in which the name attribute of the stadium class is inherited as it is, and that of the event class is inherited as the purpose alias.

ALTER CLASS soccer_stadium
INHERIT name OF event AS purpose;
Deleting a super class

A name conflict may occur again if a super class that explicitly inherited an attribute or method is dropped by using the INHERIT. In this case, you must specify the attribute or method to be explicitly inherited when dropping the super class.

CREATE CLASS a_tbl(a INT PRIMARY KEY, b INT);
CREATE CLASS b_tbl(a INT PRIMARY KEY, b INT, c INT);
CREATE CLASS c_tbl(b INT PRIMARY KEY, d INT);

CREATE CLASS a_b_c UNDER a_tbl, b_tbl, c_tbl INHERIT a OF b_tbl, b OF b_tbl;

ALTER CLASS a_b_c
DROP SUPERCLASS b_tbl
INHERIT b OF a_tbl;

The above example shows how to create the a_b_c class by inheriting a_tbl, b_tbl and c_tbl classes, and delete the b_tbl class from the super class. Because a and b are explicitly inherited from the b_tbl class, you must resolve their name conflicts before deleting it from the super class. However, a does not need to be specified explicitly because it exists only in the a_tbl class except for the b_tbl class to be deleted.

Compatible Domains

If the conflicting attributes do not have compatible domains, the class hierarchy cannot be created.

For example, the class that inherits a super class with the phone attribute of integer type cannot have another super class with the phone attribute of string type. If the types of the phone attributes of the two super classes are both String or Integer, you can add a new super class by resolving the conflict with the INHERIT clause.

Compatibility is checked when inheriting an attribute with the same name, but with the different domain. In this case, the attribute that has a lower class in the class inheritance hierarchy as the domain is automatically inherited. If the domains of the attributes to inherit are compatible, the conflict must be resolved in the class where an inheritance relationship is defined.

Sub class Conflict

Any changes in a class will be automatically propagated to all sub classes. If a problem occurs in the sub class due to the changes, CUBRID resolves the corresponding sub class conflict and then displays a message saying that the conflict has been resolved automatically by the system.

Sub class conflicts can occur due to operations such as adding a super class, or creating/deleting a method or an attribute. Any changes in a class will affect all sub classes. Since changes are automatically propagated, harmless changes can even cause side effects in sub classes.

Adding Attributes and Methods

The simplest sub class conflict occurs when an attribute is added. A sub class conflict occurs if an attribute added to a super class has the same name as one already inherited by another super class. In such cases, CUBRID will automatically resolve the problem. That is, the added attribute will not be inherited to all sub classes that have already inherited the attribute with the same name.

The following example shows how to add an attribute to the event class. The super classes of the soccer_stadium class are the event and the stadium classes, and the nation_code attribute already exists in the stadium class. Therefore, a conflict occurs in the soccer_stadium class if the nation_code attribute is added to the event class. However, CUBRID resolves this conflict automatically.

ALTER CLASS event
ADD ATTRIBUTE nation_code CHAR(3);

If the event class is dropped from the soccer_stadium super class, the cost attribute of the stadium class will be inherited automatically.

Dropping Attributes and Methods

When an attribute is dropped from a class, any resolution specifiers which refer to the attribute by using the INHERIT clause are also removed. If a conflict occurs due to the deletion of an attribute, the system will determine a new inheritance hierarchy. If you don't like the inheritance hierarchy determined by the system, you can determine it by using the INHERIT clause of the ALTER statement. The following example shows such conflict.

Suppose there is a sub class that inherits attributes from three different super classes. If a name conflict occurs in all super classes and the explicitly inherited attribute is dropped, one of the remaining two attributes will be inherited automatically to resolve the problem.

The following example shows sub class conflict. Classes B, C and D are super classes of class E, and have an attribute whose name is team and the domain is team_event. Class E was created with the place attribute inherited from class C as follows:

create class E under B, C, D
inherit place of C;

In this case, the inheritance hierarchy is as follows:

_images/image6.png

Suppose that you decide to delete class C from the super class. This drop will require changes to the inheritance hierarchy. Because the domains of the remaining classes B and D with the game attribute are at the same level, the system will randomly choose to inherit from one of the two classes. If you don't want the system to make a random selection, you can specify the class to inherit from by using the INHERIT clause when you change the class.

ALTER CLASS E INHERIT game OF D;
ALTER CLASS C DROP game;

Note

If the domain of one game attribute in one super class is event and that of another super class is team_event, team_event is more specific than event because team_event is the descendant of event. Therefore, a super class that has the team_event attribute as a domain will be inherited; a user cannot forcefully inherit a super class that has the event attribute as a domain.

Schema Invariant

Invariants of a database schema are a property of the schema that must be preserved consistently (before and after the schema change). There are four types of invariants: invariants of class hierarchy, name, inheritance and consistency.

Invariant of class hierarchy

has a single root and defines a class hierarchy as a Directed Acyclic Graph (DAG) where all connected classes have a single direction. That is, all classes except the root have one or more super classes, and cannot become their own super classes. The root of DAG is "object," a system-defined class.

Invariant of name

means that all classes in the class hierarchy and all attributes in a class must have unique names. That is, attempts to create classes with the same name or to create attributes or methods with the same name in a single class are not allowed.

Invariant of name is redefined by the 'RENAME' qualifier. The 'RENAME' qualifier allows the name of an attribute or method to be changed.

Invariant of inheritance

means that a class must inherit all attributes and methods from all super classes. This invariant can be distinguished with three qualifiers: source, conflict and domain. The names of inherited attributes and methods can be modified. For default or shared value attributes, the default or shared value can be modified. Invariant of inheritance means that such changes will be propagated to all classes that inherit these attributes and methods.

  • source qualifier

    means that if class C inherits sub classes of class S, only one of the sub class attributes (methods) inherited from class S can be inherited to class C. That is, if an attribute (method) defined in class S is inherited by other classes, it is in effect a single attribute (method), even though it exists in many sub classes. Therefore, if a class multiply inherits from classes that have attributes (methods) of the same source, only one appearance of the attribute (method) is inherited.

  • conflict qualifier

    means that if class C inherits from two or more classes that have attributes (methods) with the same name but of different sources, it can inherit more than one class. To inherit attributes (methods) with the same name, you must change their names so as not to violate the invariant of name.

  • domain qualifier

    means that a domain of an inherited attribute can be converted to the domain's sub class.

Invariant of consistency

means that the database schema must always follow the invariants of a schema and all rules except when it is being changed.

Rule for Schema Changes

The Invariants of a Schema section has described the characteristics of schema that must be preserved all the time.

There are some methods for changing schemas, and all these methods must be able to preserve the invariants of a schema. For example, suppose that in a class which has a single super class, the relationship with the super class is to be removed. If the relationship with the super class is removed, the class becomes a direct sub class of the object class, or the removal attempt will be rejected if the user specified that the class should have at least one super class. To have some rules for selecting one of the methods for changing schemas, even though such selection seems arbitrary, will be definitely useful to users and database designers.

The following three types of rules apply: conflict-resolution rules, domain-change rule and class-hierarchy rule.

Seven conflict-resolution rules reinforce the invariant of inheritance. Most schema change rules are needed because of name conflicts. A domain-change rule reinforces a domain resolution of the invariant of inheritance. A class-hierarchy rule reinforces the invariant of class hierarchy.

Conflict-Resolution Rules
  • Rule 1: If an attribute (method) name of class C and an attribute name of the super class S conflict with each other (that is, their names are same), the attribute of class C is used. The attribute of S is not inherited.

    If a class has one or more super classes, three aspects of the attribute (method) of each super class must be considered to determine whether the attributes are semantically equal and which attribute to inherit. The three aspects of the attribute (method) are the name, domain and source. The following table shows eight combinations of these three aspects that can happen with two super classes. In Case 1 (two different super classes have attributes with the same name, domain and source), only one of the two sub classes should be inherited because two attributes are identical. In Case 8 (two different super classes have attributes with different names, domains and sources), both classes should be inherited because two attributes are totally different ones.

    Case Name Domain Source
    1 Same Same Same
    2 Same Same Different
    3 Same Different Same
    4 Same Different Different
    5 Different Same Same
    6 Different Same Different
    7 Different Different Same
    8 Different Different Different

    Five cases (1, 5, 6, 7, 8) out of eight have clear meaning. Invariant of inheritance is a guideline for resolving conflicts in such cases. In other cases (2, 3, 4), it is very difficult to resolve conflicts automatically. Rules 2 and 3 can be resolutions for these conflicts.

  • Rule 2: When two or more super classes have attributes (methods) with different sources but the same name and domain, one or more attributes (methods) can be inherited if the conflict-resolution statement is used. If the conflict-resolution statement is not used, the system will select and inherit one of the two attributes.

    This rule is a guideline for resolving conflicts of Case 2 in the table above.

  • Rule 3: If two or more super classes have attributes with different sources and domains but the same name, attributes (methods) with more detailed (lower in the inheritance hierarchy) domains are inherited. If there is no inheritance relationship between domains, schema change is not allowed.

    This rule is a guideline for resolving conflicts of Case 3 and 4. If Case 3 and 4 conflict with each other, Case 3 has the priority.

  • Rule 4: The user can make any changes except the ones in Case 3 and 4. In addition, the resolution of sub class conflicts cannot cause changes in the super class.

    The philosophy of Rule 4 is that "an inheritance is a privilege that sub class has obtained from a super class, so changes in a sub class cannot affect the super class." Rule 4 means that the name of the attribute (method) included in the super class cannot be changed to resolve conflicts between class C and super classes. Rule 4 has an exception in cases where the schema change causes conflicts in Case 3 and 4.

    • For example, suppose that class A is the super class of class B, and class B has the playing_date attribute of DATE type. If an attribute of STRING type named playing_date is added to class A, it conflicts with the playing_date attribute in class B. This is what happens in Case 4. The precise way to resolve such conflict is for the user to specify that class B must inherit the playing_date attribute of class A. If a method refers to the attribute, the user of class B needs to modify the method properly so that the appropriate playing_date attribute will be referenced. Schema change of class A is not allowed because the schema falls into an inconsistent state if the user of class B does not describe an explicit statement to resolve the conflict occurring from the schema change.
    _images/image7.png
  • Rule 5: If a conflict occurs due to a schema change of the super class, the original resolution is maintained as long as the change does not violate the rules. However, if the original resolution becomes invalid due to the schema change, the system will apply another resolution.

    Rule 5 is for cases where a conflict is caused to a conflict-free class or where the original resolution becomes invalid.

    This is the case where the name or domain of an attribute (method) is modified or a super class is deleted when the attribute (method) is added to the super class or the one inherited from the super class is deleted. The philosophy of Rule 5 coincides with that of Rule 4. That is, the user can change the class freely without considering what effects the sub class that inherits from the given class will have on the inherited attribute (method).

    When you change the schema of class C, if you decide to inherit an attribute of the class due to an earlier conflict with another class, this may cause attribute (method) loss of class C. Instead, you must inherit one of the attributes (methods) that caused conflicts earlier.

    The schema change of the super class can cause a conflict between the attribute (method) of the super class and the (locally declared or inherited) attribute (method) of class C. In this case, the system resolves the conflict automatically by applying Rule 2 or 3 and may inform the user.

    Rule 5 cannot be applied to cases where a new conflict occurs due to the addition or deletion of the relationship with the super class. The addition/deletion of a super class must be limited to within the class. That is, the user must provide an explicit resolution.

  • Rule 6: Changes of attributes or methods are propagated only to sub classes without conflicts.

    This rule limits the application of Rule 5 and the invariant of inheritance. Conflicts can be detected and resolved by applying Rule 2 and 3.

  • Rule 7: Class C can be dropped even when an attribute of class R uses class C as a domain. In this case, the domain of the attribute that uses class C as a domain can be changed to object.

Domain-Change Rules
  • Rule 8: If the domain of an attribute of class C is changed from D to a super class of D, the new domain is less generic than the corresponding domain in the super class from which class C inherited the attribute. The following example explains the principle of this rule.

    Suppose that in the database there are the game class with the player attribute and the female_game class which inherits game. The domain of the player attribute of the game class is the athlete class, but the domain of the player attribute of the female_game class is changed to female_athlete which is a sub class of athlete. The following diagram shows such relationship. The domain of the player attribute of the female_game class can be changed back to athlete, which is the super class of female_athlete.

    _images/image8.png
Class-Hierarchy Rules
  • Rule 9: A class without a super class becomes a direct sub class of object. The class-hierarchy rule defines characteristics of classes without super classes. If you create a class without a super class, object becomes the super class. If you delete the super class S, which is a unique super class of class C, class C becomes a direct sub class of object.

Database Administration

User Management
Database User

To know the user name's writing rule, see Identifier.

CUBRID has two types of users by default: DBA and PUBLIC. At initial installation of the product, no password is set.

  • All users have authorization granted to the PUBLIC user. All users of the database are automatically the members of PUBLIC. Granting authorization to the PUBLIC means granting it all users.
  • The DBA user has the authorization of the database administrator. The DBA automatically becomes the member of all users and groups. That is, the DBA is granted the access for all tables. Therefore, there is no need to grant authorization explicitly to the DBA and DBA members. Each database user has a unique name. The database administrator can create multiple users simultaneously using the cubrid createdb utility (see cubrid Utilities for details). A database user cannot have a member who already has the same authorization. If authorization is granted to a user, all members of the user is automatically granted the same authorization.
CREATE USER

DBA and DBA members can create, drop and alter users by using SQL statements. At the initial installation, passwords for users are not configured.

CREATE USER user_name
[PASSWORD password]
[GROUPS user_name [{, user_name } ... ]]
[MEMBERS user_name [{, user_name } ... ]]
[COMMENT 'comment_string'];

DROP USER user_name;

ALTER USER user_name PASSWORD password;
  • user_name: specifies the user name to create, delete or change.
  • password: specifies the user password to create or change.
  • comment_string: specifies a comment for the user.

The following example shows how to create a user (Fred), change a password, and delete the user.

CREATE USER Fred;
ALTER USER Fred PASSWORD '1234';
DROP USER Fred;

The following example shows how to create a user and add member to the user. By the following statement, company becomes a group that has engineering, marketing and design as its members. marketing becomes a group with members smith and jones, design becomes a group with a member smith, and engineering becomes a group with a member brown.

CREATE USER company;
CREATE USER engineering GROUPS company;
CREATE USER marketing GROUPS company;
CREATE USER design GROUPS company;
CREATE USER smith GROUPS design, marketing;
CREATE USER jones GROUPS marketing;
CREATE USER brown GROUPS engineering;

The following example shows how to create the same groups as above but use the MEMBERS keyword instead of GROUPS.

CREATE USER smith;
CREATE USER brown;
CREATE USER jones;
CREATE USER engineering MEMBERS brown;
CREATE USER marketing MEMBERS smith, jones;
CREATE USER design MEMBERS smith;
CREATE USER company MEMBERS engineering, marketing, design;
User's COMMENT

A comment for a user can be written as follows.

CREATE USER designer GROUPS dbms, qa COMMENT 'user comment';

A comment for a user can be changed as the following ALTER USER statement.

ALTER USER DESIGNER COMMENT 'new comment';

You can see a comment for a user with this syntax.

SELECT name, comment FROM db_user;
GRANT

In CUBRID, the smallest grant unit of authorization is a table. You must grant appropriate authorization to other users (groups) before allowing them to access the table you created.

You don't need to grant authorization individually because the members of the granted group have the same authorization. The access to the (virtual) table created by a PUBLIC user is allowed to all users. You can grant access authorization to a user by using the GRANT statement.

GRANT operation [ { ,operation } ... ] ON table_name [ { ,table_name } ... ]
TO user [ { ,user } ... ] [ WITH GRANT OPTION ] ;
  • operation: Specifies an operation that can be used when granting authorization. The following table shows operations.

    • SELECT: Allows to read the table definitions and retrieve records. The most general type of permissions.
    • INSERT: Allows to create records in the table.
    • UPDATE: Allows to modify the records already existing in the table.
    • DELETE: Allows to delete records in the table.
    • ALTER: Allows to modify the table definition, rename or delete the table.
    • INDEX: Allows to call table methods or instance methods.
    • EXECUTE: Allows to call table methods or instance methods.
    • ALL PRIVILEGES: Includes all permissions described above.
  • table_name: Specifies the name of a table or virtual table to be granted.

  • user: Specifies the name of a user (group) to be granted. Enter the login name of the database user or PUBLIC, a system-defined user. If PUBLIC is specified, all database users are granted with the permission.

  • WITH GRANT OPTION: WITH GRANT OPTION allows the grantee of authorization to grant that same authorization to another user.

The following example shows how to grant the SELECT authorization for the olympic table to smith (including his members).

GRANT SELECT ON olympic TO smith;

The following example shows how to grant the SELECT, INSERT, UPDATE and DELETE authorization on the nation and athlete tables to brown and jones (including their members).

GRANT SELECT, INSERT, UPDATE, DELETE ON nation, athlete TO  brown, jones;

The following example shows how to grant every authorization on the tbl1 and tbl2 tables to all users(public).

CREATE TABLE tbl1 (a INT);
CREATE TABLE tbl2 (a INT);
GRANT ALL PRIVILEGES ON tbl1, tbl2 TO public;

The following example shows how to grant retrieving authorization on the record and history tables to brown. Using WITH GRANT OPTION allows brown to grant retrieving to another users. brown can grant authorization to others within his authorization.

GRANT SELECT ON record, history TO brown WITH GRANT OPTION;

Note

  • The grantor of authorization must be the owner of all tables listed before the grant operation or have WITH GRANT OPTION specified.
  • Before granting SELECT, UPDATE, DELETE and INSERT authorization for a virtual table, the owner of the virtual table must have SELECT and GRANT authorization for all the tables included in the query specification. The DBA user and the members of the DBA group are automatically granted all authorization for all tables.
  • To execute the TRUNCATE statement, the ALTER, INDEX, and DELETE authorization is required.
REVOKE

You can revoke authorization using the REVOKE statement. The authorization granted to a user can be revoked anytime. If more than one authorization is granted to a user, all or part of the authorization can be revoked. In addition, if authorization on multiple tables is granted to more than one user using one GRANT statement, the authorization can be selectively revoked for specific users and tables.

If the authorization (WITH GRANT OPTION) is revoked from the grantor, the authorization granted to the grantee by that grantor is also revoked.

REVOKE operation [ { , operation } ... ] ON table_name [ { , class_name } ... ]
FROM user [ { , user } ... ] ;
  • operation: Indicates an operation that can be used when granting authorization (see Syntax in GRANT for details).
  • table_name: Specifies the name of the table or virtual table to be granted.
  • user: Specifies the name of the user (group) to be granted.

The following example shows how to grant SELECT, INSERT, UPDATE and DELETE authorization to smith and jones so that they can perform on the nation and athlete tables.

GRANT SELECT, INSERT, UPDATE, DELETE ON nation, athlete TO smith, jones;

The following example shows how to execute the REVOKE statement; this allows jones to have only SELECT authorization. If jones has granted authorization to another user, the user is also allowed to execute SELECT only.

REVOKE INSERT, UPDATE, DELETE ON nation, athlete FROM jones;

The following example shows how to execute the REVOKE statement revoking all authorization that has granted to smith. smith is not allowed to execute any operations on the nation and athlete tables once this statement is executed.

REVOKE ALL PRIVILEGES ON nation, athlete FROM smith;
ALTER ... OWNER

Database Administrator (DBA) or a member of the DBA group can change the owner of table, view, trigger, and Java stored functions/procedures by using the following query.

ALTER [TABLE | CLASS | VIEW | VCLASS | TRIGGER | PROCEDURE | FUNCTION] name OWNER TO user_id;
  • name: The name of schema object of which owner is to be changed
  • user_id: User ID
ALTER TABLE test_tbl OWNER TO public;
ALTER VIEW test_view OWNER TO public;
ALTER TRIGGER test_trigger OWNER TO public;
ALTER FUNCTION test_function OWNER TO public;
ALTER PROCEDURE test_procedure OWNER TO public;
User Authorization Management METHOD

The database administrator (DBA) can check and modify user authorization by calling authorization-related methods defined in db_user where information about database user is stored, or db_authorizations (the system authorization class). The administrator can specify db_user or db_authorizations depending on the method to be called, and store the return value of a method to a variable. In addition, some methods can be called only by DBA or members of DBA group.

Note

Note that method call made by the master node is not applied to the slave node in the HA environment.

CALL method_definition ON CLASS auth_class [ TO variable ] [ ; ]
CALL method_definition ON variable [ ; ]

login( ) method

As a class method of db_user class, this method is used to change the users who are currently connected to the database. The name and password of a new user to connect are given as arguments, and they must be string type. If there is no password, a blank character ('') can be used as the argument. DBA and DBA members can call the login( ) method without a password.

-- Connect as DBA user who has no password
CALL login ('dba', '') ON CLASS db_user;

-- Connect as a user_1 whose password is cubrid
CALL login ('user_1', 'cubrid') ON CLASS db_user;

add_user( ) method

As a class method of db_user class, this method is used to add a new user. The name and password of a new user to add are given as arguments, and they must be string type. At this time, the new user name should not duplicate any user name already registered in a database. The add_user( ) can be called only by DBA or members of DBA group.

-- Add user_2 who has no password
CALL add_user ('user_3', '') ON CLASS db_user;

-- Add user_3 who has no password, and store the return value of a method into an admin variable
CALL add_user ('user_2', '') ON CLASS db_user to admin;

drop_user( ) method

As a class method of db_user class, this method is used to drop an existing user. Only the user name to be dropped is given as an argument, and it must be a string type. However, the owner of a class cannot be dropped thus DBA needs to specify a new owner of the class before dropping the user. The drop_user( ) method can be also called only by DBA or members of DBA.

-- Delete user_2
CALL drop_user ('user_2') ON CLASS db_user;

find_user( ) method

As a class method of db_user class, this method is used to find a user who is given as an argument. The name of a user to be found is given as an argument, and the return value of the method is stored into a variable that follows 'to'. The stored value can be used in a next query execution.

-- Find user_2 and store it into a variable called 'admin'
CALL find_user ('user_2') ON CLASS db_user to admin;

set_password( ) method

This method is an instance method that can call each user instance, and it is used to change a user's password. The new password of a specified user is given as an argument. General users other than DBA and DBA group members can only change their own passwords.

-- Add user_4 and store it into a variable called user_common
CALL add_user ('user_4','') ON CLASS db_user to user_common;

-- Change the password of user_4 to 'abcdef'
CALL set_password('abcdef') on user_common;

change_owner() method

As a class method of db_authorizations class, this method is used to change the owner of a class. The name of a class for which you want to change the owner, and the name of a new owner are given as arguments. At this time, the class and owner that are specified as an argument must exist in a database. Otherwise, an error occurs. change_owner( ) can be called only by DBA or members of DBA group. The ALTER ... OWNER query has the same role as the method. See ALTER ... OWNER.

-- Change the owner of table_1 to user_4
CALL change_owner ('table_1', 'user_4') ON CLASS db_authorizations;

The following example shows a CALL statement that calls the find_user method defined in the system table db_user. It is called to determine whether the database user entered as the find_user exists. The first statement calls the table method defined in the db_user class. The name (db_user in this case) is stored in x if the user is registered in the database. Otherwise, NULL is stored.

The second statement outputs the value stored in the variable x. In this query statement, the DB_ROOT is a system class that can have only one record. It can be used to output the value of sys_date or other registered variables. For this purpose, the DB_ROOT can be replaced by another table having only one record.

CALL find_user('dba') ON CLASS db_user to x;
Result
======================
db_user
SELECT x FROM db_root;
x
======================
db_user

With find_user, you can determine if the user exists in the database depending on whether the return value is NULL or not.

SET

The SET statement is the syntax that specifies a system parameter's value or user-defined variables.

System Parameter

You can define a value of a system parameter with SQL syntax by CSQL interpreter or a query editor of CUBRID Manager. However, be cautious that updatable parameters are limited. For the information of updatable parameters, see cubrid.conf Configuration File and Default Parameters.

SET SYSTEM PARAMETERS 'parameter_name=value [{; name=value}...]'

DEFAULT for value will reset the parameter to its default value with an exception of call_stack_dump_activation_list parameter.

SET SYSTEM PARAMETERS 'lock_timeout=DEFAULT';
User Variables

You can create user-defined variables in two ways. One is to use the SET statement and the other is to use the assignment statement of user-defined variables within SQL statements. You can delete the user-defined variables that you defined with the DEALLOCATE or the DROP statements.

The user-defined variables are also called session variables as they are used for maintaining connections within one application. The user-defined variables are used within the part of a connection session, and the user-defined variables defined by an application cannot be accessed by other applications. When an application terminates connections, all variables will be removed automatically. The user-defined variables are limited to twenty per connection session for an application. If you already have twenty user-defined variables and want to define a new user-defined variable, you must remove some variables with the DROP VARIABLE statement.

You can use user-defined variables in most SQL statements. If you define user-defined variables and refer to them in one statement, the sequence is not guaranteed. That is, if you refer to the variables specified in the SELECT list of the HAVING, GROUP BY or ORDER BY clause, you may not get the values in the sequence you expect. You cannot also use user-defined variables as identifiers, such as column names or table names within SQL statements

The user-defined variables are not case-sensitive. The user-defined variable type can be one of the SHORT, INTEGER, BIGINT, FLOAT, DOUBLE, NUMERIC, CHAR, VARCHAR, BIT and BIT VARYING. Other types will be converted to the VARCHAR type.

SET @v1 = 1, @v2=CAST(1 AS BIGINT), @v3 = '123', @v4 = DATE'2010-01-01';

SELECT typeof(@v1), typeof(@v2), typeof(@v3), typeof(@v4);
   typeof(@v1)         typeof(@v2)         typeof(@v3)         typeof(@v4)
======================================================================================
  'integer'           'bigint'            'character (-1)'    'character varying (1073741823)

The user-defined variables can be changed when you define values.

SET @v = 'a';
SET @v1 = 10;

SELECT @v := 1, typeof(@v1), @v1:='1', typeof(@v1);
  @v := 1                typeof(@v1)          @v1 := '1'             typeof(@v1)
======================================================================================
  1                     'integer'             '1'                    'character (-1)'
<set_statement>
        : <set_statement>, <udf_assignment>
        | SET <udv_assignment>
        ;

<udv_assignment>
        : @<name> = <expression>
        | @<name> := <expression>
        ;

{DEALLOCATE|DROP} VARIABLE <variable_name_list>
<variable_name_list>
       : <variable_name_list> ',' @<name>
  • You must define the variable names with alphanumeric characters and underscores (_).
  • When you define the variables within SQL statements, you should use the ':=' operator.

The following example shows how to define the variable a and assign a value 1 to it.

SET @a = 1;
SELECT @a;
  @a
======================
  1

The following example shows how to count the number of rows in the SELECT statement by using the user-defined variable.

CREATE TABLE t (i INTEGER);
INSERT INTO t(i) VALUES(2),(4),(6),(8);

SET @a = 0;

SELECT @a := @a+1 AS row_no, i FROM t;
  row_no                          i
 ===================================
  1                               2
  2                               4
  3                               6
  4                               8

4 rows selected.

The following example shows how to use the user-defined variable as the input of bind parameter specified in the prepared statement.

SET @a:=3;

PREPARE stmt FROM 'SELECT i FROM t WHERE i < ?';
EXECUTE stmt USING @a;
            i
=============
            2

The following example shows how to declare the user-defined variable by using the ':=' operator.

SELECT @a := 1, @user_defined_variable := 'user defined variable';
UPDATE t SET i = (@var := 1);

The following example shows how to delete the user-defined variable a and user_defined_variable.

DEALLOCATE VARIABLE @a, @user_defined_variable;
DROP VARIABLE @a, @user_defined_variable;

Note

The user-defined variables that are defined by the SET statement start by connecting an application to a server and will be maintained until the application terminates the connection. The connection maintained during this period is called a session. When an application terminates the connection or when there are no requests for a certain period of time, the session will expire, and the user-defined variables will be deleted as a result. You can set the session time with the session_state_timeout parameter of cubrid.conf; the default value is 21600 seconds (=6 hours).

The data managed by the session includes PREPARE statements, the user-defined variables, the last ID inserted (LAST_INSERT_ID) and the number of rows affected by the statement that you execute at the end (ROW_COUNT).

KILL

The KILL statement terminates transactions with an option TRANSACTION or QUERY modifier.

KILL [TRANSACTION | QUERY] tran_index, ... ;

  • KILL TRANSACTION is default of KILL statement. It is the same as KILL without a modifier. It terminates the connection associated with the given tran_index.
  • KILL QUERY terminates the statement that the transaction is executing.

DBA and a user of DBA group are able to terminate all the transactions of the system, while non-DBA users are only allowed to terminate their own transaction.

KILL TRANSACTION 1;
SHOW
DESC, DESCRIBE

It shows the column information of a table, and it's like a SHOW COLUMNS statement. For more details, see SHOW COLUMNS.

DESC tbl_name;
DESCRIBE tbl_name;
EXPLAIN

It shows the column information of a table, and it's like a SHOW COLUMNS statement. For more details, see SHOW COLUMNS.

EXPLAIN tbl_name;
SHOW TABLES

It shows the list of all table names within a database. The name of the result column will be tables_in_<database name> and it will have one column. If you use the LIKE clause, you can search the table names matching this and if you use the WHERE clause, you can search table names with more general terms. SHOW FULL TABLES displays the second column, table_type together. The table must have the value, BASE TABLE and the view has the value, VIEW.

SHOW [FULL] TABLES [LIKE 'pattern' | WHERE expr];

The following shows the examples of this syntax.

SHOW TABLES;
Tables_in_demodb
======================
  'athlete'
  'code'
  'event'
  'game'
  'history'
  'nation'
  'olympic'
  'participant'
  'record'
  'stadium'
SHOW FULL TABLES;
  Tables_in_demodb     Table_type
============================================
  'athlete'             'BASE TABLE'
  'code'                'BASE TABLE'
  'event'               'BASE TABLE'
  'game'                'BASE TABLE'
  'history'             'BASE TABLE'
  'nation'              'BASE TABLE'
  'olympic'             'BASE TABLE'
  'participant'         'BASE TABLE'
  'record'              'BASE TABLE'
  'stadium'             'BASE TABLE'
SHOW FULL TABLES LIKE '%c%';
  Tables_in_demodb      Table_type
============================================
  'code'                'BASE TABLE'
  'olympic'             'BASE TABLE'
  'participant'         'BASE TABLE'
  'record'              'BASE TABLE'
SHOW FULL TABLES WHERE table_type = 'BASE TABLE' and TABLES_IN_demodb LIKE '%co%';
  Tables_in_demodb      Table_type
============================================
  'code'                'BASE TABLE'
  'record'              'BASE TABLE'
SHOW COLUMNS

It shows the column information of a table. You can use the LIKE clause to search the column names matching it. If you use the WHERE clause, you can search column names with more general terms like, "General Considerations for All SHOW Statements.".

SHOW [FULL] COLUMNS {FROM | IN} tbl_name [LIKE 'pattern' | WHERE expr];

If a FULL keyword is used, it shows the additional information, collation and comment.

SHOW FIELDS is the same statement as SHOW COLUMNS.

The DESCRIBE (abbreviated DESC) statement and the EXPLAIN statement provide the same information with SHOW COLUMNS, but they don't support LIKE clause or WHERE clause.

This query has the following columns:

Column name Type Description
Field VARCHAR Column name
Type VARCHAR Column data type
Null VARCHAR If you can store NULL, the value is YES; if not, it is NO
Key VARCHAR
Whether a column has an index or not. If there is more than one key value in the given column of a table, this displays only the one that appears first in the order of PRI, UNI and MUL.
  • If the key is a space, the column doesn't have an index, it is not the first column in the multiple column index or the index is non-unique.
  • If the value is PRI, it is a primary key or the primary key of multiple columns.
  • If the value is UNI, it is a unique index. (The unique index allows multiple NULL values but you can also set a NOT NULL constraint.)
  • If the value is MUL, it is the first column of the non-unique index that allows the given value to be displayed in the column several times. If the column composes a composite unique index, the value will be MUL. The combination of column values can be unique but the value of each column can appear several times.
Default VARCHAR Default value defined in the column
Extra VARCHAR Additional information available on the given column. For the column with AUTO_INCREMENT constraint, it shows the 'auto_increment'.

The following shows the examples of this syntax.

SHOW COLUMNS FROM athlete;
  Field                 Type                  Null       Key          Default               Extra
================================================================================================================
  'code'                'INTEGER'             'NO'       'PRI'        NULL                  'auto_increment'
  'name'                'VARCHAR(40)'         'NO'       ''           NULL                  ''
  'gender'              'CHAR(1)'             'YES'      ''           NULL                  ''
  'nation_code'         'CHAR(3)'             'YES'      ''           NULL                  ''
  'event'               'VARCHAR(30)'         'YES'      ''           NULL                  ''
SHOW COLUMNS FROM athlete WHERE field LIKE '%c%';
  Field                 Type                  Null       Key          Default               Extra
================================================================================================================
  'code'                'INTEGER'             'NO'       'PRI'        NULL                  'auto_increment'
  'nation_code'         'CHAR(3)'             'YES'      ''           NULL                  ''
SHOW COLUMNS FROM athlete  WHERE "type" = 'INTEGER' and "key"='PRI' AND extra='auto_increment';
  Field                 Type                  Null       Key          Default               Extra
================================================================================================================
  'code'                'INTEGER'             'NO'       'PRI'        NULL                  'auto_increment'
SHOW FULL COLUMNS FROM athlete WHERE field LIKE '%c%';
  Field                 Type                  Collation             Null                  Key                   Default               Extra                 Comment
================================================================================================================================================================================
  'code'                'INTEGER'             NULL                  'NO'                  'PRI'                 NULL                  'auto_increment'      NULL
  'nation_code'         'CHAR(3)'             'iso88591_bin'        'YES'                 ''                    NULL                  ''                    NULL
SHOW INDEX

It shows the index information.

SHOW {INDEX | INDEXES | KEYS } {FROM | IN} tbl_name;

This query has the following columns:

Column name Type Description
Table VARCHAR Table name
Non_unique INTEGER
Unique or not
  • 0: Duplicated value is not allowed
  • 1: Duplicated value is allowed
Key_name VARCHAR Index name
Seq_in_index INTEGER Serial number of the column in the index. Starts from 1.
Column_name VARCHAR Column name
Collation VARCHAR Method of sorting columns in the index. 'A' means ascending and NULL means not sorted.
Cardinality INTEGER The number of values measuring the unique values in the index. Higher cardinality increases the opportunity of using an index. This value is updated every time SHOW INDEX is executed. Note that this is an approximate value.
Sub_part INTEGER The number of bytes of the indexed characters if the columns are indexed partially. NULL if all columns are indexed.
Packed   Shows how keys are packed. If they are not packed, it will be NULL. Currently no support.
Null VARCHAR YES if a column can include NULL, NO if not.
Index_type VARCHAR Index to be used (currently, only the BTREE is supported.)
Func VARCHAR A function which is used in a function-based index
Comment VARCHAR Comment to describe the index

The following shows the examples of this syntax.

SHOW INDEX IN athlete;
  Table                  Non_unique  Key_name              Seq_in_index  Column_name           Collation             Cardinality     Sub_part  Packed                Null
                  Index_type            Func                  Comment
=================================================================================================================================================================================
==========================================================================
  'athlete'                       0  'pk_athlete_code'                1  'code'                'A'                          6677         NULL  NULL                  'NO'
                  'BTREE'               NULL                  NULL
CREATE TABLE tbl1 (i1 INTEGER , i2 INTEGER NOT NULL, i3 INTEGER UNIQUE, s1 VARCHAR(10), s2 VARCHAR(10), s3 VARCHAR(10) UNIQUE);

CREATE INDEX i_tbl1_i1 ON tbl1 (i1 DESC);
CREATE INDEX i_tbl1_s1 ON tbl1 (s1 (7));
CREATE INDEX i_tbl1_i1_s1 ON tbl1 (i1, s1);
CREATE UNIQUE INDEX i_tbl1_i2_s2 ON tbl1 (i2, s2);

SHOW INDEXES FROM tbl1;
  Table                  Non_unique  Key_name              Seq_in_index  Column_name           Collation             Cardinality     Sub_part  Packed                Null
                  Index_type            Func                  Comment
=================================================================================================================================================================================
==========================================================================
  'tbl1'                          1  'i_tbl1_i1'                      1  'i1'                  'D'                             0         NULL  NULL                  'YES'
                  'BTREE'               NULL                  NULL
  'tbl1'                          1  'i_tbl1_i1_s1'                   1  'i1'                  'A'                             0         NULL  NULL                  'YES'
                  'BTREE'               NULL                  NULL
  'tbl1'                          1  'i_tbl1_i1_s1'                   2  's1'                  'A'                             0         NULL  NULL                  'YES'
                  'BTREE'               NULL                  NULL
  'tbl1'                          0  'i_tbl1_i2_s2'                   1  'i2'                  'A'                             0         NULL  NULL                  'NO'
                  'BTREE'               NULL                  NULL
  'tbl1'                          0  'i_tbl1_i2_s2'                   2  's2'                  'A'                             0         NULL  NULL                  'YES'
                  'BTREE'               NULL                  NULL
  'tbl1'                          1  'i_tbl1_s1'                      1  's1'                  'A'                             0            7  NULL                  'YES'
                  'BTREE'               NULL                  NULL
  'tbl1'                          0  'u_tbl1_i3'                      1  'i3'                  'A'                             0         NULL  NULL                  'YES'
                  'BTREE'               NULL                  NULL
  'tbl1'                          0  'u_tbl1_s3'                      1  's3'                  'A'                             0         NULL  NULL                  'YES'
                  'BTREE'               NULL                  NULL
SHOW COLLATION

It lists collations supported by the database. If LIKE clause is present, it indicates which collation names to match.

SHOW COLLATION [ LIKE 'pattern' ];

This query has the following columns:

Column name Type Description
Collation VARCHAR Collation name
Charset CHAR(1) Charset name
Id INTEGER Collation ID
Built_in CHAR(1) Built-in collation or not. Built-in collations are impossible to add or remove because they are hard-coded.
Expansions CHAR(1) Collation with expansion or not. For details, see Expansion.
Strength CHAR(1) The number of levels to be considered in comparison, and the character order can be different by this number. For details, see Collation Properties.

The following shows the examples of this syntax.

SHOW COLLATION;
  Collation             Charset                        Id  Built_in              Expansions            Strength
===========================================================================================================================
  'euckr_bin'           'euckr'                         8  'Yes'                 'No'                  'Not applicable'
  'iso88591_bin'        'iso88591'                      0  'Yes'                 'No'                  'Not applicable'
  'iso88591_en_ci'      'iso88591'                      3  'Yes'                 'No'                  'Not applicable'
  'iso88591_en_cs'      'iso88591'                      2  'Yes'                 'No'                  'Not applicable'
  'utf8_bin'            'utf8'                          1  'Yes'                 'No'                  'Not applicable'
  'utf8_de_exp'         'utf8'                         76  'No'                  'Yes'                 'Tertiary'
  'utf8_de_exp_ai_ci'   'utf8'                         72  'No'                  'Yes'                 'Primary'
  'utf8_en_ci'          'utf8'                          5  'Yes'                 'No'                  'Not applicable'
  'utf8_en_cs'          'utf8'                          4  'Yes'                 'No'                  'Not applicable'
  'utf8_es_cs'          'utf8'                         85  'No'                  'No'                  'Quaternary'
  'utf8_fr_exp_ab'      'utf8'                         94  'No'                  'Yes'                 'Tertiary'
  'utf8_gen'            'utf8'                         32  'No'                  'No'                  'Quaternary'
  'utf8_gen_ai_ci'      'utf8'                         37  'No'                  'No'                  'Primary'
  'utf8_gen_ci'         'utf8'                         44  'No'                  'No'                  'Secondary'
  'utf8_ja_exp'         'utf8'                        124  'No'                  'Yes'                 'Tertiary'
  'utf8_ja_exp_cbm'     'utf8'                        125  'No'                  'Yes'                 'Tertiary'
  'utf8_km_exp'         'utf8'                        132  'No'                  'Yes'                 'Quaternary'
  'utf8_ko_cs'          'utf8'                          7  'Yes'                 'No'                  'Not applicable'
  'utf8_ko_cs_uca'      'utf8'                        133  'No'                  'No'                  'Quaternary'
  'utf8_tr_cs'          'utf8'                          6  'Yes'                 'No'                  'Not applicable'
  'utf8_tr_cs_uca'      'utf8'                        205  'No'                  'No'                  'Quaternary'
  'utf8_vi_cs'          'utf8'                        221  'No'                  'No'                  'Quaternary'
SHOW COLLATION LIKE '%_ko_%';
  Collation             Charset                        Id  Built_in              Expansions            Strength
===========================================================================================================================
  'utf8_ko_cs'          'utf8'                          7  'Yes'                 'No'                  'Not applicable'
  'utf8_ko_cs_uca'      'utf8'                        133  'No'                  'No'                  'Quaternary'
SHOW TIMEZONES

It shows the timezone information which the current CUBRID supports.

SHOW [FULL] TIMEZONES [ LIKE 'pattern' ];

If FULL is not specified, one column which has timezone's region names is displayed. The name of this column is timezone_region.

If FULL is specified, four columns which have timezone information are displayed.

If LIKE clause is present, it indicates which timezone_region names to match.

Column name Type Description
timezone_region VARCHAR(32) Timezone region name
region_offset VARCHAR(32) Offset of timezone (daylight saving time is not considered)
dst_offset VARCHAR(32) Offset of daylight saving time (applied to timezone region) which is currently considered
dst_abbreviation VARCHAR(32) An abbreviation of the daylight saving time which is currently applied for the region

The information listed for the second, third and fourth columns is for the current date and time.

If a timezone region doesn't have daylight saving time rules at all then the dst_offset and dst_abbreviation columns will contain NULL values.

If at the current date, there aren't daylight saving time rules that apply, then dst_offset will be set to 0 and dst_abbreviation will be the empty string.

The LIKE condition without the WHERE condition is applied on the first column. The WHERE condition may be used to filter the output.

SHOW TIMEZONES;
timezone_region
======================
'Africa/Abidjan'
'Africa/Accra'
'Africa/Addis_Ababa'
'Africa/Algiers'
'Africa/Asmara'
'Africa/Asmera'
...
'US/Michigan'
'US/Mountain'
'US/Pacific'
'US/Samoa'
'UTC'
'Universal'
'W-SU'
'WET'
'Zulu'
SHOW FULL TIMEZONES;
timezone_region       region_offset         dst_offset            dst_abbreviation
===================================================================================
'Africa/Abidjan'      '+00:00'              '+00:00'              'GMT'
'Africa/Accra'        '+00:00'              NULL                  NULL
'Africa/Addis_Ababa'  '+03:00'              '+00:00'              'EAT'
'Africa/Algiers'      '+01:00'              '+00:00'              'CET'
'Africa/Asmara'       '+03:00'              '+00:00'              'EAT'
'Africa/Asmera'       '+03:00'              '+00:00'              'EAT'
...
'US/Michigan'         '-05:00'              '+00:00'              'EST'
'US/Mountain'         '-07:00'              '+00:00'              'MST'
'US/Pacific'          '-08:00'              '+00:00'              'PST'
'US/Samoa'            '-11:00'              '+00:00'              'SST'
'UTC'                 '+00:00'              '+00:00'              'UTC'
'Universal'           '+00:00'              '+00:00'              'UTC'
'W-SU'                '+04:00'              '+00:00'              'MSK'
'WET'                 '+00:00'              '+00:00'              'WET'
'Zulu'                '+00:00'              '+00:00'              'UTC'
SHOW FULL TIMEZONES LIKE '%Paris%';
timezone_region       region_offset         dst_offset            dst_abbreviation
========================================================================================
'Europe/Paris'        '+01:00'              '+00:00'              'CET'
SHOW GRANTS

It shows the permissions associated with the database user accounts.

SHOW GRANTS FOR 'user';

The following shows the examples of this syntax.

CREATE TABLE testgrant (id INT);
CREATE USER user1;
GRANT INSERT,SELECT ON testgrant TO user1;

SHOW GRANTS FOR user1;
  Grants for USER1
======================
  'GRANT INSERT, SELECT ON testgrant TO USER1'
SHOW CREATE TABLE

When a table name is specified, It shows the CREATE TABLE statement of the table.

SHOW CREATE TABLE table_name;
SHOW CREATE TABLE nation;
  TABLE                 CREATE TABLE
============================================
  'nation'               'CREATE TABLE [nation] ([code] CHARACTER(3) NOT NULL,
[name] CHARACTER VARYING(40) NOT NULL, [continent] CHARACTER VARYING(10),
[capital] CHARACTER VARYING(30),  CONSTRAINT [pk_nation_code] PRIMARY KEY  ([code]))
COLLATE iso88591_bin'

SHOW CREATE TABLE statement does not display as the user's written syntax. For example, the comment that user wrote is not displayed, and table names and column names are always displayed as lower case letters.

SHOW CREATE VIEW

It shows the corresponding CREATE VIEW statement if view name is specified.

SHOW CREATE VIEW view_name;

The following shows the examples of this syntax.

SHOW CREATE VIEW db_class;
  View              Create View
========================================
  'db_class'       'SELECT c.class_name, CAST(c.owner.name AS VARCHAR(255)), CASE c.class_type WHEN 0 THEN 'CLASS' WHEN 1 THEN 'VCLASS' ELSE
                   'UNKNOW' END, CASE WHEN MOD(c.is_system_class, 2) = 1 THEN 'YES' ELSE 'NO' END, CASE WHEN c.sub_classes IS NULL THEN 'NO'
                   ELSE NVL((SELECT 'YES' FROM _db_partition p WHERE p.class_of = c and p.pname IS NULL), 'NO') END, CASE WHEN
                   MOD(c.is_system_class / 8, 2) = 1 THEN 'YES' ELSE 'NO' END FROM _db_class c WHERE CURRENT_USER = 'DBA' OR {c.owner.name}
                   SUBSETEQ (  SELECT SET{CURRENT_USER} + COALESCE(SUM(SET{t.g.name}), SET{})  FROM db_user u, TABLE(groups) AS t(g)  WHERE
                   u.name = CURRENT_USER) OR {c} SUBSETEQ (  SELECT SUM(SET{au.class_of})  FROM _db_auth au  WHERE {au.grantee.name} SUBSETEQ
                   (  SELECT SET{CURRENT_USER} + COALESCE(SUM(SET{t.g.name}), SET{})  FROM db_user u, TABLE(groups) AS t(g)  WHERE u.name =
                   CURRENT_USER) AND  au.auth_type = 'SELECT')'
SHOW ACCESS STATUS

SHOW ACCESS STATUS statement displays login information regarding database accounts. Only database's DBA account can use this statement.

SHOW ACCESS STATUS [LIKE 'pattern' | WHERE expr] ;

This statement displays the following columns.

Column name Type Description
user_name VARCHAR(32) DB user's account
last_access_time DATETIME Last time that the database user accessed
last_access_host VARCHAR(32) Lastly accessed host
program_name VARCHAR(32) The name of client program(broker_cub_cas_1, csql ..)

The following shows the result of running this statement.

SHOW ACCESS STATUS;
  user_name last_access_time last_access_host program_name
=============================================================================
  'DBA' 08:19:31.000 PM 02/10/2014 127.0.0.1 'csql'
  'PUBLIC' NULL NULL NULL

Note

The above login information which SHOW ACCESS STATUS shows is initialized when the database is restarted, and this query is not replication in HA environment; therefore, each node shows the different result.

SHOW EXEC STATISTICS

It shows statistics information of executing query.

  • To start collecting @collect_exec_stats statistics information, configure the value of session variable @collect_exec_stats to 1; to stop, configure it to 0.
  • It outputs the result of collecting statistics information.
    • The SHOW EXEC STATISTICS statement outputs four part of data page statistics information; data_page_fetches, data_page_dirties, data_page_ioreads, and data_page_iowrites. The result columns consist of variable column (name of statistics name) and value column (value of statistics value). Once the SHOW EXEC STATISTICS statement is executed, the statistics information which has been accumulated is initialized.
    • The SHOW EXEC STATISTICS ALL statement outputs all items of statistics information.

For details, see statdump.

SHOW EXEC STATISTICS [ALL];

The following shows the examples of this syntax.

-- set session variable @collect_exec_stats as 1 to start collecting the statistical information.
SET @collect_exec_stats = 1;
SELECT * FROM db_class;

-- print the statistical information of the data pages.
SHOW EXEC STATISTICS;
variable                value
===============================
'data_page_fetches'     332
'data_page_dirties'     85
'data_page_ioreads'     18
'data_page_iowrites'    28
SELECT * FROM db_index;

-- print all of the statistical information.
SHOW EXEC STATISTICS ALL;
variable                                value
============================================
'file_creates'                          0
'file_removes'                          0
'file_ioreads'                          6
'file_iowrites'                         0
'file_iosynches'                        0
'data_page_fetches'                     548
'data_page_dirties'                     34
'data_page_ioreads'                     6
'data_page_iowrites'                    0
'data_page_victims'                     0
'data_page_iowrites_for_replacement'    0
'log_page_ioreads'                      0
'log_page_iowrites'                     0
'log_append_records'                    0
'log_checkpoints'                       0
'log_wals'                              0
'page_locks_acquired'                   13
'object_locks_acquired'                 9
'page_locks_converted'                  0
'object_locks_converted'                0
'page_locks_re-requested'               0
'object_locks_re-requested'             8
'page_locks_waits'                      0
'object_locks_waits'                    0
'tran_commits'                          3
'tran_rollbacks'                        0
'tran_savepoints'                       0
'tran_start_topops'                     6
'tran_end_topops'                       6
'tran_interrupts'                       0
'btree_inserts'                         0
'btree_deletes'                         0
'btree_updates'                         0
'btree_covered'                         0
'btree_noncovered'                      2
'btree_resumes'                         0
'btree_multirange_optimization'         0
'query_selects'                         4
'query_inserts'                         0
'query_deletes'                         0
'query_updates'                         0
'query_sscans'                          2
'query_iscans'                          4
'query_lscans'                          0
'query_setscans'                        2
'query_methscans'                       0
'query_nljoins'                         2
'query_mjoins'                          0
'query_objfetches'                      0
'network_requests'                      88
'adaptive_flush_pages'                  0
'adaptive_flush_log_pages'              0
'adaptive_flush_max_pages'              0
'network_requests'                      88
'adaptive_flush_pages'                  0
'adaptive_flush_log_pages'              0
'adaptive_flush_max_pages'              0
Diagnostics
SHOW VOLUME HEADER

It shows the volume header of the specified volume in one row.

SHOW VOLUME HEADER OF volume_id;

This query has the following columns:

Column name Type Description
Volume_id INT Volume identifier
Magic_symbol VARCHAR(100) Magic value for for a volume file
Io_page_size INT Size of DB volume
Purpose VARCHAR(32) Volume purposes, purposes type: DATA, INDEX, GENERIC, TEMP TEMP, TEMP
Sector_size_in_pages INT Size of sector in pages
Num_total_sectors INT Total number of sectors
Num_free_sectors INT Number of free sectors
Hint_alloc_sector INT Hint for next sector to be allocated
Num_total_pages INT Total number of pages
Num_free_pages INT Number of free pages
Sector_alloc_table_size_in_pages INT Size of sector allocation table in page
Sector_alloc_table_first_page INT First page of sector allocation table
Page_alloc_table_size_in_pages INT Size of page allocation table in page
Page_alloc_table_first_page INT First page of page allocation table
Last_system_page INT Last system page
Creation_time DATETIME Database creation time
Num_max_pages INT max page count of this volume, this is not equal to the total_pages,if this volume is auto extended
Num_used_data_pages INT allocated pages for DATA purpose
Num_used_index_pages INT allocated pages for INDEX purpose
Checkpoint_lsa VARCHAR(64) Lowest log sequence address to start the recovery process of this volume
Boot_hfid VARCHAR(64) System Heap file for booting purposes and multi volumes
Full_name VARCHAR(255) The full path of volume
Next_vol_full_name VARCHAR(255) The full path of next volume
Remarks VARCHAR(64)  

The following shows the examples of this syntax.

-- csql> ;line on
SHOW VOLUME HEADER OF 0;
<00001> Volume_id                       : 0
        Magic_symbol                    : 'MAGIC SYMBOL = CUBRID/Volume at disk location = 32'
        Io_page_size                    : 16384
        Purpose                         : 'Permanent GENERIC Volume'
        Sector_size_in_pages            : 10
        Num_total_sectors               : 640
        Num_free_sectors                : 550
        Hint_alloc_sector               : 94
        Num_total_pages                 : 6400
        Num_free_pages                  : 6025
        Sector_alloc_table_size_in_pages: 1
        Sector_alloc_table_first_page   : 1
        Page_alloc_table_size_in_pages  : 1
        Page_alloc_table_first_page     : 2
        Last_system_page                : 2
        Creation_time                   : 06:09:27.000 PM 02/27/2014
        Num_max_pages                   : 6400
        Num_used_data_pages             : 192
        Num_used_index_pages            : 180
        Checkpoint_lsa                  : '(0|12832)'
        Boot_hfid                       : '(0|41|50)'
        Full_name                       : '/home1/brightest/CUBRID/databases/demodb/demodb'
        Next_vol_full_name              : ''
        Remarks                         : ''
SHOW LOG HEADER

It shows the header information of an active log file.

SHOW LOG HEADER [OF file_name];

If you omit OF file_name, it shows the header information of a memory; if you include OF file_name, it shows the header information of file_name.

This query has the following columns:

Column name Type Description
Magic_symbol VARCHAR(32) Magic value for log file
Magic_symbol_location INT Magic symbol location from log page
Creation_time DATETIME Database creation time
Release VARCHAR(32) CUBRID Release version
Compatibility_disk_version VARCHAR(32) Compatibility of the database against the current release of CUBRID
Db_page_size INT Size of pages in the database
Log_page_size INT Size of log pages in the database
Shutdown INT Was the log shutdown
Next_trans_id INT Next transaction identifier
Num_avg_trans INT Number of average transactions
Num_avg_locks INT Average number of object locks
Num_active_log_pages INT Number of pages in the active log portion
Db_charset INT charset number of database
First_active_log_page BIGINT Logical pageid at physical location 1 in active log
Current_append VARCHAR(64) Current append location
Checkpoint VARCHAR(64) Lowest log sequence address to start the recovery process
Next_archive_page_id BIGINT Next logical page to archive
Active_physical_page_id INT Physical location of logical page to archive
Next_archive_num INT Next log archive number
Last_archive_num_for_syscrashes INT Last log archive needed for system crashes
Last_deleted_archive_num INT Last deleted archive number
Backup_lsa_level0 VARCHAR(64) LSA of backup level 0
Backup_lsa_level1 VARCHAR(64) LSA of backup level 1
Backup_lsa_level2 VARCHAR(64) LSA of backup level 2
Log_prefix VARCHAR(256) Log prefix name
Has_logging_been_skipped INT Whether or not logging skipped
Perm_status VARCHAR(64) Reserved for future expansion
Backup_info_level0 VARCHAR(128) detail information of backup level 0. currently only backup start-time is used
Backup_info_level1 VARCHAR(128) detail information of backup level 1. currently only backup start-time is used
Backup_info_level2 VARCHAR(128) detail information of backup level 2. currently only backup start-time is used
Ha_server_state VARCHAR(32) current ha state, one of flowing value: na, idle, active, to-be-active, standby, to-be-standby, maintenance, dead
Ha_file VARCHAR(32) ha replication status, one of following value: clear, archived, sync
Eof_lsa VARCHAR(64) EOF LSA
Smallest_lsa_at_last_checkpoint VARCHAR(64) The smallest LSA of the last checkpoint, can be NULL LSA
Next_mvcc_id BIGINT The next MVCCID will be used for the next transaction
Mvcc_op_log_lsa VARCHAR(32) The LSA used to link log entries for MVCC operation
Last_block_oldest_mvcc_id BIGINT Used to find the oldest MVCCID in a block of log data, can be NULL
Last_block_newest_mvcc_id BIGINT Used to find the newest MVCCID in a block of log data, Can be NULL

The following shows the examples of this syntax.

-- csql> ;line on
SHOW LOG HEADER;
::
<00001> Volume_id : -2
Magic_symbol : 'CUBRID/LogActive' Magic_symbol_location : 16 Creation_time : 05:27:05.000 PM 02/05/2016 Release : '10.0.0' Compatibility_disk_version : '10' Db_page_size : 16384 Log_page_size : 16384 Shutdown : 0 Next_trans_id : 17 Num_avg_trans : 3 Num_avg_locks : 30 Num_active_log_pages : 1279 Db_charset : 3 First_active_log_page : 0 Current_append : '(102|5776)' Checkpoint : '(101|7936)' Next_archive_page_id : 0 Active_physical_page_id : 1 Next_archive_num : 0 Last_archive_num_for_syscrashes: -1 Last_deleted_archive_num : -1 Backup_lsa_level0 : '(-1|-1)' Backup_lsa_level1 : '(-1|-1)' Backup_lsa_level2 : '(-1|-1)' Log_prefix : 'mvccdb' Has_logging_been_skipped : 0 Perm_status : 'LOG_PSTAT_CLEAR' Backup_info_level0 : 'time: N/A' Backup_info_level1 : 'time: N/A' Backup_info_level2 : 'time: N/A' Ha_server_state : 'idle' Ha_file : 'UNKNOWN' Eof_lsa : '(102|5776)' Smallest_lsa_at_last_checkpoint: '(101|7936)' Next_mvcc_id : 6 Mvcc_op_log_lsa : '(102|5488)' Last_block_oldest_mvcc_id : 4 Last_block_newest_mvcc_id : 5
SHOW LOG HEADER OF 'demodb_lgat';
<00001> Volume_id                      : -2
        Magic_symbol                   : 'CUBRID/LogActive'
        Magic_symbol_location          : 16
        Creation_time                  : 05:27:05.000 PM 02/05/2016
        Release                        : '10.0.0'
        Compatibility_disk_version     : '10'
        Db_page_size                   : 16384
        Log_page_size                  : 16384
        Shutdown                       : 0
        Next_trans_id                  : 15
        Num_avg_trans                  : 3
        Num_avg_locks                  : 30
        Num_active_log_pages           : 1279
        Db_charset                     : 3
        First_active_log_page          : 0
        Current_append                 : '(101|8016)'
        Checkpoint                     : '(101|7936)'
        Next_archive_page_id           : 0
        Active_physical_page_id        : 1
        Next_archive_num               : 0
        Last_archive_num_for_syscrashes: -1
        Last_deleted_archive_num       : -1
        Backup_lsa_level0              : '(-1|-1)'
        Backup_lsa_level1              : '(-1|-1)'
        Backup_lsa_level2              : '(-1|-1)'
        Log_prefix                     : 'mvccdb'
        Has_logging_been_skipped       : 0
        Perm_status                    : 'LOG_PSTAT_CLEAR'
        Backup_info_level0             : 'time: N/A'
        Backup_info_level1             : 'time: N/A'
        Backup_info_level2             : 'time: N/A'
        Ha_server_state                : 'idle'
        Ha_file                        : 'UNKNOWN'
        Eof_lsa                        : '(101|8016)'
        Smallest_lsa_at_last_checkpoint: '(101|7936)'
        Next_mvcc_id                   : 4
        Mvcc_op_log_lsa                : '(-1|-1)'
        Last_block_oldest_mvcc_id      : NULL
        Last_block_newest_mvcc_id      : NULL
SHOW ARCHIVE LOG HEADER

It shows the header information of an archive log file.

SHOW ARCHIVE LOG HEADER OF file_name;

This query has the following columns:

Column name Type Description
Volume_id INT Identifier of log volume
Magic_symbol VARCHAR(32) Magic value for file/magic Unix utility
Magic_symbol_location INT Magic symbol location from log page
Creation_time DATETIME Database creation time
Next_trans_id BIGINT Next transaction identifier
Num_pages INT Number of pages in the archive log
First_page_id BIGINT Logical page id at physical location 1 in archive log
Archive_num INT The archive log number

The following shows the examples of this syntax.

-- csql> ;line on
SHOW ARCHIVE LOG HEADER OF 'demodb_lgar001';
<00001> Volume_id            : -20
        Magic_symbol         : 'CUBRID/LogArchive'
        Magic_symbol_location: 16
        Creation_time        : 04:42:28.000 PM 12/11/2013
        Next_trans_id        : 22695
        Num_pages            : 1278
        First_page_id        : 1278
        Archive_num          : 1
SHOW HEAP HEADER

It shows shows the header page of the table.

SHOW [ALL] HEAP HEADER OF table_name;
  • ALL: If "ALL" is given in syntax in the partition table, the basic table and its partitioned tables are shown.

This query has the following columns:

Column name Type Description
Class_name VARCHAR(256) Table name
Class_oid VARCHAR(64) Format: (volid|pageid|slotid)
Volume_id INT Volume identifier where the file reside
File_id INT File identifier
Header_page_id INT First page identifier (the header page)
Overflow_vfid VARCHAR(64) Overflow file identifier (if any)
Next_vpid VARCHAR(64) Next page (i.e., the 2nd page of heap file)
Unfill_space INT Stop inserting when page has run below this. leave it for updates
Estimates_num_pages BIGINT Estimation of number of heap pages.
Estimates_num_recs BIGINT Estimation of number of objects in heap
Estimates_avg_rec_len INT Estimation total length of records
Estimates_num_high_best INT Number of pages in the best array that we believe have at least HEAP_DROP_FREE_SPACE. When this number goes to zero and there are at least other HEAP_NUM_BEST_SPACESTATS best pages, we look for them
Estimates_num_others_high_best INT Total of other believed known best pages, which are not included in the best array and we believe they have at least HEAP_DROP_FREE_SPACE
Estimates_head INT Head of best circular array
Estimates_best_list VARCHAR(512) Format: '((best[0].vpid.volid|best[0].vpid.pageid), best[0].freespace), ... , ((best[9].vpid.volid|best[9].vpid.pageid), best[9].freespace)'
Estimates_num_second_best INT Number of second best hints. The hints are in "second_best" array. They are used when finding new best pages.
Estimates_head_second_best INT Index of head of second best hints. A new second best hint will be stored on this index.
Estimates_num_substitutions INT Number of page substitutions. This will be used to insert a new second best page into second best hints.
Estimates_second_best_list VARCHAR(512) Format: '(second_best[0].vpid.volid|second_best[0].vpid.pageid), ... , (second_best[9].vpid.volid|second_best[9].vpid.pageid)'
Estimates_last_vpid VARCHAR(64) Format: '(volid|pageid)'
Estimates_full_search_vpid VARCHAR(64) Format: '(volid|pageid)'

The following shows the examples of this syntax.

-- csql> ;line on
SHOW HEAP HEADER OF athlete;
<00001> Class_name                    : 'athlete'
        Class_oid                     : '(0|463|8)'
        Volume_id                     : 0
        File_id                       : 147
        Header_page_id                : 590
        Overflow_vfid                 : '(-1|-1)'
        Next_vpid                     : '(0|591)'
        Unfill_space                  : 1635
        Estimates_num_pages           : 27
        Estimates_num_recs            : 6677
        Estimates_avg_rec_len         : 54
        Estimates_num_high_best       : 1
        Estimates_num_others_high_best: 0
        Estimates_head                : 0
        Estimates_best_list           : '((0|826), 14516), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1),0), ((-1|-1), 0)'
        Estimates_num_second_best     : 0
        Estimates_head_second_best    : 0
        Estimates_tail_second_best    : 0
        Estimates_num_substitutions   : 0
        Estimates_second_best_list    : '(-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1)'
        Estimates_last_vpid           : '(0|826)'
        Estimates_full_search_vpid    : '(0|590)'
CREATE TABLE participant2 (
    host_year INT,
    nation CHAR(3),
    gold INT,
    silver INT,
    bronze INT
)
PARTITION BY RANGE (host_year) (
    PARTITION before_2000 VALUES LESS THAN (2000),
    PARTITION before_2008 VALUES LESS THAN (2008)
);
SHOW ALL HEAP HEADER OF participant2;
<00001> Class_name                    : 'participant2'
        Class_oid                     : '(0|467|6)'
        Volume_id                     : 0
        File_id                       : 374
        Header_page_id                : 940
        Overflow_vfid                 : '(-1|-1)'
        Next_vpid                     : '(-1|-1)'
        Unfill_space                  : 1635
        Estimates_num_pages           : 1
        Estimates_num_recs            : 0
        Estimates_avg_rec_len         : 0
        Estimates_num_high_best       : 1
        Estimates_num_others_high_best: 0
        Estimates_head                : 1
        Estimates_best_list           : '((0|940), 16308), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0)'
        Estimates_num_second_best     : 0
        Estimates_head_second_best    : 0
        Estimates_tail_second_best    : 0
        Estimates_num_substitutions   : 0
        Estimates_second_best_list    : '(-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1)'
        Estimates_last_vpid           : '(0|940)'
        Estimates_full_search_vpid    : '(0|940)'
<00002> Class_name                    : 'participant2__p__before_2000'
        Class_oid                     : '(0|467|7)'
        Volume_id                     : 0
        File_id                       : 376
        Header_page_id                : 950
        Overflow_vfid                 : '(-1|-1)'
        Next_vpid                     : '(-1|-1)'
        Unfill_space                  : 1635
        Estimates_num_pages           : 1
        Estimates_num_recs            : 0
        Estimates_avg_rec_len         : 0
        Estimates_num_high_best       : 1
        Estimates_num_others_high_best: 0
        Estimates_head                : 1
        Estimates_best_list           : '((0|950), 16308), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0)'
        Estimates_num_second_best     : 0
        Estimates_head_second_best    : 0
        Estimates_tail_second_best    : 0
        Estimates_num_substitutions   : 0
        Estimates_second_best_list    : '(-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1)'
        Estimates_last_vpid           : '(0|950)'
        Estimates_full_search_vpid    : '(0|950)'
<00003> Class_name                    : 'participant2__p__before_2008'
        Class_oid                     : '(0|467|8)'
        Volume_id                     : 0
        File_id                       : 378
        Header_page_id                : 960
        Overflow_vfid                 : '(-1|-1)'
        Next_vpid                     : '(-1|-1)'
        Unfill_space                  : 1635
        Estimates_num_pages           : 1
        Estimates_num_recs            : 0
        Estimates_avg_rec_len         : 0
        Estimates_num_high_best       : 1
        Estimates_num_others_high_best: 0
        Estimates_head                : 1
        Estimates_best_list           : '((0|960), 16308), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0)'
        Estimates_num_second_best     : 0
        Estimates_head_second_best    : 0
        Estimates_tail_second_best    : 0
        Estimates_num_substitutions   : 0
        Estimates_second_best_list    : '(-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1)'
        Estimates_last_vpid           : '(0|960)'
        Estimates_full_search_vpid    : '(0|960)'
SHOW HEAP HEADER OF participant2__p__before_2008;
<00001> Class_name                    : 'participant2__p__before_2008'
        Class_oid                     : '(0|467|8)'
        Volume_id                     : 0
        File_id                       : 378
        Header_page_id                : 960
        Overflow_vfid                 : '(-1|-1)'
        Next_vpid                     : '(-1|-1)'
        Unfill_space                  : 1635
        Estimates_num_pages           : 1
        Estimates_num_recs            : 0
        Estimates_avg_rec_len         : 0
        Estimates_num_high_best       : 1
        Estimates_num_others_high_best: 0
        Estimates_head                : 1
        Estimates_best_list           : '((0|960), 16308), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0), ((-1|-1), 0)'
        Estimates_num_second_best     : 0
        Estimates_head_second_best    : 0
        Estimates_tail_second_best    : 0
        Estimates_num_substitutions   : 0
        Estimates_second_best_list    : '(-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1), (-1|-1)'
        Estimates_last_vpid           : '(0|960)'
        Estimates_full_search_vpid    : '(0|960)'
SHOW HEAP CAPACITY

It shows the capacity of the table.

SHOW [ALL] HEAP CAPACITY OF table_name;
  • ALL: If "all" is given in syntax, the basic table and its partition table(s) is shown.

This query has the following columns:

Column name Type Description
Table_name VARCHAR(256) Table name
Class_oid VARCHAR(64) Heap file descriptor
Volume_id INT Volume identifier where the file reside
File_id INT File identifier
Header_page_id INT First page identifier (the header page)
Num_recs BIGINT Total Number of objects
Num_relocated_recs BIGINT Number of relocated records
Num_overflowed_recs BIGINT Number of big records
Num_pages BIGINT Total number of heap pages
Avg_rec_len INT Average object length
Avg_free_space_per_page INT Average free space per page
Avg_free_space_per_page_without_last_page INT Average free space per page without taking in consideration last page
Avg_overhead_per_page INT Average overhead per page
Repr_id INT Currently cached catalog column info
Num_total_attrs INT total number of columns
Num_fixed_width_attrs INT Number of the fixed width columns
Num_variable_width_attrs INT Number of variable width columns
Num_shared_attrs INT Number of shared columns
Num_class_attrs INT Number of table columns
Total_size_fixed_width_attrs INT Total size of the fixed width columns

The following shows the examples of this syntax.

-- csql> ;line on
SHOW HEAP CAPACITY OF athlete;
<00001> Table_name                              : 'athlete'
        Class_oid                               : '(0|463|8)'
        Volume_id                               : 0
        File_id                                 : 147
        Header_page_id                          : 590
        Num_recs                                : 6677
        Num_relocated_recs                      : 0
        Num_overflowed_recs                     : 0
        Num_pages                               : 27
        Avg_rec_len                             : 53
        Avg_free_space_per_page                 : 2139
        Avg_free_space_per_page_except_last_page: 1663
        Avg_overhead_per_page                   : 993
        Repr_id                                 : 1
        Num_total_attrs                         : 5
        Num_fixed_width_attrs                   : 3
        Num_variable_width_attrs                : 2
        Num_shared_attrs                        : 0
        Num_class_attrs                         : 0
        Total_size_fixed_width_attrs            : 8
SHOW ALL HEAP CAPACITY OF participant2;
<00001> Table_name                              : 'participant2'
        Class_oid                               : '(0|467|6)'
        Volume_id                               : 0
        File_id                                 : 374
        Header_page_id                          : 940
        Num_recs                                : 0
        Num_relocated_recs                      : 0
        Num_overflowed_recs                     : 0
        Num_pages                               : 1
        Avg_rec_len                             : 0
        Avg_free_space_per_page                 : 16016
        Avg_free_space_per_page_except_last_page: 0
        Avg_overhead_per_page                   : 4
        Repr_id                                 : 1
        Num_total_attrs                         : 5
        Num_fixed_width_attrs                   : 5
        Num_variable_width_attrs                : 0
        Num_shared_attrs                        : 0
        Num_class_attrs                         : 0
        Total_size_fixed_width_attrs            : 20
<00002> Table_name                              : 'participant2__p__before_2000'
        Class_oid                               : '(0|467|7)'
        Volume_id                               : 0
        File_id                                 : 376
        Header_page_id                          : 950
        Num_recs                                : 0
        Num_relocated_recs                      : 0
        Num_overflowed_recs                     : 0
        Num_pages                               : 1
        Avg_rec_len                             : 0
        Avg_free_space_per_page                 : 16016
        Avg_free_space_per_page_except_last_page: 0
        Avg_overhead_per_page                   : 4
        Repr_id                                 : 1
        Num_total_attrs                         : 5
        Num_fixed_width_attrs                   : 5
        Num_variable_width_attrs                : 0
        Num_shared_attrs                        : 0
        Num_class_attrs                         : 0
        Total_size_fixed_width_attrs            : 20
<00003> Table_name                              : 'participant2__p__before_2008'
        Class_oid                               : '(0|467|8)'
        Volume_id                               : 0
        File_id                                 : 378
        Header_page_id                          : 960
        Num_recs                                : 0
        Num_relocated_recs                      : 0
        Num_overflowed_recs                     : 0
        Num_pages                               : 1
        Avg_rec_len                             : 0
        Avg_free_space_per_page                 : 16016
        Avg_free_space_per_page_except_last_page: 0
        Avg_overhead_per_page                   : 4
        Repr_id                                 : 1
        Num_total_attrs                         : 5
        Num_fixed_width_attrs                   : 5
        Num_variable_width_attrs                : 0
        Num_shared_attrs                        : 0
        Num_class_attrs                         : 0
        Total_size_fixed_width_attrs            : 20
SHOW SLOTTED PAGE HEADER

It shows the header information of specified slotted page.

SHOW SLOTTED PAGE HEADER { WHERE|OF } VOLUME = volume_num AND PAGE = page_num;

This query has the following columns:

Column name Type Description
Volume_id INT Volume id of the page
Page_id INT page id of the page
Num_slots INT Number of allocated slots for the page
Num_records INT Number of records on page
Anchor_type VARCHAR(32) One of flowing: ANCHORED, ANCHORED_DONT_REUSE_SLOTS, UNANCHORED_ANY_SEQUENCE, UNANCHORED_KEEP_SEQUENCE
Alignment VARCHAR(8) Alignment for records, one of flowing: CHAR, SHORT, INT, DOUBLE
Total_free_area INT Total free space on page
Contiguous_free_area INT Contiguous free space on page
Free_space_offset INT Byte offset from the beginning of the page to the first free byte area on the page
Need_update_best_hint INT True if saving is need for recovery (undo)
Is_saving INT True if we should update best pages hint for this page.
Flags INT Flag value of the page

The following shows the examples of this syntax.

-- csql> ;line on
SHOW SLOTTED PAGE HEADER OF VOLUME=0 AND PAGE=140;
<00001> Volume_id            : 0
        Page_id              : 140
        Num_slots            : 3
        Num_records          : 3
        Anchor_type          : 'ANCHORED_DONT_REUSE_SLOTS'
        Alignment            : 'INT'
        Total_free_area      : 15880
        Contiguous_free_area : 15880
        Free_space_offset    : 460
        Need_update_best_hint: 1
        Is_saving            : 0
        Flags                : 0
SHOW SLOTTED PAGE SLOTS

It shows the information of all slots in the specified slotted page.

SHOW SLOTTED PAGE SLOTS { WHERE|OF } VOLUME = volume_num AND PAGE = page_num;

This query has the following columns:

Column name Type Description
Volume_id INT Volume id of the page
Page_id INT Page id of the page
Slot_id INT The slot id
Offset INT Byte offset from the beginning of the page to the beginning of the record
Type VARCHAR(32) Record type, one of flowing: REC_UNKNOWN, REC_ASSIGN_ADDRESS, REC_HOME, REC_NEWHOME, REC_RELOCATION, REC_BIGONE, REC_MARKDELETED, REC_DELETED_WILL_REUSE
Length INT Length of record
Waste INT Whether or not wasted

The following shows the examples of this syntax.

-- csql> ;line on
SHOW SLOTTED PAGE HEADER OF VOLUME=0 AND PAGE=140;
<00001> Volume_id: 0
        Page_id  : 140
        Slot_id  : 0
        Offset   : 40
        Type     : 'HOME'
        Length   : 292
        Waste    : 0
<00002> Volume_id: 0
        Page_id  : 140
        Slot_id  : 1
        Offset   : 332
        Type     : 'HOME'
        Length   : 64
        Waste    : 0
<00003> Volume_id: 0
        Page_id  : 140
        Slot_id  : 2
        Offset   : 396
        Type     : 'HOME'
        Length   : 64
        Waste    : 0
SHOW INDEX HEADER

It shows the index header page of the index of the table.

SHOW INDEX HEADER OF table_name.index_name;

If ALL keyword is used and an index name is omitted, it shows the entire headers of the indexes of the table.

SHOW ALL INDEXES HEADER OF table_name;

This query has the following columns:

Column name Type Description
Table_name VARCHAR(256) Table name
Index_name VARCHAR(256) Index name
Btid VARCHAR(64) BTID (volid|fileid|root_pageid)
Node_type VARCHAR(16) 'LEAF' or 'NON_LEAF'
Max_key_len INT Maximum key length for the subtree
Num_oids INT Number of OIDs stored in the Btree
Num_nulls INT Number of NULLs (they aren't stored)
Num_keys INT Number of unique keys in the Btree
Topclass_oid VARCHAR(64) Topclass oid or NULL OID (non unique index)(volid|pageid|slotid)
Unique INT Unique or non-unique
Overflow_vfid VARCHAR(32) VFID (volid|fileid)
Key_type VARCHAR(256) Type name
Columns VARCHAR(256) the list of columns which consists of the index

The following shows the examples of this syntax.

-- Prepare test environment
CREATE TABLE tbl1(a INT, b VARCHAR(5));
CREATE INDEX index_ab ON tbl1(a ASC, b DESC);
-- csql> ;line on
SHOW INDEX HEADER OF tbl1.index_ab;
<00001> Table_name   : 'tbl1'
        Index_name   : 'index_a'
        Btid         : '(0|378|950)'
        Node_type    : 'LEAF'
        Max_key_len  : 0
        Num_oids     : -1
        Num_nulls    : -1
        Num_keys     : -1
        Topclass_oid : '(0|469|4)'
        Unique       : 0
        Overflow_vfid: '(-1|-1)'
        Key_type     : 'midxkey(integer,character varying(5))'
        Columns      : 'a,b DESC'
SHOW INDEX CAPACITY

It shows the index capacity of the index of the table.

SHOW INDEX CAPACITY OF table_name.index_name;

If ALL keyword is used and an index name is omitted, it shows the entire capacity of the indexes of the table.

SHOW ALL INDEXES CAPACITY OF table_name;

This query has the following columns:

Column name Type Description
Table_name VARCHAR(256) Table name
Index_name VARCHAR(256) Index name
Btid VARCHAR(64) BTID (volid|fileid|root_pageid)
Num_distinct_key INT Distinct key count (in leaf pages)
Total_value INT Total number of values stored in tree
Avg_num_value_per_key INT Average number of values (OIDs) per key
Num_leaf_page INT Leaf page count
Num_non_leaf_page INT NonLeaf page count
Num_total_page INT Total page count
Height INT Height of the tree
Avg_key_len INT Average key length
Avg_rec_len INT Average page record length
Total_space VARCHAR(64) Total space occupied by index
Total_used_space VARCHAR(64) Total used space in index
Total_free_space VARCHAR(64) Total free space in index
Avg_num_page_key INT Average page key count (in leaf pages)
Avg_page_free_space VARCHAR(64) Average page free space

The following shows the examples of this syntax.

-- Prepare test environment
CREATE TABLE tbl1(a INT, b VARCHAR(5));
CREATE INDEX index_a ON tbl1(a ASC);
CREATE INDEX index_b ON tbl1(b ASC);
-- csql> ;line on
SHOW INDEX CAPACITY OF tbl1.index_a;
<00001> Table_name           : 'tbl1'
        Index_name           : 'index_a'
        Btid                 : '(0|378|950)'
        Num_distinct_key     : 0
        Total_value          : 0
        Avg_num_value_per_key: 0
        Num_leaf_page        : 1
        Num_non_leaf_page    : 0
        Num_total_page       : 1
        Height               : 1
        Avg_key_len          : 0
        Avg_rec_len          : 0
        Total_space          : '16.0K'
        Total_used_space     : '116.0B'
        Total_free_space     : '15.9K'
        Avg_num_page_key     : 0
        Avg_page_free_space  : '15.9K'
SHOW ALL INDEXES CAPACITY OF tbl1;
<00001> Table_name           : 'tbl1'
        Index_name           : 'index_a'
        Btid                 : '(0|378|950)'
        Num_distinct_key     : 0
        Total_value          : 0
        Avg_num_value_per_key: 0
        Num_leaf_page        : 1
        Num_non_leaf_page    : 0
        Num_total_page       : 1
        Height               : 1
        Avg_key_len          : 0
        Avg_rec_len          : 0
        Total_space          : '16.0K'
        Total_used_space     : '116.0B'
        Total_free_space     : '15.9K'
        Avg_num_page_key     : 0
        Avg_page_free_space  : '15.9K'
<00002> Table_name           : 'tbl1'
        Index_name           : 'index_b'
        Btid                 : '(0|381|960)'
        Num_distinct_key     : 0
        Total_value          : 0
        Avg_num_value_per_key: 0
        Num_leaf_page        : 1
        Num_non_leaf_page    : 0
        Num_total_page       : 1
        Height               : 1
        Avg_key_len          : 0
        Avg_rec_len          : 0
        Total_space          : '16.0K'
        Total_used_space     : '120.0B'
        Total_free_space     : '15.9K'
        Avg_num_page_key     : 0
        Avg_page_free_space  : '15.9K'
SHOW CRITICAL SECTIONS

Total critical section (hereafter CS) information of a database is shown.

SHOW CRITICAL SECTIONS;

This query has the following columns:

Column name Type Description
Index INT The index of CS
Name VARCHAR(32) The name of CS
Num_holders VARCHAR(16) The number of CS holders. This has one of these values: 'N readers', '1 writer', 'none'
Num_waiting_readers INT The number of waiting readers
Num_waiting_writers INT The number of waiting writers
Owner_thread_index INT The thread index of CS owner writer, NULL if no owner
Owner_tran_index INT Transaction index of CS owner writer, NULL if no owner
Total_enter_count BIGINT Total count of enterers
Total_waiter_count BIGINT Total count of waiters
Waiting_promoter_thread_index INT The thread index of waiting promoter, NULL if no waiting promoter
Max_waiting_msecs NUMERIC(10,3) Maximum waiting time (millisecond)
Total_waiting_msecs NUMERIC(10,3) Total waiting time (millisecond)

The following shows the examples of this syntax.

SHOW CRITICAL SECTIONS;
Index  Name                  Num_holders           Num_waiting_readers  Num_waiting_writers  Owner_thread_index  Owner_tran_index     Total_enter_count    Total_waiter_count  Waiting_promoter_thread_index  Max_waiting_msecs     Total_waiting_msecs
============================================================================================================================================================================================================================================================
    0  'ER_LOG_FILE'         'none'                                  0                    0                NULL              NULL                   217                     0                           NULL  0.000                 0.000
    1  'ER_MSG_CACHE'        'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    2  'WFG'                 'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    3  'LOG'                 'none'                                  0                    0                NULL              NULL                    11                     0                           NULL  0.000                 0.000
    4  'LOCATOR_CLASSNAME_TABLE'  'none'                                  0                    0                NULL              NULL                    33                     0                           NULL  0.000                 0.000
    5  'FILE_NEWFILE'        'none'                                  0                    0                NULL              NULL                    12                     0                           NULL  0.000                 0.000
    6  'QPROC_QUERY_TABLE'   'none'                                  0                    0                NULL              NULL                     3                     0                           NULL  0.000                 0.000
    7  'QPROC_QFILE_PGCNT'   'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    8  'QPROC_XASL_CACHE'    'none'                                  0                    0                NULL              NULL                     5                     0                           NULL  0.000                 0.000
    9  'QPROC_LIST_CACHE'    'none'                                  0                    0                NULL              NULL                     1                     0                           NULL  0.000                 0.000
    10  'BOOT_SR_DBPARM'      'none'                                  0                    0                NULL              NULL                     3                     0                           NULL  0.000                 0.000
    11  'DISK_REFRESH_GOODVOL'  'none'                                  0                    0                NULL              NULL                     6                     0                           NULL  0.000                 0.000
    12  'CNV_FMT_LEXER'       'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    13  'HEAP_CHNGUESS'       'none'                                  0                    0                NULL              NULL                    10                     0                           NULL  0.000                 0.000
    14  'SPAGE_SAVESPACE'     'none'                                  0                    0                NULL              NULL                     1                     0                           NULL  0.000                 0.000
    15  'TRAN_TABLE'          'none'                                  0                    0                NULL              NULL                     7                     0                           NULL  0.000                 0.000
    16  'CT_OID_TABLE'        'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    17  'SCANID_BITMAP'       'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    18  'LOG_FLUSH'           'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    19  'HA_SERVER_STATE'     'none'                                  0                    0                NULL              NULL                     2                     0                           NULL  0.000                 0.000
    20  'COMPACTDB_ONE_INSTANCE'  'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    21  'SESSION_STATE'       'none'                                  0                    0                NULL              NULL                     3                     0                           NULL  0.000                 0.000
    22  'ACL'                 'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    23  'QPROC_FILTER_PRED_CACHE'  'none'                                  0                    0                NULL              NULL                     1                     0                           NULL  0.000                 0.000
    24  'PARTITION_CACHE'     'none'                                  0                    0                NULL              NULL                     1                     0                           NULL  0.000                 0.000
    25  'EVENT_LOG_FILE'      'none'                                  0                    0                NULL              NULL                     0                     0                           NULL  0.000                 0.000
    26  'ACCESS_STATUS'       'none'                                  0                    0                NULL              NULL                     1                     0                           NULL  0.000                 0.000
SHOW TRANSACTION TABLES

It shows internal information of transaction descriptors which is internal data structure to manage each transaction. It only shows valid transactions and the result may not be a consistent snapshot of a transaction descriptor.

SHOW { TRAN | TRANSACTION } TABLES [ WHERE EXPR ];

This query has the following columns:

Column name Type Description
Tran_index INT Index on the transaction table or NULL for unassigned transaction descriptor slot
Tran_id INT Transaction Identifier
Is_loose_end INT 0 for Ordinary transactions, 1 for loose-end transactions
State VARCHAR(64) State of the transaction. Either one of the followings: 'TRAN_RECOVERY', 'TRAN_ACTIVE', 'TRAN_UNACTIVE_COMMITTED', 'TRAN_UNACTIVE_WILL_COMMIT', 'TRAN_UNACTIVE_COMMITTED_WITH_POSTPONE', 'TRAN_UNACTIVE_ABORTED', 'TRAN_UNACTIVE_UNILATERALLY_ABORTED', 'TRAN_UNACTIVE_2PC_PREPARE', 'TRAN_UNACTIVE_2PC_COLLECTING_PARTICIPANT_VOTES', 'TRAN_UNACTIVE_2PC_ABORT_DECISION', 'TRAN_UNACTIVE_2PC_COMMIT_DECISION', 'TRAN_UNACTIVE_COMMITTED_INFORMING_PARTICIPANTS', 'TRAN_UNACTIVE_ABORTED_INFORMING_PARTICIPANTS','TRAN_STATE_UNKNOWN'
Isolation VARCHAR(64) Isolation level of the transaction. Either one of the followings: 'SERIALIZABLE', 'REPEATABLE READ', 'COMMITTED READ', 'TRAN_UNKNOWN_ISOLATION'
Wait_msecs INT Wait until this number of milliseconds for locks.
Head_lsa VARCHAR(64) First log address of transaction.
Tail_lsa VARCHAR(64) Last log record address of transaction.
Undo_next_lsa VARCHAR(64) Next log record address of transaction for UNDO purposes.
Postpone_next_lsa VARCHAR(64) Next address of a postpone record to be executed.
Savepoint_lsa VARCHAR(64) Address of last save-point.
Topop_lsa VARCHAR(64) Address of last top operation.
Tail_top_result_lsa VARCHAR(64) Address of last partial abort/commit.
Client_id INT Unique identifier of client application bind to transaction.
Client_type VARCHAR(40) Type of the client. Either one of the followings: 'SYSTEM_INTERNAL', 'DEFAULT', 'CSQL', 'READ_ONLY_CSQL', 'BROKER', 'READ_ONLY_BROKER', 'SLAVE_ONLY_BROKER', 'ADMIN_UTILITY', 'ADMIN_CSQL', 'LOG_COPIER', 'LOG_APPLIER', 'RW_BROKER_REPLICA_ONLY', 'RO_BROKER_REPLICA_ONLY', 'SO_BROKER_REPLICA_ONLY', 'ADMIN_CSQL_WOS', 'UNKNOWN'
Client_info VARCHAR(256) General information of client application.
Client_db_user VARCHAR(40) Current login database account from client application.
Client_program VARCHAR(256) Program name of client application.
Client_login_user VARCHAR(16) Current login user of OS which running the client application.
Client_host VARCHAR(64) Host name of client application.
Client_pid INT Process id of client application.
Topop_depth INT Depth of nested top operation.
Num_unique_btrees INT Number of unique btrees contained in unique_stat_info array.
Max_unique_btrees INT Size of unique_stat_info_array.
Interrupt INT The flag of whether or not interrupt current transaction. 0 for No, 1 for Yes.
Num_transient_classnames INT Number of transient classnames by this transaction.
Repl_max_records INT Capacity of replication record array.
Repl_records VARCHAR(20) Replication record buffer array, display address pointer as 0x12345678 or NULL for 0x00000000.
Repl_current_index INT Current position of replication record in the array.
Repl_append_index INT Current position of appended record in the array.
Repl_flush_marked_index INT Index of flush marked replication record at first.
Repl_insert_lsa VARCHAR(64) Insert Replication target LSA.
Repl_update_lsa VARCHAR(64) Update Replication target LSA.
First_save_entry VARCHAR(20) First save entry for the transaction, display address pointer as 0x12345678 or NULL for 0x00000000.
Tran_unique_stats VARCHAR(20) Local statistical info for multiple row. display address pointer as 0x12345678 or NULL for 0x00000000.
Modified_class_list VARCHAR(20) List of dirty classes, display address pointer as 0x12345678 or NULL for 0x00000000.
Num_new_files INT Number of new files created.
Num_new_temp_files INT Number of new temp files created.
Waiting_for_res VARCHAR(20) Waiting resource. Just display address pointer as 0x12345678 or NULL for 0x00000000.
Has_deadlock_priority INT Whether or not have deadlock priority. 0 for No, 1 for Yes.
Suppress_replication INT Suppress writing replication logs when flag is set.
Query_timeout DATETIME A query should be executed before query_timeout time or NULL for waiting until query complete.
Query_start_time DATETIME Current query start time or NULL for query completed.
Tran_start_time DATETIME Current transaction start time or NULL for transaction completed.
Xasl_id VARCHAR(64) vpid:(volid|pageid),vfid:(volid|pageid) or NULL for query completed.
Disable_modifications INT Disable modification if greater than zero.
Abort_reason VARCHAR(40) Reason of transaction aborted. Either one of the followings: 'NORMAL', 'ABORT_DUE_TO_DEADLOCK', 'ABORT_DUE_ROLLBACK_ON_ESCALATION'

The following shows the examples of the statement.

SHOW TRAN TABLES WHERE CLIENT_TYPE = 'CSQL';
=== <Result of SELECT Command in Line 1> ===

<00001> Tran_index              : 1
        Tran_id                 : 58
        Is_loose_end            : 0
        State                   : 'ACTIVE'
        Isolation               : 'COMMITTED READ'
        Wait_msecs              : -1
        Head_lsa                : '(-1|-1)'
        Tail_lsa                : '(-1|-1)'
        Undo_next_lsa           : '(-1|-1)'
        Postpone_next_lsa       : '(-1|-1)'
        Savepoint_lsa           : '(-1|-1)'
        Topop_lsa               : '(-1|-1)'
        Tail_top_result_lsa     : '(-1|-1)'
        Client_id               : 108
        Client_type             : 'CSQL'
        Client_info             : ''
        Client_db_user          : 'PUBLIC'
        Client_program          : 'csql'
        Client_login_user       : 'cubrid'
        Client_host             : 'cubrid001'
        Client_pid              : 13190
        Topop_depth             : 0
        Num_unique_btrees       : 0
        Max_unique_btrees       : 0
        Interrupt               : 0
        Num_transient_classnames: 0
        Repl_max_records        : 0
        Repl_records            : NULL
        Repl_current_index      : 0
        Repl_append_index       : -1
        Repl_flush_marked_index : -1
        Repl_insert_lsa         : '(-1|-1)'
        Repl_update_lsa         : '(-1|-1)'
        First_save_entry        : NULL
        Tran_unique_stats       : NULL
        Modified_class_list     : NULL
        Num_new_files           : 1
        Num_new_temp_files      : 0
        Waiting_for_res         : NULL
        Has_deadlock_priority   : 0
        Suppress_replication    : 0
        Query_timeout           : NULL
        Query_start_time        : 03:10:11.425 PM 02/04/2016
        Tran_start_time         : 03:10:11.425 PM 02/04/2016
        Xasl_id                 : 'vpid: (32766|50), vfid: (32766|43)'
        Disable_modifications   : 0
        Abort_reason            : 'NORMAL'
SHOW THREADS

It shows internal information of each thread. The results are sorted by "Index" column with ascending order and may not be a consistent snapshot of thread entries. The statement under SA MODE shows an empty result.

SHOW THREADS [ WHERE EXPR ];

This query has the following columns:

Column name Type Description
Index INT Thread entry index.
Jobq_index INT Job queue index only for worker threads. NULL for non-worker threads.
Thread_id BIGINT Thread id.
Tran_index INT Transaction index to which this thread belongs. If no related tran index, NULL.
Type VARCHAR(8) Thread type. Either one of the followings: 'MASTER', 'SERVER', 'WORKER', 'DAEMON', 'VACUUM_MASTER', 'VACUUM_WORKER', 'NONE', 'UNKNOWN'.
Status VARCHAR(8) Thread status. Either one of the followings: 'DEAD', 'FREE', 'RUN', 'WAIT', 'CHECK'.
Resume_status VARCHAR(32) Resume status. Either one of the followings: 'RESUME_NONE', 'RESUME_DUE_TO_INTERRUPT', 'RESUME_DUE_TO_SHUTDOWN', 'PGBUF_SUSPENDED', 'PGBUF_RESUMED', 'JOB_QUEUE_SUSPENDED', 'JOB_QUEUE_RESUMED', 'CSECT_READER_SUSPENDED', 'CSECT_READER_RESUMED', 'CSECT_WRITER_SUSPENDED', 'CSECT_WRITER_RESUMED', 'CSECT_PROMOTER_SUSPENDED', 'CSECT_PROMOTER_RESUMED', 'CSS_QUEUE_SUSPENDED', 'CSS_QUEUE_RESUMED', 'QMGR_ACTIVE_QRY_SUSPENDED', 'QMGR_ACTIVE_QRY_RESUMED', 'QMGR_MEMBUF_PAGE_SUSPENDED', 'QMGR_MEMBUF_PAGE_RESUMED', 'HEAP_CLSREPR_SUSPENDED', 'HEAP_CLSREPR_RESUMED', 'LOCK_SUSPENDED', 'LOCK_RESUMED', 'LOGWR_SUSPENDED', 'LOGWR_RESUMED'
Net_request VARCHAR(64) The net request name in net_requests array, such as: 'LC_ASSIGN_OID'. If not request name, shows NULL
Conn_client_id INT Client id whom this thread is responding, if no client id, shows NULL
Conn_request_id INT Request id which this thread is processing, if no request id, shows NULL
Conn_index INT Connection index, if not connection index, shows NULL
Last_error_code INT Last error code
Last_error_msg VARCHAR(256) Last error message, if message length is more than 256, it will be truncated, If no error message, shows NULL
Private_heap_id VARCHAR(20) The address of id of thread private memory allocator, such as: 0x12345678. If no related heap id, shows NULL.
Query_entry VARCHAR(20) The address of the QMGR_QUERY_ENTRY*, such as: 0x12345678, if no related QMGR_QUERY_ENTRY, shows NULL.
Interrupted INT 0 or 1, is this request/transaction interrupted
Shutdown INT 0 or 1, is server going down?
Check_interrupt INT 0 or 1
Check_page_validation INT 0 or 1
Wait_for_latch_promote INT 0 or 1, whether this thread is waiting for latch promotion.
Lockwait_blocked_mode VARCHAR(24) Lockwait blocked mode. Either one of the followings: 'NULL_LOCK', 'IS_LOCK', 'S_LOCK', 'IS_LOCK', 'IX_LOCK', 'SIX_LOCK', 'X_LOCK', 'SCH_M_LOCK', 'UNKNOWN'
Lockwait_start_time DATETIME Start blocked time, if not in blocked state, shows NULL
Lockwait_msecs INT Time in milliseconds, if not in blocked state, shows NULL
Lockwait_state VARCHAR(24) The lock wait state such as: 'SUSPENDED', 'RESUMED', 'RESUMED_ABORTED_FIRST', 'RESUMED_ABORTED_OTHER', 'RESUMED_DEADLOCK_TIMEOUT', 'RESUMED_TIMEOUT', 'RESUMED_INTERRUPT'. If not in blocked state, shows NULL
Next_wait_thread_index INT The next wait thread index, if not exist, shows NULL
Next_tran_wait_thread_index INT The next wait thread index in lock manager, if not exist, shows NULL
Next_worker_thread_index INT The next worker thread index in css_Job_queue.worker_thrd_list, if not exist, shows NULL

The following shows the examples of the statement.

SHOW THREADS WHERE RESUME_STATUS != 'RESUME_NONE' AND STATUS != 'FREE';
=== <Result of SELECT Command in Line 1> ===
<00001> Index                      : 183
        Jobq_index                 : 3
        Thread_id                  : 140077788813056
        Tran_index                 : 3
        Type                       : 'WORKER'
        Status                     : 'RUN'
        Resume_status              : 'JOB_QUEUE_RESUMED'
        Net_request                : 'QM_QUERY_EXECUTE'
        Conn_client_id             : 108
        Conn_request_id            : 196635
        Conn_index                 : 3
        Last_error_code            : 0
        Last_error_msg             : NULL
        Private_heap_id            : '0x02b3de80'
        Query_entry                : '0x7f6638004cb0'
        Interrupted                : 0
        Shutdown                   : 0
        Check_interrupt            : 1
        Check_page_validation      : 1
        Wait_for_latch_promote     : 0
        Lockwait_blocked_mode      : NULL
        Lockwait_start_time        : NULL
        Lockwait_msecs             : NULL
        Lockwait_state             : NULL
        Next_wait_thread_index     : NULL
        Next_tran_wait_thread_index: NULL
        Next_worker_thread_index   : NULL
<00002> Index                      : 192
        Jobq_index                 : 2
        Thread_id                  : 140077779339008
        Tran_index                 : 2
        Type                       : 'WORKER'
        Status                     : 'WAIT'
        Resume_status              : 'LOCK_SUSPENDED'
        Net_request                : 'LC_FIND_LOCKHINT_CLASSOIDS'
        Conn_client_id             : 107
        Conn_request_id            : 131097
        Conn_index                 : 2
        Last_error_code            : 0
        Last_error_msg             : NULL
        Private_heap_id            : '0x02bcdf10'
        Query_entry                : NULL
        Interrupted                : 0
        Shutdown                   : 0
        Check_interrupt            : 1
        Check_page_validation      : 1
        Wait_for_latch_promote     : 0
        Lockwait_blocked_mode      : 'SCH_S_LOCK'
        Lockwait_start_time        : 10:47:45.000 AM 02/03/2016
        Lockwait_msecs             : -1
        Lockwait_state             : 'SUSPENDED'
        Next_wait_thread_index     : NULL
        Next_tran_wait_thread_index: NULL
        Next_worker_thread_index   : NULL
SHOW JOB QUEUES

It shows the status of job queue. The statement under SA MODE shows an empty result.

SHOW JOB QUEUES;

This query has the following columns:

Column name Type Description
Jobq_index INT The index of job queue
Num_total_workers INT Total number of work threads of the queue
Num_busy_workers INT The number of busy worker threads of the queue
Num_connection_workers INT The number of connection worker threads of the queue

System Catalog

You can easily get various schema information from the SQL statement by using the system catalog virtual class. For example, you can get the following schema information by using the catalog virtual class.

-- Classes that refer to the 'b_user' class
SELECT class_name
FROM db_attribute
WHERE domain_class_name = 'db_user';

-- The number of classes that the current user can access
SELECT COUNT(*)
FROM db_class;

-- Attribute of the 'db_user' class
SELECT attr_name, data_type
FROM db_attribute
WHERE class_name = 'db_user';
System Catalog Classes

To define a catalog virtual class, define a catalog class first. The figure below shows catalog classes to be added and their relationships. The arrows represent the reference relationship between classes, and the classes that start with an underline (_) are catalog classes.

_images/image9.png

Added catalog classes represent information about all classes, attributes and methods in the database. Catalog classes are made up of class composition hierarchy and designed to have OIDs of catalog class instances for cross reference.

_db_class

Represents class information. An index for class_name is created.

Attribute Name Data Type Description
class_of object A class object. Represents a meta information object for the class stored in the system.
class_name VARCHAR(255) Class name
class_type INTEGER 0 for a class, and 1 for a virtual class
is_system_class INTEGER 0 for a user-defined class, and 1 for a system class
owner db_user Class owner
inst_attr_count INTEGER The number of instance attributes
class_attr_count INTEGER The number of class attributes
shared_attr_count INTEGER The number of shared attributes
inst_meth_count INTEGER The number of instance methods
class_meth_count INTEGER The number of class methods
collation_id INTEGER Collation id
sub_classes SEQUENCE OF _db_class Class one level down
super_classes SEQUENCE OF _db_class Class one level up
inst_attrs SEQUENCE OF _db_attribute Instance attribute
class_attrs SEQUENCE OF _db_attribute Class attribute
shared_attrs SEQUENCE OF _db_attribute Shared attribute
inst_meths SEQUENCE OF _db_method Instance method
class_meths SEQUENCE OF _db_method Class method
meth_files SEQUENCE OF _db_methfile File path in which the function for the method is located
query_specs SEQUENCE OF _db_queryspec SQL definition statement for a virtual class
indexes SEQUENCE OF _db_index Index created in the class
comment VARCHAR(2048) Comment to describe the class
partition SEQUENCE of _db_partition Partition information

The following example shows how to retrieve all sub classes under the class owned by user 'PUBLIC' (for the child class female_event in the result, see the example in ADD SUPERCLASS Clause).

SELECT class_name, SEQUENCE(SELECT class_name FROM _db_class s WHERE s IN c.sub_classes)
FROM _db_class c
WHERE c.owner.name = 'PUBLIC' AND c.sub_classes IS NOT NULL;
  class_name            sequence((select class_name from _db_class s where s in c.sub_classes))
============================================
  'event'               {'female_event'}

Note

All examples of system catalog classes have been written in the csql utility. In this example, --no-auto-commit (inactive mode of auto-commit) and -u (specifying user DBA) options are used.

% csql --no-auto-commit -u dba demodb
_db_attribute

Represents attribute information. Indexes for class_of, attr_name and attr_type are created.

Attribute Name Data Type Description
class_of _db_class Class to which the attribute belongs
attr_name VARCHAR(255) Attribute name
attr_type INTEGER Type defined for the attribute. 0 for an instance attribute, 1 for a class attribute, and 2 for a shared attribute.
from_class_of _db_class If the attribute is inherited, the super class in which the attribute is defined is specified. Otherwise, NULL is specified.
from_attr_name VARCHAR(255) Inherited attribute. If an attribute name has changed to resolve a name conflict, the original name define in the super class is specified. Otherwise, NULL is specified.
def_order INTEGER Order of attributes in the class. Begins with 0. If the attribute is inherited, the order is the one defined in the super class. For example, if class y inherits attribute a from class x and a was first defined in x, def_order becomes 0.
data_type INTEGER Data type of the attribute. One of the values specified in the "Data Types Supported by CUBRID" table below.
default_value VARCHAR(255)

Default value. Stores as a character string regardless of data types. If there is no default value, NULL. If the default value is NULL, NULL is used.

If the data type is an object, 'volume id | page id | slot id' is used. If the data type is a collection, '{element 1, element 2, ... is used.

domains SEQUENCE OF _db_domain Domain information of the data type
is_nullable INTEGER 0 if a not null constraint is configured, and 1 otherwise.
comment VARCHAR(1024) Comment to describe the attribute.

Data Types Supported by CUBRID

Value Meaning Value Meaning
1 INTEGER 22 NUMERIC
2 FLOAT 23 BIT
3 DOUBLE 24 VARBIT
4 STRING 25 CHAR
5 OBJECT 31 BIGINT
6 SET 32 DATETIME
7 MULTISET 33 BLOB
8 SEQUENCE 34 CLOB
9 ELO 35 ENUM
10 TIME 36 TIMESTAMPTZ
11 TIMESTAMP 37 TIMESTAMPLTZ
12 DATE 38 DATETIMETZ
18 SHORT 39 DATETIMELTZ

Character Sets Supported by CUBRID

Value Meaning
0 US English - ASCII encoding
2 Binary
3 Latin 1 - ISO 8859 encoding
4 KSC 5601 1990 - EUC encoding
5 UTF8 - UTF8 encoding

The following example shows how to retrieve user classes (from_class_of.is_system_class = 0) among the ones owned by user 'PUBLIC'.'

SELECT class_of.class_name, attr_name
FROM _db_attribute
WHERE class_of.owner.name = 'PUBLIC' AND from_class_of.is_system_class = 0
ORDER BY 1, def_order;
class_of.class_name   attr_name
============================================
  'female_event'        'code'
  'female_event'        'sports'
  'female_event'        'name'
  'female_event'        'gender'
  'female_event'        'players'
_db_domain

Represents domain information. An index for object_of is created.

Attribute Name Data Type Description
object_of object Attribute that refers to the domain, which can be a method parameter or domain
data_type INTEGER Data type of the domain (a value in the "Value" column of the "Data Types Supported by CUBRID" table in _db_attribute)
prec INTEGER Precision of the data type. 0 is used if the precision is not specified.
scale INTEGER Scale of the data type. 0 is used if the scale is not specified.
class_of _db_class Domain class if the data type is an object, NULL otherwise.
code_set INTEGER Character set (value of table "character sets supported by CUBRID" in _db_attribute) if it is character data type. 0 otherwise.
collation_id INTEGER Collation id
enumeration SEQUENCE OF STRING String printed enumeration type definition
set_domains SEQUENCE OF _db_domain Domain information about the data type of collection element if it is collection data type. NULL otherwise.
_db_charset

Represents charset information.

Attribute Name Data type Description
charset_id INTEGER Charset ID
charset_name CHARACTER VARYING(32) Charset name
default_collation INTEGER Default collation ID
char_size INTEGER One character's byte size
_db_collation

The information on collation.

Attribute Name Data Type Description
coll_id INTEGER Collation ID
coll_name VARCHAR(32) Collation name
charset_id INTEGER Charset ID
built_in INTEGER Built-in or not while installing the product (0: Not built-in, 1: Built-in)
expansions INTEGER Expansion support (0: Not supported, 1: Supported)
contractions INTEGER Contraction support (0: Not supported, 1: Supported)
uca_strength INTEGER Weight strength
checksum VARCHAR(32) Checksum of a collation file
_db_method

Represents method information. Indexes for class_of and meth_name are created.

Attribute Name Data Type Description
class_of _db_class Class to which the method belongs
meth_type INTEGER Type of the method defined in the class. 0 for an instance method, and 1 for a class method.
from_class_of _db_class If the method is inherited, the super class in which it is defined is used otherwise NULL
from_meth_name VARCHAR(255) If the method is inherited and its name is changed to resolve a name conflict, the original name defined in the super class is used otherwise NULL
meth_name VARCHAR(255) Method name
signatures SEQUENCE OF _db_meth_sig C function executed when the method is called

The following example shows how to retrieve class methods of the class with a class method (c.class_meth_count > 0), among classes owned by user 'DBA.'

SELECT class_name, SEQUENCE(SELECT meth_name
                            FROM _db_method m
                            WHERE m in c.class_meths)
FROM _db_class c
WHERE c.owner.name = 'DBA' AND c.class_meth_count > 0
ORDER BY 1;
  class_name            sequence((select meth_name from _db_method m where m in c.class_meths))
============================================
  'db_serial'           {'change_serial_owner'}
  'db_authorizations'   {'add_user', 'drop_user', 'find_user', 'print_authorizations', 'info', 'change_owner', 'change_trigg
r_owner', 'get_owner'}
  'db_authorization'    {'check_authorization'}
  'db_user'             {'add_user', 'drop_user', 'find_user', 'login'}
  'db_root'             {'add_user', 'drop_user', 'find_user', 'print_authorizations', 'info', 'change_owner', 'change_trigg
r_owner', 'get_owner', 'change_sp_owner'}
_db_meth_sig

Represents configuration information of C functions on the method. An index for meth_of is created.

Attribute Name Data Type Description
meth_of _db_method Method for the function information
arg_count INTEGER The number of input arguments of the function
func_name VARCHAR(255) Function name
return_value SEQUENCE OF _db_meth_arg Return value of the function
arguments SEQUENCE OF _db_meth_arg Input arguments of the function
_db_meth_arg

Represents method argument information. An index for meth_sig_of is created.

Attribute Name Data Type Description
meth_sig_of _db_meth_sig Information of the function to which the argument belongs
data_type INTEGER Data type of the argument (a value in the "Value" column of the "Data Types Supported by CUBRID" in _db_attribute)
index_of INTEGER Order of the argument listed in the function definition. Begins with 0 if it is a return value, and 1 if it is an input argument.
domains SEQUENCE OF _db_domain Domain of the argument
_db_meth_file

Represents information of a file in which a function is defined. An index for class_of is created.

Attribute Name Data Type Description
class_of _db_class Class to which the method file information belongs
from_class_of _db_class If the file information is inherited, the super class in which it is defined is used otherwise, NULL
path_name VARCHAR(255) File path in which the method is located
_db_query_spec

Represents the SQL statement of a virtual class. An index for class_of is created.

Attribute Name Data Type Description
class_of _db_class Class information of the virtual class
spec VARCHAR(4096) SQL definition statement of the virtual class
_db_index

Represents index information. An index for class_of is created.

Attribute Name Data Type Description
class_of _db_class Class to which to index belongs
index_name varchar(255) Index name
is_unique INTEGER 1 if the index is unique, and 0 otherwise.
key_count INTEGER The number of attributes that comprise the key
key_attrs SEQUENCE OF _db_index_key Attributes that comprise the key
is_reverse INTEGER 1 for a reverse index, and 0 otherwise.
is_primary_key INTEGER 1 for a primary key, and 0 otherwise.
is_foreign_key INTEGER 1 for a foreign key, and 0 otherwise.
filter_expression VARCHAR(255) The conditions of filtered indexes
have_function INTEGER 1 for a function index, and 0 otherwise.
comment VARCHAR (1024) Comment to describe the index

The following example shows how to retrieve names of indexes that belong to the class.

SELECT class_of.class_name, index_name
FROM _db_index
ORDER BY 1;
  class_of.class_name   index_name
============================================
  '_db_attribute'       'i__db_attribute_class_of_attr_name'
  '_db_auth'            'i__db_auth_grantee'
  '_db_class'           'i__db_class_class_name'
  '_db_domain'          'i__db_domain_object_of'
  '_db_index'           'i__db_index_class_of'
  '_db_index_key'       'i__db_index_key_index_of'
  '_db_meth_arg'        'i__db_meth_arg_meth_sig_of'
  '_db_meth_file'       'i__db_meth_file_class_of'
  '_db_meth_sig'        'i__db_meth_sig_meth_of'
  '_db_method'          'i__db_method_class_of_meth_name'
  '_db_partition'       'i__db_partition_class_of_pname'
  '_db_query_spec'      'i__db_query_spec_class_of'
  '_db_stored_procedure'  'u__db_stored_procedure_sp_name'
  '_db_stored_procedure_args'  'i__db_stored_procedure_args_sp_name'
  'athlete'             'pk_athlete_code'
  'db_serial'           'pk_db_serial_name'
  'db_user'             'i_db_user_name'
  'event'               'pk_event_code'
  'game'                'pk_game_host_year_event_code_athlete_code'
  'game'                'fk_game_event_code'
  'game'                'fk_game_athlete_code'
  'history'             'pk_history_event_code_athlete'
  'nation'              'pk_nation_code'
  'olympic'             'pk_olympic_host_year'
  'participant'         'pk_participant_host_year_nation_code'
  'participant'         'fk_participant_host_year'
  'participant'         'fk_participant_nation_code'
  'record'              'pk_record_host_year_event_code_athlete_code_medal'
  'stadium'             'pk_stadium_code'
_db_index_key

Represents key information on an index. An index for index_of is created.

Attribute Name Data Type Description
index_of _db_index Index to which the key attribute belongs
key_attr_name VARCHAR(255) Name of the attribute that comprises the key
key_order INTEGER Order of the attribute in the key. Begins with 0.
asc_desc INTEGER 1 if the order of attribute values is descending, and 0 otherwise.
key_prefix_length INTEGER Length of prefix to be used as a key
func VARCHAR(255) Functional expression of function based index

The following example shows how to retrieve the names of index that belongs to the class.

SELECT class_of.class_name, SEQUENCE(SELECT key_attr_name
                                     FROM _db_index_key k
                                     WHERE k in i.key_attrs)
FROM _db_index i
WHERE key_count >= 2;
  class_of.class_name   sequence((select key_attr_name from _db_index_key k where k in
i.key_attrs))
============================================
  '_db_partition'       {'class_of', 'pname'}
  '_db_method'          {'class_of', 'meth_name'}
  '_db_attribute'       {'class_of', 'attr_name'}
  'participant'         {'host_year', 'nation_code'}
  'game'                {'host_year', 'event_code', 'athlete_code'}
  'record'              {'host_year', 'event_code', 'athlete_code', 'medal'}
  'history'             {'event_code', 'athlete'}
_db_auth

Represents user authorization information of the class. An index for the grantee is created.

Attribute Name Data Type Description
grantor db_user Authorization grantor
grantee db_user Authorization grantee
class_of _db_class Class object to which authorization is to be granted
auth_type VARCHAR(7) Type name of the authorization granted
is_grantable INTEGER 1 if authorization for the class can be granted to other users, and 0 otherwise.

Authorization types supported by CUBRID are as follows:

  • SELECT
  • INSERT
  • UPDATE
  • DELETE
  • ALTER
  • INDEX
  • EXECUTE

The following example shows how to retrieve authorization information defined in the class db_trig.

SELECT grantor.name, grantee.name, auth_type
FROM _db_auth
WHERE class_of.class_name = 'db_trig';
  grantor.name          grantee.name          auth_type
==================================================================
  'DBA'                 'PUBLIC'              'SELECT'
_db_data_type

Represents the data type supported by CUBRID (see the "Data Types Supported by CUBRID" table in _db_attribute).

Attribute Name Data Type Description
type_id INTEGER Data type identifier. Corresponds to the "Value" column in the "Data Types Supported by CUBRID" table.
type_name VARCHAR(9) Data type name. Corresponds to the "Meaning" column in the "Data Types Supported by CUBRID" table.

The following example shows how to retrieve attributes and type names of the event class.

SELECT a.attr_name, t.type_name
FROM _db_attribute a join _db_data_type t ON a.data_type = t.type_id
WHERE class_of.class_name = 'event'
ORDER BY a.def_order;
  attr_name             type_name
============================================
  'code'                'INTEGER'
  'sports'              'STRING'
  'name'                'STRING'
  'gender'              'CHAR'
  'players'             'INTEGER'
_db_partition

Represents partition information. Indexes for class_of and pname are created.

Attribute Name Data Type Description
class_of _db_class OID of the parent class
pname VARCHAR(255) Parent - NULL
ptype INTEGER 0 - HASH 1 - RANGE 2 - LIST
pexpr VARCHAR(255) Parent only
pvalues SEQUENCE OF Parent - Column name, Hash size RANGE - MIN/MAX value : - Infinite MIN/MAX is stored as NULL LIST - value list
comment VARCHAR(1024) Comment to describe the partition
_db_stored_procedure

Represents Java stored procedure information. An index for sp_name is created.

Attribute Name Data Type Description
sp_name VARCHAR(255) Stored procedure name
sp_type INTEGER Stored procedure type (function or procedure)
return_type INTEGER Return value type
arg_count INTEGER The number of arguments
args SEQUENCE OF _db_stored_procedure_args Argument list
lang INTEGER Implementation language (currently, Java)
target VARCHAR(4096) Name of the Java method to be executed
owner db_user Owner
comment VARCHAR (1024) Comment to describe the stored procedure
_db_stored_procedure_args

Represents Java stored procedure argument information. An index for sp_name is created.

Attribute Name Data Type Description
sp_name VARCHAR(255) Stored procedure name
index_of INTEGER Order of the arguments
arg_name VARCHAR(255) Argument name
data_type INTEGER Data type of the argument
mode INTEGER Mode (IN, OUT, INOUT)
comment VARCHAR (1024) Comment to describe the argument
db_user
Attribute Name Data Type Description
name VARCHAR(1073741823) User name
id INTEGER User identifier
password db_password User password. Not displayed to the user.
direct_groups SET OF db_user Groups to which the user belongs directly
groups SET OF db_user Groups to which the user belongs directly or indirectly
authorization db_authorization Information of the authorization owned by the user
triggers SEQUENCE OF object Triggers that occur due to user actions
comment VARCHAR (1024) Comment to describe the user

Function Names

  • set_password ()
  • set_password_encoded ()
  • add_member ()
  • drop_member ()
  • print_authorizations ()
  • add_user ()
  • drop_user ()
  • find_user ()
  • login ()
db_authorization
Attribute Name Data Type Description
owner db_user User information
grants SEQUENCE OF object Sequence of {object for which the user has authorization, authorization grantor of the object, authorization type}

Method Name

  • check_authorization (varchar(255), integer)
db_trigger
Attribute Name Data Type Description
owner db_user Trigger owner
name VARCHAR(1073741823) Trigger name
status INTEGER 1 for INACTIVE, and 2 for ACTIVE. The default value is 2.
priority DOUBLE Execution priority between triggers. The default value is 0.
event INTEGER 0 is set for UPDATE, 1 for UPDATE STATEMENT, 2 for DELETE, 3 for DELETE STATEMENT, 4 for INSERT, 5 for INSERT STATEMENT, 8 for COMMIT, and 9 for ROLLBACK.
target_class object Class object for the trigger target class
target_attribute VARCHAR(1073741823) Trigger target attribute name. If the target attribute is not specified, NULL* is used.
target_class_attribute INTEGER If the target attribute is an instance attribute, 0 is used. If it is a class attribute, 1 is used. The default value is 0.
condition_type INTEGER If a condition exist, 1; otherwise NULL.
condition VARCHAR(1073741823) Action condition specified in the IF statement
condition_time INTEGER 1 for BEFORE, 2 for AFTER, and 3 for DEFERRED if a condition exists; NULL, otherwise.
action_type INTEGER 1 for one of INSERT, UPDATE, DELETE, and CALL, 2 for REJECT, 3 for INVALIDATE_TRANSACTION, and 4 for PRINT.
action_definition VARCHAR(1073741823) Execution statement to be triggered
action_time INTEGER 1 for BEFORE, 2 for AFTER, and 3 for DEFERRED.
comment VARCHAR (1024) Comment to describe the trigger
db_ha_apply_info

A table that stores the progress status every time the applylogdb utility applies replication logs. This table is updated at every point the applylogdb utility commits, and the accumulative count of operations are stored in the *_counter column. The meaning of each column is as follows:

Column Name Column Type Description
db_name VARCHAR(255) Name of the database stored in the log
db_creation_time DATETIME Creation time of the source database for the log to be applied
copied_log_path VARCHAR(4096) Path to the log file to be applied
committed_lsa_pageid BIGINT The page id of commit log lsa reflected last. Although applylogdb is restarted, the logs before last_committed_lsa are not reflected again.
committed_lsa_offset INTEGER The offset of commit log lsa reflected last. Although applylogdb is restarted, the logs before last_committed_lsa are not reflected again.
committed_rep_pageid BIGINT The page id of the replication log lsa reflected last. Check whether the reflection of replication has been delayed or not.
committed_rep_offset INTEGER The offset of the replication log lsa reflected last. Check whether the reflection of replication has been delayed or not.
append_lsa_page_id BIGINT The page id of the last replication log lsa at the last reflection. Saves append_lsa of the replication log header that is being processed by applylogdb at the time of reflecting the replication. Checks whether the reflection of replication has been delayed or not at the time of reflecting the replication log.
append_lsa_offset INTEGER The offset of the last replication log lsa at the last reflection. Saves append_lsa of the replication log header that is being processed by applylogdb at the time of reflecting the replication. Checks whether the reflection of replication has been delayed or not at the time of reflecting the replication log.
eof_lsa_page_id BIGINT The page id of the replication log EOF lsa at the last reflection. Saves eof_lsa of the replication log header that is being processed by applylogdb at the time of reflecting the replication. Checks whether the reflection of replication has been delayed or not at the time of reflecting the replication log.
eof_lsa_offset INTEGER The offset of the replication log EOF lsa at the last reflection. Saves eof_lsa of the replication log header that is being processed by applylogdb at the time of reflecting the replication. Checks whether the reflection of replication has been delayed or not at the time of reflecting the replication log.
final_lsa_pageid BIGINT The pageid of replication log lsa processed last by applylogdb. Checks whether the reflection of replication has been delayed or not.
final_lsa_offset INTEGER The offset of replication log lsa processed last by applylogdb. Checks whether the reflection of replication has been delayed or not.
required_page_id BIGINT The smallest page which should not be deleted by the log_max_archives parameter. The log page number from which the replication will be reflected.
required_page_offset INTEGER The offset of the log page from which the replication will be reflected.
log_record_time DATETIME Timestamp included in replication log committed in the slave database, i.e. the creation time of the log
log_commit_time DATETIME The time of reflecting the last commit log
last_access_time DATETIME The final update time of the db_ha_apply_info catalog
status INTEGER Progress status (0: IDLE, 1: BUSY)
insert_counter BIGINT Number of times that applylogdb was inserted
update_counter BIGINT Number of times that applylogdb was updated
delete_counter BIGINT Number of times that applylogdb was deleted
schema_counter BIGINT Number of times that applylogdb changed the schema
commit_counter BIGINT Number of times that applylogdb was committed
fail_counter BIGINT Number of times that applylogdb failed to be inserted/updated/deleted/committed and to change the schema
start_time DATETIME Time when the applylogdb process accessed the slave database
System Catalog Virtual Class

General users can only see information of classes for which they have authorization through system catalog virtual classes. This section explains which information each system catalog virtual class represents, and virtual class definition statements.

DB_CLASS

Represents information of classes for which the current user has access authorization to a database.

Attribute Name Data Type Description
class_name VARCHAR(255) Class name
owner_name VARCHAR(255) Name of class owner
class_type VARCHAR(6) 'CLASS' for a class, and 'VCLASS' for a virtual class
is_system_class VARCHAR(3) 'YES' for a system class, and 'NO' otherwise.
partitioned VARCHAR(3) 'YES' for a partitioned group class, and 'NO' otherwise.
is_reuse_oid_class VARCHAR(3) 'YES' for a REUSE_OID class, and 'NO' otherwise.
collation VARCHAR(32) Collation name
comment VARCHAR(2048) Comment to describe the class

The following example shows how to retrieve classes owned by the current user.

SELECT class_name
FROM db_class
WHERE owner_name = CURRENT_USER;
  class_name
======================
  'stadium'
  'code'
  'nation'
  'event'
  'athlete'
  'participant'
  'olympic'
  'game'
  'record'
  'history'
  'female_event'

The following example shows how to retrieve virtual classes that can be accessed by the current user.

SELECT class_name
FROM db_class
WHERE class_type = 'VCLASS';
  class_name
======================
  'db_stored_procedure_args'
  'db_stored_procedure'
  'db_partition'
  'db_trig'
  'db_auth'
  'db_index_key'
  'db_index'
  'db_meth_file'
  'db_meth_arg_setdomain_elm'
  'db_meth_arg'
  'db_method'
  'db_attr_setdomain_elm'
  'db_attribute'
  'db_vclass'
  'db_direct_super_class'
  'db_class'

The following example shows how to retrieve system classes that can be accessed by the current user(PUBLIC user).

SELECT class_name
FROM db_class
WHERE is_system_class = 'YES' AND class_type = 'CLASS'
ORDER BY 1;
  class_name
======================
  'db_authorization'
  'db_authorizations'
  'db_root'
  'db_serial'
  'db_user'
DB_DIRECT_SUPER_CLASS

Represents the names of super classes (if any) of the class for which the current user has access authorization to a database.

Attribute Name Data Type Description
class_name VARCHAR(255) Class name
super_class_name VARCHAR(255) super class name

The following example shows how to retrieve super classes of the female_event class (see ADD SUPERCLASS Clause).

SELECT super_class_name
FROM db_direct_super_class
WHERE class_name = 'female_event';
  super_class_name
======================
  'event'

The following example shows how to retrieve super classes of the class owned by the current user (PUBLIC user).

SELECT c.class_name, s.super_class_name
FROM db_class c, db_direct_super_class s
WHERE c.class_name = s.class_name AND c.owner_name = user
ORDER BY 1;
  class_name            super_class_name
============================================
  'female_event'        'event'
DB_VCLASS

Represents SQL definition statements of virtual classes for which the current user has access authorization to a database.

Attribute Name Data Type Description
vclass_name VARCHAR(255) Virtual class name
vclass_def VARCHAR(4096) SQL definition statement of the virtual class
comment VARCHAR(2048) Comment to describe the virtual class

The following example shows how to retrieve SQL definition statements of the db_class virtual class.

SELECT vclass_def
FROM db_vclass
WHERE vclass_name = 'db_class';
  vclass_def
======================
  'SELECT [c].[class_name], CAST([c].[owner].[name] AS VARCHAR(255)), CASE [c].[class_type] WHEN 0 THEN 'CLASS' WHEN 1 THEN 'VCLASS' ELSE 'UNKNOW' END, CASE WHEN MOD([c].[is_system_class], 2) = 1 THEN 'YES' ELSE 'NO' END, CASE WHEN [c].[sub_classes] IS NULL THEN 'NO' ELSE NVL((SELECT 'YES' FROM [_db_partition] [p] WHERE [p].[class_of] = [c] and [p].[pname] IS NULL), 'NO') END, CASE WHEN MOD([c].[is_system_class] / 8, 2) = 1 THEN 'YES' ELSE 'NO' END FROM [_db_class] [c] WHERE CURRENT_USER = 'DBA' OR {[c].[owner].[name]} SUBSETEQ (  SELECT SET{CURRENT_USER} + COALESCE(SUM(SET{[t].[g].[name]}), SET{})  FROM [db_user] [u], TABLE([groups]) AS [t]([g])  WHERE [u].[name] = CURRENT_USER) OR {[c]} SUBSETEQ (  SELECT SUM(SET{[au].[class_of]}) FROM [_db_auth] [au]  WHERE {[au].[grantee].[name]} SUBSETEQ (  SELECT SET{CURRENT_USER} + COALESCE(SUM(SET{[t].[g].[name]}), SET{})  FROM [db_user] [u], TABLE([groups]) AS [t]([g])  WHERE [u].[name] = CURRENT_USER) AND  [au].[auth_type] = 'SELECT')'
DB_ATTRIBUTE

Represents the attribute information of a class for which the current user has access authorization in the database.

Attribute Name Data Type Description
attr_name VARCHAR(255) Attribute name
class_name VARCHAR(255) Name of the class to which the attribute belongs
attr_type VARCHAR(8) 'INSTANCE' for an instance attribute, 'CLASS' for a class attribute, and 'SHARED' for a shared attribute.
def_order INTEGER Order of attributes in the class. Begins with 0. If the attribute is inherited, the order is the one defined in the super class.
from_class_name VARCHAR(255) If the attribute is inherited, the super class in which it is defined is used. Otherwise, NULL.
from_attr_name VARCHAR(255) If the attribute is inherited and its name is changed to resolve a name conflict, the original name defined in the super class is used. Otherwise, NULL.
data_type VARCHAR(9) Data type of the attribute (one in the "Meaning" column of the "Data Types Supported by CUBRID" table in _db_attribute)
prec INTEGER Precision of the data type. 0 is used if the precision is not specified.
scale INTEGER Scale of the data type. 0 is used if the scale is not specified.
charset VARCHAR (32) charset name
collation VARCHAR (32) collation name
domain_class_name VARCHAR(255) Domain class name if the data type is an object. NULL otherwise.
default_value VARCHAR(255) Saved as a character string by default, regardless of data types. If no default value is specified, NULL is stored. If a default value is NULL, it is displayed as 'NULL'. An object data type is represented as 'volume id | page id | slot id' while a set data type is represented as '{element 1, element 2, ... }'.
is_nullable VARCHAR(3) 'NO' if a not null constraint is set, and 'YES' otherwise.
comment VARCHAR(1024) Comment to describe the attribute.

The following example shows how to retrieve attributes and data types of the event class.

SELECT attr_name, data_type, domain_class_name
FROM db_attribute
WHERE class_name = 'event'
ORDER BY def_order;
  attr_name             data_type             domain_class_name
==================================================================
  'code'                'INTEGER'             NULL
  'sports'              'STRING'              NULL
  'name'                'STRING'              NULL
  'gender'              'CHAR'                NULL
  'players'             'INTEGER'             NULL

The following example shows how to retrieve attributes of the female_event class and its super class.

SELECT attr_name, from_class_name
FROM db_attribute
WHERE class_name = 'female_event'
ORDER BY def_order;
  attr_name             from_class_name
============================================
  'code'                'event'
  'sports'              'event'
  'name'                'event'
  'gender'              'event'
  'players'             'event'

The following example shows how to retrieve classes whose attribute names are similar to name, among the ones owned by the current user. (The user is PUBLIC.)

SELECT a.class_name, a.attr_name
FROM db_class c join db_attribute a ON c.class_name = a.class_name
WHERE c.owner_name = CURRENT_USER AND attr_name like '%name%'
ORDER BY 1;
  class_name            attr_name
============================================
  'athlete'             'name'
  'code'                'f_name'
  'code'                's_name'
  'event'               'name'
  'female_event'        'name'
  'nation'              'name'
  'stadium'             'name'
DB_ATTR_SETDOMAIN_ELM

Among attributes of the class to which the current user has access authorization in the database, if an attribute's data type is a collection (SET, MULTISET, SEQUENCE), this macro represents the data type of the element of the collection.

Attribute Name Data Type Description
attr_name VARCHAR(255) Attribute name
class_name VARCHAR(255) Name of the class to which the attribute belongs
attr_type VARCHAR(8) 'INSTANCE' for an instance attribute, 'CLASS' for a class attribute, and 'SHARED' for a shared attribute.
data_type VARCHAR(9) Data type of the element
prec INTEGER Precision of the data type of the element
scale INTEGER Scale of the data type of the element
code_set INTEGER Character set if the data type of the element is a character
domain_class_name VARCHAR(255) Domain class name if the data type of the element is an object

If the set_attr attribute of class D is of a SET (A, B, C) type, the following three records exist.

Attr_name Class_name Attr_type Data_type Prec Scale Code_set Domain_class_name
'set_attr' 'D' 'INSTANCE' 'SET' 0 0 0 'A'
'set_attr' 'D' 'INSTANCE' 'SET' 0 0 0 'B'
'set_attr' 'D' 'INSTANCE' 'SET' 0 0 0 'C'

The following example shows how to retrieve collection type attributes and data types of the city class (the city table defined in Containment Operators is created).

SELECT attr_name, attr_type, data_type, domain_class_name
FROM db_attr_setdomain_elm
WHERE class_name = 'city';
  attr_name             attr_type             data_type             domain_class_name
==============================================================================

'sports'              'INSTANCE'            'STRING'              NULL
DB_CHARSET

Represents charset information.

Attribute name Data type Description
charset_id INTEGER Charset ID
charset_name CHARACTER VARYING(32) Charset name
default_collation CHARACTER VARYING(32) Default collation name
char_size INTEGER One character's byte size
DB_COLLATION

The information on collation.

Attribute Name Data Type Description
coll_id INTEGER Collation ID
coll_name VARCHAR(255) Collation name
charset_name VARCHAR(255) Charset name
is_builtin VARCHAR(3) Built-in or not while installing the product(Yes, No)
has_expansions VARCHAR(3) Having expansion or not(Yes, No)
contractions INTEGER Whether to include abbreviation
uca_strength VARCHAR(255) Weight strength (Not applicable, Primary, Secondary, Tertiary, Quaternary, Identity, Unknown)
DB_METHOD

Represents method information of a class for which the current user has access authorization to a database.

Attribute Name Data Type Description
meth_name VARCHAR(255) Method name
class_name VARCHAR(255) Name of the class to which the method belongs
meth_type VARCHAR(8) 'INSTANCE' for an instance method, and 'CLASS' for a class method.
from_class_name VARCHAR(255) If the method is inherited, the super class in which it is defined is used otherwise NULL
from_meth_name VARCHAR(255) If the method is inherited and its name is changed to resolve a name conflict, the original name defined in the super class is used otherwise NULL
func_name VARCHAR(255) Name of the C function for the method

The following example shows how to retrieve methods of the db_user class.

SELECT meth_name, meth_type, func_name
FROM db_method
WHERE class_name = 'db_user'
ORDER BY meth_type, meth_name;
  meth_name             meth_type             func_name
==================================================================
  'add_user'            'CLASS'               'au_add_user_method'
  'drop_user'           'CLASS'               'au_drop_user_method'
  'find_user'           'CLASS'               'au_find_user_method'
  'login'               'CLASS'               'au_login_method'
  'add_member'          'INSTANCE'            'au_add_member_method'
  'drop_member'         'INSTANCE'            'au_drop_member_method'
  'print_authorizations'  'INSTANCE'            'au_describe_user_method'
  'set_password'        'INSTANCE'            'au_set_password_method'
  'set_password_encoded'  'INSTANCE'            'au_set_password_encoded_method'
  'set_password_encoded_sha1'  'INSTANCE'            'au_set_password_encoded_sha1_method'
DB_METH_ARG

Represents the input/output argument information of the method of the class for which the current user has access authorization to a database.

Attribute Name Data Type Description
meth_name VARCHAR(255) Method name
class_name VARCHAR(255) Name of the class to which the method belongs
meth_type VARCHAR(8) 'INSTANCE' for an instance method, and 'CLASS' for a class method.
index_of INTEGER Order in which arguments are listed in the function definition. Begins with 0 if it is a return value, and 1 if it is an input argument.
data_type VARCHAR(9) Data type of the argument
prec INTEGER Precision of the argument
scale INTEGER Scale of the argument
code_set INTEGER Character set if the data type of the argument is a character.
domain_class_name VARCHAR(255) Domain class name if the data type of the argument is an object.

The following example shows how to retrieve input arguments of the method of the db_user class.

SELECT meth_name, data_type, prec
FROM db_meth_arg
WHERE class_name = 'db_user';
  meth_name             data_type                    prec
=========================================================
  'append_data'         'STRING'               1073741823
DB_METH_ARG_SETDOMAIN_ELM

If the data type of the input/output argument of the method of the class is a set, for which the current user has access authorization in the database, this macro represents the data type of the element of the set.

Attribute Name Data Type Description
meth_name VARCHAR(255) Method name
class_name VARCHAR(255) Name of the class to which the method belongs
meth_type VARCHAR(8) 'INSTANCE' for an instance method, and 'CLASS' for a class method.
index_of INTEGER Order of arguments listed in the function definition. Begins with 0 if it is a return value, and 1 if it is an input argument.
data_type VARCHAR(9) Data type of the element
prec INTEGER Precision of the element
scale INTEGER Scale of the element
code_set INTEGER Character set if the data type of the element is a character
domain_class_name VARCHAR(255) Domain class name if the data type of the element is an object
DB_METH_FILE

Represents information of a file in which the method of the class for which the current user has access authorization in the database is defined.

Attribute Name Data Type Description
class_name VARCHAR(255) Name of the class to which the method file belongs
path_name VARCHAR(255) File path in which the C function is defined
from_class_name VARCHAR(255) Name of the super class in which the method file is defined if the method is inherited, and otherwise NULL
DB_INDEX

Represents information of indexes created for the class for which the current user has access authorization to a database.

Attribute Name Data Type Description
index_name VARCHAR(255) Index name
is_unique VARCHAR(3) 'YES' for a unique index, and 'NO' otherwise.
is_reverse VARCHAR(3) 'YES' for a reversed index, and 'NO' otherwise.
class_name VARCHAR(255) Name of the class to which the index belongs
key_count INTEGER The number of attributes that comprise the key
is_primary_key VARCHAR(3) 'YES' for a primary key, and 'NO' otherwise.
is_foreign_key VARCHAR(3) 'YES' for a foreign key, and 'NO' otherwise.
filter_expression VARCHAR(255) Conditions of filtered indexes
have_function VARCHAR(3) 'YES' for function based and 'NO' otherwise.
comment VARCHAR(1024) Comment to describe the index

The following example shows how to retrieve index information of the class.

SELECT class_name, index_name, is_unique
FROM db_index
ORDER BY 1;
  class_name            index_name            is_unique
==================================================================
  'athlete'             'pk_athlete_code'     'YES'
  'city'                'pk_city_city_name'   'YES'
  'db_serial'           'pk_db_serial_name'   'YES'
  'db_user'             'i_db_user_name'      'NO'
  'event'               'pk_event_code'       'YES'
  'female_event'        'pk_event_code'       'YES'
  'game'                'pk_game_host_year_event_code_athlete_code'  'YES'
  'game'                'fk_game_event_code'  'NO'
  'game'                'fk_game_athlete_code'  'NO'
  'history'             'pk_history_event_code_athlete'  'YES'
  'nation'              'pk_nation_code'      'YES'
  'olympic'             'pk_olympic_host_year'  'YES'
  'participant'         'pk_participant_host_year_nation_code'  'YES'
  'participant'         'fk_participant_host_year'  'NO'
  'participant'         'fk_participant_nation_code'  'NO'
  'record'              'pk_record_host_year_event_code_athlete_code_medal'  'YES'
  'stadium'             'pk_stadium_code'     'YES'
...
DB_INDEX_KEY

Represents the key information of indexes created for the class for which the current user has access authorization to a database.

Attribute Name Data Type Description
index_name VARCHAR(255) Index name
class_name VARCHAR(255) Name of the class to which the index belongs
key_attr_name VARCHAR(255) Name of attributes that comprise the key
key_order INTEGER Order of attributes in the key. Begins with 0.
asc_desc VARCHAR(4) 'DESC' if the order of attribute values is descending, and 'ASC' otherwise.
key_prefix_length INTEGER The length of prefix to be used as a key
func VARCHAR(255) Functional expression of function based index

The following example shows how to retrieve index key information of the class.

SELECT class_name, key_attr_name, index_name
FROM db_index_key
ORDER BY class_name, key_order;
 'athlete'             'code'                'pk_athlete_code'
 'city'                'city_name'           'pk_city_city_name'
 'db_serial'           'name'                'pk_db_serial_name'
 'db_user'             'name'                'i_db_user_name'
 'event'               'code'                'pk_event_code'
 'female_event'        'code'                'pk_event_code'
 'game'                'host_year'           'pk_game_host_year_event_code_athlete_code'
 'game'                'event_code'          'fk_game_event_code'
 'game'                'athlete_code'        'fk_game_athlete_code'
...
DB_AUTH

Represents authorization information of classes for which the current user has access authorization to a database.

Attribute Name Data Type Description
grantor_name VARCHAR(255) Name of the user who grants authorization
grantee_name VARCHAR(255) Name of the user who is granted authorization
class_name VARCHAR(255) Name of the class for which authorization is to be granted
auth_type VARCHAR(7) Name of the authorization type granted
is_grantable VARCHAR(3) 'YES' if authorization for the class can be granted to other users, and 'NO' otherwise.

The following example how to retrieve authorization information of the classes whose names begin with db_a.

SELECT class_name, auth_type, grantor_name
FROM db_auth
WHERE class_name like 'db_a%'
ORDER BY 1;
  class_name            auth_type             grantor_name
==================================================================
  'db_attr_setdomain_elm'  'SELECT'             'DBA'
  'db_attribute'           'SELECT'             'DBA'
  'db_auth'                'SELECT'             'DBA'
  'db_authorization'       'EXECUTE'            'DBA'
  'db_authorization'       'SELECT'             'DBA'
  'db_authorizations'      'EXECUTE'            'DBA'
  'db_authorizations'      'SELECT'             'DBA'
DB_TRIG

Represents information of a trigger that has the class for which the current user has access authorization to a database, or its attribute as the target.

Attribute Name Data Type Description
trigger_name VARCHAR(255) Trigger name
target_class_name VARCHAR(255) Target class
target_attr_name VARCHAR(255) Target attribute. If not specified in the trigger, NULL
target_attr_type VARCHAR(8) Target attribute type. If specified, 'INSTANCE' is used for an instance attribute, and 'CLASS' is used for a class attribute.
action_type INTEGER 1 for one of INSERT, UPDATE, DELETE, and CALL, 2 for REJECT, 3 for INVALIDATE_TRANSACTION, and 4 for PRINT.
action_time INTEGER 1 for BEFORE, 2 for AFTER, and 3 for DEFERRED.
comment VARCHAR(1024) Comment to describe the trigger.
DB_PARTITION

Represents information of partitioned classes for which the current user has access authorization to a database.

Attribute Name Data Type Description
class_name VARCHAR(255) Class name
partition_name VARCHAR(255) Partition name
partition_class_name VARCHAR(255) Partitioned class name
partition_type VARCHAR(32) Partition type (HASH, RANGE, LIST)
partition_expr VARCHAR(255) Partition expression
partition_values SEQUENCE OF RANGE - MIN/MAX value - For infinite MIN/MAX, NULL LIST - value list
comment VARCHAR(1024) Comment to describe the partition

The following example shows how to retrieve the partition information currently configured for the participant2 class.

SELECT * from db_partition where class_name = 'participant2';
  class_name            partition_name        partition_class_name         partition_type   partition_expr        partition_values
====================================================================================================================================
  'participant2'        'before_2000'         'participant2__p__before_2000'  'RANGE'       'host_year'           {NULL, 2000}
  'participant2'        'before_2008'         'participant2__p__before_2008'  'RANGE'       'host_year'           {2000, 2008}
DB_STORED_PROCEDURE

Represents information of Java stored procedure for which the current user has access authorization to a database.

Attribute Name Data Type Description
sp_name VARCHAR(255) Stored procedure name
sp_type VARCHAR(16) Stored procedure type (function or procedure)
return_type VARCHAR(16) Return value type
arg_count INTEGER The number of arguments
lang VARCHAR(16) Implementing language (currently, Java)
target VARCHAR(4096) Name of the Java method to be executed
owner VARCHAR(256) Owner
comment VARCHAR(1024) Comment to describe the stored procedure

The following example shows how to retrieve Java stored procedures owned by the current user.

SELECT sp_name, target from db_stored_procedure
WHERE sp_type = 'FUNCTION' AND owner = CURRENT_USER;
  sp_name               target
============================================
  'hello'               'SpCubrid.HelloCubrid() return java.lang.String'
  'sp_int'              'SpCubrid.SpInt(int) return int'
DB_STORED_PROCEDURE_ARGS

Represents argument information of Java stored procedure for which the current user has access authorization to a database.

Attribute Name Data Type Description
sp_name VARCHAR(255) Stored procedure name
index_of INTEGER Order of the arguments
arg_name VARCHAR(256) Argument name
data_type VARCHAR(16) Data type of the argument
mode VARCHAR(6) Mode (IN, OUT, INOUT)
comment VARCHAR(1024) Comment to describe the argument

The following example shows how to retrieve arguments the 'phone_info' Java stored procedure in the order of the arguments.

SELECT index_of, arg_name, data_type, mode
FROM db_stored_procedure_args
WHERE sp_name = 'phone_info'
ORDER BY index_of;
     index_of  arg_name              data_type             mode
===============================================================
            0  'name'                'STRING'              'IN'
            1  'phoneno'             'STRING'              'IN'
Catalog Class/Virtual Class Authorization

Catalog classes are created to be owned by dba. However, dba can only execute SELECT operations. If dba executes operations such as UPDATE / DELETE, an authorization failure error occurs. General users cannot execute queries on system catalog classes.

Although catalog virtual classes are created to be owned by dba, all users can perform the SELECT statement on catalog virtual classes. Of course, UPDATE / DELETE operations on catalog virtual classes are not allowed.

Updating catalog classes/virtual classes is automatically performed by the system when users execute a DDL statement that creates/modifies/deletes a class/attribute/index/user/authorization.

Querying on Catalog

To query on catalog classes, you must convert identifiers such as class, virtual class, attribute, trigger, method and index names to lowercases, and create them. Therefore, you must use lowercases when querying on catalog classes. But, DB user name is changed as uppercases and stored into db_user system catalog table.

CREATE TABLE Foo(name varchar(255));
SELECT class_name, partitioned FROM db_class WHERE class_name = 'Foo';
There are no results.
SELECT class_name, partitioned FROM db_class WHERE class_name = 'foo';
  class_name   partitioned
============================
  'foo'       'NO'
CREATE USER tester PASSWORD 'testpwd';
SELECT name, password FROM db_user;
  name                  password
============================================
  'DBA'                 NULL
  'PUBLIC'              NULL
  'TESTER'              db_password

CUBRID Management

This chapter describes how the database administrators (DBA) operates the CUBRID system.

  • It includes instructions on how to use the cubrid utility, which starts and stops various processes of the CUBRID server, the broker and manager server. See Controlling CUBRID Processes.
  • It includes instructions on the following: database management tasks (creating and deleting databases, adding volume, etc.), migration tasks (moving database to a different location or making changes so that it fits the system's version), and making back-ups and rollbacks of the database in case of failures. See cubrid Utilities.
  • It includes instructions on the system configuration. See System Parameters.
  • It includes how to use SystemTap, which can monitors and traces the operating processes dynamically. See SystemTap.
  • It includes instructions on troubleshooting. See Troubleshooting.

The cubrid utilities provide features that can be used to comprehensively manage the CUBRID service. The CUBRID utilities are divided into the service management utility, which is used to manage the CUBRID service process, and the database management utility, which is used to manage the database.

The service management utilities are as follows:

  • Service utility : Operates and manages the master process.
  • Server utility : Operates and manages the server process.
  • Broker utility : Operates and manages the broker process and application server (CAS) process.
  • Manager utility : Operates and manages the manager server process.
  • HA utility : Operates and manages the HA-related processes.

See Controlling CUBRID Processes for details.

The database management utilities are as follows:

See cubrid Utilities for details.

Note

If you want to control the service by using cubrid utility on Windows Vista or later, it is recommended that you run the command prompt with an administrator account. If you use cubrid utility without an administrator account, the result message is not displayed even though you can run it through the User Account Control (UAC) dialog.

To run the command prompt on Windows Vista or later with an administrator account, right-click [Start] > [All Programs] > [Accessories] > [Command Prompt] and select [Run as Administrator]. In the dialog verifying authorization, click [Yes], and then the command prompt is run as an administrator account.

Controlling CUBRID Processes

CUBRID processes can be controlled by cubrid utility.

Controlling CUBRID Service

The following cubrid utility syntax shows how to control services registered in the configuration file. One of the following can be specified in <command>.

cubrid service <command>
<command>: {start|stop|restart|status}
  • start: start services.
  • stop: stop services.
  • restart: restart services.
  • status: check status.

No additional options or arguments are required.

Controlling Database Server

The following cubrid utility syntax shows how to control database server process.

cubrid server <command> [database_name]
<command>: {start|stop|restart|status}

One of the following can be specified in <command>:

  • start: start a database server process.
  • stop: stop a database server process.
  • restart: restart a database server process.
  • status: check status of a database server process.

Every command except status must have a database name as an argument.

Controlling Broker

The following cubrid utility syntax shows how to control CUBRID broker process.

cubrid broker <command>
<command>: start
           |stop
           |restart
           |status [options] [broker_name_expr]
           |acl {status|reload} broker_name
           |on <broker_name> |off <broker_name>
           |reset broker_name
           |info
  • start: start broker processes.
  • stop: stop broker processes.
  • restart: restart broker processes.
  • status: check status of broker processes.
  • acl: limit broker access.
  • on/off: enable/disable the specified broker.
  • reset: reset the connection to broker.
  • info: display the broker configuration information.
Controlling CUBRID Manager Server

To use the CUBRID Manager, the Manager server must be running where database server is running. The following cubrid utility syntax shows how to control the CUBRID Manager processes.

cubrid manager <command>
<command>: {start|stop|status}
  • start: start manager server processes.
  • stop: stop manager server processes.
  • status: check the status of manager processes.
Controlling CUBRID HA

The following cubrid heartbeat utility syntax shows how to use CUBRID HA. One of the following can be specified in command.

cubrid heartbeat <command>
<command>: {start|stop|copylogdb|applylogdb|reload|status}
  • start: start HA-related processes.
  • stop: stop HA-related processes.
  • copylogdb: start or stop copylogdb process.
  • applylogdb: start or stop applylogdb process.
  • reload: reload information on HA configuration.
  • status: check HA status.

For details, see cubrid heartbeat Utility.

CUBRID Services

Registering Services

You can register database servers, CUBRID brokers, CUBRID Manager(s) or CUBRID HA as CUBRID service in the configuration file ( cubrid.conf ). To register services, you can input for each server, broker, manager or heartbeat as a parameter value, and it is possible to input several values by concatenating them in comma(,).

If you do not register any service, only master process is registered by default. It is convenient for you to view status of all related processes at a glance or start and stop the processes at once with the cubrid service utility once it is registered as CUBRID service.

For details on CUBRID HA configuration, see Registering HA to cubrid service.

The following example shows how to register database server and broker as service in the cubrid.conf file and enable databases ( demodb and testdb ) to start automatically at once when CUBRID server starts running.

# cubrid.conf
...

[service]

# The list of processes to be started automatically by 'cubrid service start' command
# Any combinations are available with server, broker, manager and heartbeat.
service=server,broker

# The list of database servers in all by 'cubrid service start' command.
# This property is effective only when the above 'service' property contains 'server' keyword.
server=demodb,testdb
Starting Services

In Linux environment, you can enter the code below to start CUBRID after installation. If no server is registered in the configuration file, only master process (cub_master) runs by default.

In the Windows environment, the code below is normally executed only if a user with system permission has logged in. An administrator or general user can start or stop the CUBRID server by clicking its icon on the taskbar tray.

% cubrid service start

@ cubrid master start
++ cubrid master start: success

The following message is returned if master process is already running.

% cubrid service start

@ cubrid master start
++ cubrid master is running.

The following message is returned if master process fails to run. The example shows that service fails to start due to conflicts of the cubrid_port_id parameter value specified in the cubrid.conf file. In such a case, you can resolve the problem by changing the port. If it fails to start even though no port is occupied by process, delete /tmp/CUBRID1523 file and then restart the process.

% cubrid service start

@ cubrid master start
cub_master: '/tmp/CUBRID1523' file for UNIX domain socket exist.... Operation not permitted
++ cubrid master start: fail

After registering service as explained in CUBRID Services, enter the code below to start the service. You can verify that database server process and broker as well as registered demodb and testdb are starting at once.

% cubrid service start

@ cubrid master start
++ cubrid master start: success
@ cubrid server start: demodb

This may take a long time depending on the amount of restore works to do.
CUBRID 9.2

++ cubrid server start: success
@ cubrid server start: testdb

This may take a long time depending on the amount of recovery works to do.
CUBRID 9.2

++ cubrid server start: success
@ cubrid broker start
++ cubrid broker start: success
Stopping Services

Enter code below to stop CUBRID service. If no services are registered by a user, only master process stops and then restarts.

% cubrid service stop
@ cubrid master stop
++ cubrid master stop: success

Enter code below to stop registered CUBRID service. You can verify that server process, broker process, and master process as well as demodb and testdb stop at once.

% cubrid service stop
@ cubrid server stop: demodb

Server demodb notified of shutdown.
This may take several minutes. Please wait.
++ cubrid server stop: success
@ cubrid server stop: testdb
Server testdb notified of shutdown.
This may take several minutes. Please wait.
++ cubrid server stop: success
@ cubrid broker stop
++ cubrid broker stop: success
@ cubrid master stop
++ cubrid master stop: success
Restarting Services

Enter code below to restart CUBRID service. If no services are registered by a user, only master process stops and then restarts.

% cubrid service restart

@ cubrid master stop
++ cubrid master stop: success
@ cubrid master start
++ cubrid master start: success

Enter code below to restart registered CUBRID service. You can verify that server process, broker process, and master process as well as demodb and testdb stop and then restart at once.

% cubrid service restart

@ cubrid server stop: demodb
Server demodb notified of shutdown.
This may take several minutes. Please wait.
++ cubrid server stop: success
@ cubrid server stop: testdb
Server testdb notified of shutdown.
This may take several minutes. Please wait.
++ cubrid server stop: success
@ cubrid broker stop
++ cubrid broker stop: success
@ cubrid master stop
++ cubrid master stop: success
@ cubrid master start
++ cubrid master start: success
@ cubrid server start: demodb

This may take a long time depending on the amount of recovery works to do.

CUBRID 10.0

++ cubrid server start: success
@ cubrid server start: testdb

This may take a long time depending on the amount of recovery works to do.

CUBRID 10.0

++ cubrid server start: success
@ cubrid broker start
++ cubrid broker start: success
Managing Service Status

The following example shows how to check the status of master process and database server registered.

% cubrid service status

@ cubrid master status
++ cubrid master is running.
@ cubrid server status

Server testdb (rel 9.2, pid 31059)
Server demodb (rel 9.2, pid 30950)

@ cubrid broker status
% query_editor
----------------------------------------
ID   PID   QPS   LQS PSIZE STATUS
----------------------------------------
 1 15465     0     0 48032 IDLE
 2 15466     0     0 48036 IDLE
 3 15467     0     0 48036 IDLE
 4 15468     0     0 48036 IDLE
 5 15469     0     0 48032 IDLE

% broker1 OFF

@ cubrid manager server status
++ cubrid manager server is not running.

The following message is returned if master process has stopped.

% cubrid service status
@ cubrid master status
++ cubrid master is not running.
cubrid Utility Logging

CUBRID supports a logging feature about cubrid utility's running result.

Logging contents

The following contents are written to the $CUBRID/log/cubrid_utility.log file.

  • All commands through cubrid utilities: only usage, version and parsing errors are not logged.
  • Execution results by cubrid utilities: success/failure.
  • An error message when failure.

Log file size

A size of cubrid_utility.log file is expanded by the size specified by error_log_size parameter in cubrid.conf; if this size is enlarged as the specified size, it is backed up as the cubrid_utility.log.bak file.

Log format

<time> (cubrid PID) <contents>

The following is an example of printing the log file.

13-11-19 15:27:19.426 (17724) cubrid manager stop
13-11-19 15:27:19.430 (17724) FAILURE: ++ cubrid manager server is not running.
13-11-19 15:27:19.434 (17726) cubrid service start
13-11-19 15:27:19.439 (17726) FAILURE: ++ cubrid master is running.
13-11-19 15:27:22.931 (17726) SUCCESS
13-11-19 15:27:22.936 (17756) cubrid service restart
13-11-19 15:27:31.667 (17756) SUCCESS
13-11-19 15:27:31.671 (17868) cubrid service stop
13-11-19 15:27:34.909 (17868) SUCCESS

However, in Windows, some cubrid commands are executed through a service process; therefore, a duplicated information can be displayed again.

13-11-13 17:17:47.638 ( 3820) cubrid service stop
13-11-13 17:17:47.704 ( 7848) d:\CUBRID\bin\cubrid.exe service stop --for-windows-service
13-11-13 17:17:56.027 ( 7848) SUCCESS
13-11-13 17:17:57.136 ( 3820) SUCCESS

And, in Windows, a process run through the service process cannot print out an error message; therefore, for error messages related to the service start, you should definitely check them in the cubrid_utility.log file.

Database Server

Starting Database Server

The following example shows how to run demodb server.

% cubrid server start demodb

@ cubrid server start: demodb

This may take a long time depending on the amount of recovery works to do.

CUBRID 9.2

++ cubrid server start: success

If you start demodb server while master process has stopped, master process automatically runs at first and then a specified database server runs.

% cubrid server start demodb

@ cubrid master start
++ cubrid master start: success
@ cubrid server start: demodb

This may take a long time depending on the amount of recovery works to do.

CUBRID 9.2

++ cubrid server start: success

The following message is returned while demodb server is running.

% cubrid server start demodb

@ cubrid server start: demodb
++ cubrid server 'demodb' is running.

cubrid server start runs cub_server process of a specific database regardless of HA mode configuration. To run database in HA environment, you should use cubrid heartbeat start.

Stopping Database Server

The following example shows how to stop demodb server.

% cubrid server stop demodb

@ cubrid server stop: demodb
Server demodb notified of shutdown.
This may take several minutes. Please wait.
++ cubrid server stop: success

The following message is returned while demodb server has stopped.

% cubrid server stop demodb

@ cubrid server stop: demodb
++ cubrid server 'demodb' is not running.

cubrid server stop stops cub_server process of a specific database regardless of HA mode configuration. Be careful not to restart the database server or occur failover. To stop database in HA environment, you should use cubrid heartbeat stop .

Restarting Database Server

The following example shows how to restart demodb server. demodb server that has already run stops and the server restarts.

% cubrid server restart demodb

@ cubrid server stop: demodb
Server demodb notified of shutdown.
This may take several minutes. Please wait.
++ cubrid server stop: success
@ cubrid server start: demodb

This may take a long time depending on the amount of recovery works to do.

CUBRID 9.2

++ cubrid server start: success
Checking Database Server Status

The following example shows how to check the status of a database server. Names of currently running database servers are displayed.

% cubrid server status

@ cubrid server status
Server testdb (rel 9.2, pid 24465)
Server demodb (rel 9.2, pid 24342)

The following example shows the message when master process has stopped.

% cubrid server status

@ cubrid server status
++ cubrid master is not running.
Limiting Database Server Access

To limit brokers and the CSQL Interpreter connecting to the database server, configure the parameter value of access_ip_control in the cubrid.conf file to yes and enter the path of a file in which the list of IP addresses allowed to access the access_ip_control_file parameter value is written. You should enter the absolute file path. If you enter the relative path, the system will search the file under the $CUBRID/conf directory on Linux and under the %CUBRID%\conf directory on Windows.

The following example shows how to configure the cubrid.conf file.

# cubrid.conf
access_ip_control=yes
access_ip_control_file="/home1/cubrid1/CUBRID/db.access"

The following example shows the format of the access_ip_control_file file.

[@<db_name>]
<ip_addr>
...
  • <db_name>: The name of a database in which access is allowed
  • <ip_addr>: The IP address allowed to access a database. Using an asterisk (*) at the last digit means that all IP addresses are allowed. Several lines of <ip_addr> can be added in the next line of the name of a database.

To configure several databases, it is possible to specify additional [@<db_name>] and <ip_addr>.

Accessing any IP address except localhost is blocked by server if access_ip_control is set to yes but ip_control_file is not configured. A server will not run if analyzing access_ip_control_file fails caused by incorrect format.

The following example shows access_ip_control_file.

[@dbname1]
10.10.10.10
10.156.*

[@dbname2]
*

[@dbname3]
192.168.1.15

The example above shows that dbname1 database allows the access of IP addresses starting with 10.156; dbname2 database allows the access of every IP address; dbname3 database allows the access of an IP address, 192.168.1.15, only.

For the database which has already been running, you can modify a configuration file or you can check the currently applied status by using the following commands.

To change the contents of access_ip_control_file and apply it to server, use the following command.

cubrid server acl reload <database_name>

To display the IP configuration of a server which is currently running, use the following command.

cubrid server acl status <database_name>
Database Server Log
Error Log

The following log is created in the file of a server error log if an IP address that is not allowed to access is used.

Time: 10/29/10 17:32:42.360 - ERROR *** ERROR CODE = -1022, Tran = 0, CLIENT = (unknown):(unknown)(-1), EID = 2
Address(10.24.18.66) is not authorized.

An error log of the database server is saved into $CUBRID/log/server directory, and the format of the file name is <db_name>_<yyyymmdd>_<hhmi>.err. The extension is ".err".

demodb_20130618_1655.err

Note

For details on how to limit an access to the broker server, see Limiting Broker Access.

Event Log

If an event which affects on the query performance occurs, this is saved into the event log.

The events which are saved on the event log are SLOW_QUERY, MANY_IOREADS, LOCK_TIMEOUT, DEADLOCK and TEMP_VOLUME_EXPAND.

This log file is saved into the $CUBRID/log/server directory, and the format of the file name is <db_name>_<yyyymmdd>_<hhmi>.event. The extension is ".event".

demodb_20130618_1655.event

SLOW_QUERY

If a slow query occurs, this event is written. If sql_trace_slow parameter value of cubrid.conf is set, this event will arise. The output example is as follows.

06/12/13 16:41:05.558 - SLOW_QUERY
  client: PUBLIC@testhost|csql(13173)
  sql: update [y] [y] set [y].[a]= ?:1  where [y].[a]= ?:0  using index [y].[pk_y_a](+)
  bind: 5
  bind: 200
  time: 1015
  buffer: fetch=48, ioread=2, iowrite=0
  wait: cs=1, lock=1010, latch=0
  • client: <DB user>@<application client host name>|<program name>(<process ID>)
  • sql: slow query
  • bind: binding value. it is printed out as the number of <num> in the sql item, "?:<num>". The value of "?:0" is 5, and the value of "?:1" is 200.
  • time: execution time(ms)
  • buffer: execution statistics in the buffer
    • fetch: fetching pages count
    • ioread: I/O read pages count
    • iowrite: I/O write pages count
  • wait: waiting time
    • cs: waiting time on the critical section(ms)
    • lock: waiting time to acquire the lock(ms)
    • latch: waiting time to acquire the latch(ms)

On the above example, the query execution time was 1015ms, and lock waiting time was 1010ms, so we can indicate that almost all execution time was from lock waiting.

MANY_IOREADS

Queries which brought many I/O reads are written on the event log. If I/O reads occurs more than sql_trace_ioread_pages parameter value of cubrid.conf, the event is written on the event log. The following is an output example.

06/12/13 17:07:29.457 - MANY_IOREADS
  client: PUBLIC@testhost|csql(12852)
  sql: update [x] [x] set [x].[a]= ?:1  where ([x].[a]> ?:0 ) using index [x].[idx](+)
  bind: 8
  bind: 100
  time: 528
  ioreads: 15648
  • client: <DB user>@<application client host name>|<process name>(<process ID>)
  • sql: an SQL which brought many I/O reads
  • bind: binding value. it is printed out as the number of <num> in the sql item, "?:<num>". The value of "?:0" is 8, and the value of "?:1" is 100.
  • time: execution time(ms)
  • ioread: I/O read pages count

LOCK_TIMEOUT

When lock timeout occurs, queries of a waiter and a blocker are written on the event log. The following is an output example.

02/02/16 20:56:18.650 - LOCK_TIMEOUT
waiter:
  client: public@testhost|csql(21529)
  lock:    X_LOCK (oid=0|650|3, table=t)
  sql: update [t] [t] set [t].[a]= ?:0  where [t].[a]= ?:1
  bind: 2
  bind: 1

blocker:
  client: public@testhost|csql(21541)
  lock:    X_LOCK (oid=0|650|3, table=t)
  sql: update [t] [t] set [t].[a]= ?:0  where [t].[a]= ?:1
  bind: 3
  bind: 1
  • waiter: a waiting client to acquire locks.
    • lock: lock type, table and index names
    • sql: a waiting SQL to acquire locks.
    • bind: binding value.
  • blocker: a client to have locks.
    • lock: lock type, table and index names
    • sql: a SQL which is acquiring locks
    • bind: binding value

On the above, you can indicate the blocker which brought lock timeout and the waiter which is waiting locks.

DEADLOCK

When a deadlock occurs, lock information of that transaction is written into the event log. The following is an output example.

02/02/16 20:56:17.638 - DEADLOCK
client: public@testhost|csql(21541)
hold:
  lock:    X_LOCK (oid=0|650|5, table=t)
  sql: update [t] [t] set [t].[a]= ?:0  where [t].[a]= ?:1
  bind: 3
  bind: 1

  lock:    X_LOCK (oid=0|650|3, table=t)
  sql: update [t] [t] set [t].[a]= ?:0  where [t].[a]= ?:1
  bind: 3
  bind: 1

wait:
  lock:    X_LOCK (oid=0|650|4, table=t)
  sql: update [t] [t] set [t].[a]= ?:0  where [t].[a]= ?:1
  bind: 5
  bind: 2

client: public@testhost|csql(21529)
hold:
  lock:    X_LOCK (oid=0|650|6, table=t)
  sql: update [t] [t] set [t].[a]= ?:0  where [t].[a]= ?:1
  bind: 4
  bind: 2

  lock:    X_LOCK (oid=0|650|4, table=t)
  sql: update [t] [t] set [t].[a]= ?:0  where [t].[a]= ?:1
  bind: 4
  bind: 2

wait:
  lock:    X_LOCK (oid=0|650|3, table=t)
  sql: update [t] [t] set [t].[a]= ?:0  where [t].[a]= ?:1
  bind: 6
  bind: 1
  • client: <DB user>@<application client host name>|<process name>(<process ID>)
    • hold: an object which is acquiring a lock
      • lock: lock type, table name
      • sql: SQL which is acquiring locks
      • bind: binding value
    • wait: an object which is waiting a lock
      • lock: lock type, table name
      • sql: SQL which is waiting a lock
      • bind: binding value

On the above output, you can check the application clients and SQLs which brought the deadlock.

For more details on locks, see lockdb and Lock Protocol.

TEMP_VOLUME_EXPAND

When a temporary temp volume is expanded, this time is written to the event log. By this log, you can check what transaction brought the expansion of a temporary temp volume.

06/15/13 18:55:43.458 - TEMP_VOLUME_EXPAND
  client: public@testhost|csql(17540)
  sql: select [x].[a], [x].[b] from [x] [x] where (([x].[a]< ?:0 )) group by [x].[b] order by 1
  bind: 1000
  time: 44
  pages: 24399
  • client: <DB user>@<application client host name>|<process name>(<process ID>)
  • sql: SQL which requires a temporary temp volume. All INSERT statement except for INSERT ... SELECT syntax, and DDL statement are not delivered to the DB server, so it is shown as EMPTY SELECT, UPDATE and DELETE statements are shown on this item
  • bind: binding value
  • time: a required time to create a temporary temp volume(ms)
  • pages: a required number of pages to create a temporary temp volume
Database Server Errors

Database server error processes use the server error code when an error has occurred. A server error can occur in any task that uses server processes. For example, server errors may occur while using the query handling program or the cubrid utility.

Checking the Database Server Error Codes

  • Every data definition statement starting with #define ER_ in the $CUBRID/include/dbi.h file indicate the serer error codes.
  • All message groups under "$set 5 MSGCAT_SET_ERROR" in the CUBRID/msg/en_US (in Korean, ko_KR.eucKR or ko_KR.utf8)/cubrid.msg $ file indicates the server error messages.

When you write a C code with CCI driver, we recommend you to write a code with an error code name than with an error code number. For example, the error code number for violating the unique key is -670 or -886, but users can easily recognize the error when it is written as ER_BTREE_UNIQUE_FAILED or ER_UNIQUE_VIOLATION_WITHKEY.

However, when you write a JAVA code with JDBC driver, you have to use error code numbers because "dbi.h" file cannot be included into the JAVA code. For JDBC program, you can get an error number by using getErrorCode() method of SQLException class.

$ vi $CUBRID/include/dbi.h

#define NO_ERROR                                       0
#define ER_FAILED                                     -1
#define ER_GENERIC_ERROR                              -1
#define ER_OUT_OF_VIRTUAL_MEMORY                      -2
#define ER_INVALID_ENV                                -3
#define ER_INTERRUPTED                                -4
...
#define ER_LK_OBJECT_TIMEOUT_SIMPLE_MSG              -73
#define ER_LK_OBJECT_TIMEOUT_CLASS_MSG               -74
#define ER_LK_OBJECT_TIMEOUT_CLASSOF_MSG             -75
#define ER_LK_PAGE_TIMEOUT                           -76
...
#define ER_PT_SYNTAX                                -493
...
#define ER_BTREE_UNIQUE_FAILED                      -670
...
#define ER_UNIQUE_VIOLATION_WITHKEY                 -886
...
#define ER_LK_OBJECT_DL_TIMEOUT_SIMPLE_MSG          -966
#define ER_LK_OBJECT_DL_TIMEOUT_CLASS_MSG           -967
#define ER_LK_OBJECT_DL_TIMEOUT_CLASSOF_MSG         -968
...

The following are some of the server error code names, error code numbers, and error messages.

Error Code Name Error Code Number Error Message
ER_LK_OBJECT_TIMEOUT_SIMPLE_MSG -73 Your transaction (index ?, ?@?|?) timed out waiting on ? lock on object ?|?|?. You are waiting for user(s) ? to finish.
ER_LK_OBJECT_TIMEOUT_CLASS_MSG -74 Your transaction (index ?, ?@?|?) timed out waiting on ? lock on class ?. You are waiting for user(s) ? to finish.
ER_LK_OBJECT_TIMEOUT_CLASSOF_MSG -75 Your transaction (index ?, ?@?|?) timed out waiting on ? lock on instance ?|?|? of class ?. You are waiting for user(s) ? to finish.
ER_LK_PAGE_TIMEOUT -76 Your transaction (index ?, ?@?|?) timed out waiting on ? on page ?|?. You are waiting for user(s) ? to release the page lock.
ER_PT_SYNTAX -493 Syntax: ?
ER_BTREE_UNIQUE_FAILED -670 Operation would have caused one or more unique constraint violations.
ER_UNIQUE_VIOLATION_WITHKEY -886 "?" caused unique constraint violation.
ER_LK_OBJECT_DL_TIMEOUT_SIMPLE_MSG -966 Your transaction (index ?, ?@?|?) timed out waiting on ? lock on object ?|?|? because of deadlock. You are waiting for user(s) ? to finish.
ER_LK_OBJECT_DL_TIMEOUT_CLASS_MSG -967 Your transaction (index ?, ?@?|?) timed out waiting on ? lock on class ? because of deadlock. You are waiting for user(s) ? to finish.
ER_LK_OBJECT_DL_TIMEOUT_CLASSOF_MSG -968 Your transaction (index ?, ?@?|?) timed out waiting on ? lock on instance ?|?|? of class ? because of deadlock. You are waiting for user(s) ? to

Broker

Starting Broker

Enter the command below to start the broker.

$ cubrid broker start
@ cubrid broker start
++ cubrid broker start: success

The following message is returned if the broker is already running.

$ cubrid broker start
@ cubrid broker start
++ cubrid broker is running.
Stopping Broker

Enter the command below to stop the broker.

$ cubrid broker stop
@ cubrid broker stop
++ cubrid broker stop: success

The following message is returned if the broker has stopped.

$ cubrid broker stop
@ cubrid broker stop
++ cubrid broker is not running.
Restarting Broker

Enter the command below to restart the whole brokers.

$ cubrid broker restart
Checking Broker Status

The cubrid broker status utility allows you to check the broker status such as number of completed jobs and the number of standby jobs by providing various options.

cubrid broker status [options] [expr]
  • expr: A part of the broker name or "SERVICE=ON|OFF"

Specifying expr performs that the status of specific brokers which include expr in their names is monitored; specifying no argument means that status of all brokers which are registered in the broker environment configuration file ( cubrid_broker.conf ) is monitored.

If "SERVICE=ON" is specified on expr, only the status of working brokers is displayed; if "SERVICE=OFF" is specified, only the status of stopped brokers is displayed.

The following [options] are available with the cubrid broker status utility. -b, -q, -c, -m, -S, -P and -f are options to define the information to print; -s, -l and -t are options to control printing. All of these are possible to use as combining each other.

-b

Displays the status information of a broker but does not display information on broker application server.

-q

Displays standby jobs in the job queue.

-f

Displays information of DB and host accessed by broker.

If it is used with the -b option, additional information on CAS is displayed. But SELECT, INSERT, UPDATE, DELETE, OTHERS items which shown on -b option are excluded.

If it is used with the -P option, STMT-POOL-RATIO is additionally printed. This item shows the ratio to use statements in the pool when you are using prepared statements.

-l SECOND

The -l option is only used with -f option together. It specifies accumulation period (unit: sec.) when displaying the number of application servers whose client status is Waiting or Busy. If it is omitted, the default value (1 second) is specified.

-t

Displays results in tty mode on the screen. The output can be redirected and used as a file.

-s SECOND

Regularly displays the status of broker based on specified period. It returns to a command prompt if q is entered.

If you do not specify options or arguments, the status of all brokers is displayed.

$ cubrid broker status
@ cubrid broker status
% query_editor
----------------------------------------
ID   PID   QPS   LQS PSIZE STATUS
----------------------------------------
 1 28434     0     0 50144 IDLE
 2 28435     0     0 50144 IDLE
 3 28436     0     0 50144 IDLE
 4 28437     0     0 50140 IDLE
 5 28438     0     0 50144 IDLE

% broker1 OFF
  • % query_editor: The broker name
  • ID: Serial number of CAS within the broker
  • PID: CAS process ID within the broker
  • QPS: The number of queries processed per second
  • LQS: The number of long-duration queries processed per second
  • PSIZE: Size of CAS
  • STATUS: The current status of CAS (BUSY, IDLE, CLIENT_WAIT, CLOSE_WAIT)
  • % broker1 OFF: broker1's SERVICE parameter is set to OFF. So, broker1 is not started.

The following shows the detail status of broker for 5 seconds. The display will reset per 5 seconds as the new status information. To escape the display of the status, press <Q>.

$ cubrid broker status -b -s 5
@ cubrid broker status

 NAME                    PID  PORT   AS   JQ    TPS    QPS   SELECT   INSERT   UPDATE   DELETE   OTHERS     LONG-T     LONG-Q   ERR-Q  UNIQUE-ERR-Q  #CONNECT  #REJECT
=======================================================================================================================================================================
* query_editor         13200 30000    5    0      0      0        0        0        0        0        0     0/60.0     0/60.0       0             0         0        0
* broker1              13269 33000    5    0     70     60       10       20       10       10       10     0/60.0     0/60.0      30            10       213        1
  • NAME: The broker name
  • PID: Process ID of the broker
  • PORT: Port number of the broker
  • AS: The number of CAS
  • JQ: The number of standby jobs in the job queue
  • TPS: The number of transactions processed per second (calculated only when the option is configured to "-b -s <sec>")
  • QPS: The number of queries processed per second (calculated only when the option is configured to "-b -s <sec>")
  • SELECT: The number of SELECT queries after staring of the broker. When there is an option of "-b -s <sec>", it is updated every time with the number of SELECTs which have been executed during the seconds specified by this option.
  • INSERT: The number of INSERT queries after staring of the broker. When there is an option of "-b -s <sec>", it is updated every time with the number of INSERTs which have been executed during the seconds specified by this option.
  • UPDATE: The number of UPDATE queries after staring of the broker. When there is an option of "-b -s <sec>", it is updated every time with the number of UPDATEs which have been executed during the seconds specified by this option.
  • DELETE: The number of DELETE queries after staring of the broker. When there is an option of "-b -s <sec>", it is updated every time with the number of DELETEs which have been executed during the seconds specified by this option.
  • OTHERS: The number of queries like CREATE and DROP except for SELECT, INSERT, UPDATE, DELETE. When there is an option of "-b -s <sec>", it is updated every time with the number of queries which have been executed during the seconds specified by this option.
  • LONG-T: The number of transactions which exceed LONG_TRANSACTION_TIME. / the value of the LONG_TRANSACTION_TIME parameter. When there is an option of "-b -s <sec>", it is updated every time with the number of transactions which have been executed during the seconds specified by this option.
  • LONG-Q: The number of queries which exceed LONG_QUERY_TIME. / the value of the LONG_QUERY_TIME parameter. When there is an option of "-b -s <sec>", it is updated every time with the number of queries which have been executed during the seconds specified by this option.
  • ERR-Q: The number of queries with errors found. When there is an option of "-b -s <sec>", it is updated every time with the number of errors which have occurred during the seconds specified by this option.
  • UNIQUE-ERR-Q: The number of queries with unique key errors found. When there is an option of "-b -s <sec>", it is updated every time with the number of unique key errors which have occurred during the seconds specified by this option.
  • #CONNECT: The number of connections that an application client accesses to CAS after starting the broker.
  • #REJECT: The count that an application client excluded from ACL IP list is rejected to access a CAS. Regarding ACL setting, see Limiting Broker Access.

The following checks the status of broker whose name includes broker1 and job status of a specific broker in the job queue with the -q option. If you do not specify broker1 as an argument, list of jobs in the job queue for all brokers is displayed.

% cubrid broker status -q broker1
@ cubrid broker status
% broker1
----------------------------------------
ID   PID   QPS   LQS PSIZE STATUS
----------------------------------------
 1 28444     0     0 50144 IDLE
 2 28445     0     0 50140 IDLE
 3 28446     0     0 50144 IDLE
 4 28447     0     0 50144 IDLE
 5 28448     0     0 50144 IDLE

The following monitors the status of a broker whose name includes broker1 with the -s option. If you do not specify broker1 as an argument, monitoring status for all brokers is performed regularly. It returns to a command prompt if q is not entered.

% cubrid broker status -s 5 broker1
% broker1
----------------------------------------
ID   PID   QPS   LQS PSIZE STATUS
----------------------------------------
 1 28444     0     0 50144 IDLE
 2 28445     0     0 50140 IDLE
 3 28446     0     0 50144 IDLE
 4 28447     0     0 50144 IDLE
 5 28448     0     0 50144 IDLE

With the -t option, it display information of TPS and QPS to a file. To cancel displaying, press <Ctrl+C> to stop program.

% cubrid broker status -b -t -s 1 > log_file

The following views information of server/database accessed by broker, the last access times of applications, the IP addresses accessed to CAS and the versions of drivers etc. with the -f option.

$ cubrid broker status -f broker1
@ cubrid broker status
% broker1
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ID   PID   QPS   LQS PSIZE STATUS         LAST ACCESS TIME      DB       HOST   LAST CONNECT TIME       CLIENT IP   CLIENT VERSION    SQL_LOG_MODE   TRANSACTION STIME  #CONNECT  #RESTART
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1 26946     0     0 51168 IDLE         2011/11/16 16:23:42  demodb  localhost 2011/11/16 16:23:40      10.0.1.101     9.2.0.0062              NONE 2011/11/16 16:23:42         0         0
 2 26947     0     0 51172 IDLE         2011/11/16 16:23:34      -          -                   -          0.0.0.0                                -                   -         0         0
 3 26948     0     0 51172 IDLE         2011/11/16 16:23:34      -          -                   -          0.0.0.0                                -                   -         0         0
 4 26949     0     0 51172 IDLE         2011/11/16 16:23:34      -          -                   -          0.0.0.0                                -                   -         0         0
 5 26950     0     0 51172 IDLE         2011/11/16 16:23:34      -          -                   -          0.0.0.0                                -                   -         0         0

Meaning of each column in code above is as follows:

  • LAST ACCESS TIME: Time when CAS runs or the latest time when an application client accesses CAS
  • DB: Name of a database which CAS accesses most recently
  • HOST: Name of a which CAS accesses most recently
  • LAST CONNECT TIME: Most recent time when CAS accesses a database
  • CLIENT IP: IP of an application clients currently being connected to an application server(CAS). If no application client is connected, 0.0.0.0 is displayed.
  • CLIENT VERSION: A driver's version of an application client currently being connected to a CAS
  • SQL_LOG_MODE: SQL logging mode of CAS. If the mode is same as the mode configured in the broker, "-" is displayed.
  • TRANSACTION STIME: Transaction start time
  • #CONNECT: The number of connections that an application client accesses to CAS after starting the broker
  • #RESTART: The number of connection that CAS is re-running after starting the broker

Enter the command below with the -b and -f options to display AS(T W B Ns-W Ns-B) and CANCELED additionally.

// The -f option is added upon execution of broker status information. Configuring Ns-W and Ns-B are displayed as long as N seconds by using the -l.
% cubrid broker status -b -f -l 2
@ cubrid broker status
NAME          PID    PSIZE PORT  AS(T W B 2s-W 2s-B) JQ TPS QPS LONG-T LONG-Q  ERR-Q UNIQUE-ERR-Q CANCELED ACCESS_MODE SQL_LOG  #CONNECT #REJECT
================================================================================================================================================
query_editor 16784 56700 30000      5 0 0     0   0   0  16  29 0/60.0 0/60.0      1            1        0          RW     ALL         4       1

Meaning of added columns in code above is as follows:

  • AS(T): Total number of CAS being executed
  • AS(W): The number of CAS in the status of Waiting
  • AS(B): The number of CAS in the status of Busy
  • AS(Ns-W): The number of CAS that the client belongs to has been waited for N seconds.
  • AS(Ns-B): The number of CAS that the client belongs to has been Busy for N seconds.
  • CANCELED: The number of queries have cancelled by user interruption since the broker starts (if it is used with the -l N option, it specifies the number of accumulations for N seconds).
Limiting Broker Access

To limit the client applications accessing the broker, set to ON for the ACCESS_ CONTROL parameter in the cubrid_broker.conf file, and enter a name of the file in which the users and the list of databases and IP addresses allowed to access the ACCESS_CONTROL_FILE parameter value are written. The default value of the ACCESS_CONTROL broker parameter is OFF. The ACCESS_CONTROL and ACCESS_CONTROL_FILE parameters must be written under [broker] which common parameters are specified.

The format of ACCESS_CONTROL_FILE is as follows:

[%<broker_name>]
<db_name>:<db_user>:<ip_list_file>
...
  • <broker_name>: A broker name. It is the one of broker names specified in cubrid_broker.conf .
  • <db_name>: A database name. If it is specified as *, all databases are allowed to access the broker server.
  • <db_user>: A database user ID. If it is specified as *, all database user IDs are allowed to access the broker server.
  • <ip_list_file>: Names of files in which the list of accessible IPs are stored. Several files such as ip_list_file1, ip_list_file2, ... can be specified by using a comma (,).

[%<broker_name>] and <db_name>:<db_user>:<ip_list_file> can be specified separately for each broker. A separated line can be specified for the same <db_name> and the same <db_user>. List of IPs can be written up to the maximum of 256 lines per <db_name>:<db_user> in a broker.

The format of the ip_list_file is as follows:

<ip_addr>
...
  • <ip_addr>: An IP address that is allowed to access the server. If the last digit of the address is specified as *, all IP addresses in that rage are allowed to access the broker server.

If a value for ACCESS_CONTROL is set to ON and a value for ACCESS_CONTROL_FILE is not specified, the broker will only allow the access requests from the localhost.

If the analysis of ACCESS_CONTROL_FILE and ip_list_file fails when starting a broker, the broker will not be run.

# cubrid_broker.conf
[broker]
MASTER_SHM_ID           =30001
ADMIN_LOG_FILE          =log/broker/cubrid_broker.log
ACCESS_CONTROL   =ON
ACCESS_CONTROL_FILE     =/home1/cubrid/access_file.txt
[%QUERY_EDITOR]
SERVICE                 =ON
BROKER_PORT             =30000
......

The following example shows the content of ACCESS_CONTROL_FILE. The * symbol represents everything, and you can use it when you want to specify database names, database user IDs and IPs in the IP list file which are allowed to access the broker server.

[%QUERY_EDITOR]
dbname1:dbuser1:READIP.txt
dbname1:dbuser2:WRITEIP1.txt,WRITEIP2.txt
*:dba:READIP.txt
*:dba:WRITEIP1.txt
*:dba:WRITEIP2.txt

[%BROKER2]
dbname:dbuser:iplist2.txt

[%BROKER3]
dbname:dbuser:iplist2.txt

[%BROKER4]
dbname:dbuser:iplist2.txt

The brokers specified above are QUERY_EDITOR, BROKER2, BROKER3, and BROKER4.

The QUERY_EDITOR broker only allows the following application access requests.

  • When a user logging into dbname1 with a dbuser1 account connects from IPs registered in READIP.txt
  • When a user logging into dbname1 with a dbuser2 account connects from IPs registered in WRITEIP1.txt and WRITEIP2.txt
  • When a user logging into every database with a DBA account connects from IPs registered in READIP.txt, WRITEIP1.txt, and WRITEIP2.txt

The following example shows how to specify the IPs allowed in ip_list_file.

192.168.1.25
192.168.*
10.*
*

The descriptions for the IPs specified in the example above are as follows:

  • The first line setting allows an access from 192.168.1.25.
  • The second line setting allows an access from all IPs starting with 192.168.
  • The third line setting allows an access from all IPs starting with 10.
  • The fourth line setting allows an access from all IPs.

For the broker which has already been running, you can modify the configuration file or check the currently applied status of configuration by using the following commands.

To configure databases, database user IDs and IPs allowed to access the broker and then apply the modified configuration to the server, use the following command.

cubrid broker acl reload [<BR_NAME>]
  • <BR_NAME>: A broker name. If you specify this value, you can apply the changes only to specified brokers. If you omit it, you can apply the changes to all brokers.

To display the databases, database user IDs and IPs that are allowed to access the broker in running on the screen, use the following command.

cubrid broker acl status [<BR_NAME>]
  • <BR_NAME>: A broker name. If you specify the value, you can display the specified broker configuration. If you omit it, you can display all broker configurations.

The below is an example of displaying results.

$ cubrid broker acl status
ACCESS_CONTROL=ON
ACCESS_CONTROL_FILE=access_file.txt

[%broker1]
demodb:dba:iplist1.txt
       CLIENT IP LAST ACCESS TIME
==========================================
    10.20.129.11
  10.113.153.144 2013-11-07 15:19:14
  10.113.153.145
  10.113.153.146
         10.64.* 2013-11-07 15:20:50

testdb:dba:iplist2.txt
       CLIENT IP LAST ACCESS TIME
==========================================
               * 2013-11-08 10:10:12

Broker Logs

If you try to access brokers through IP addresses that are not allowed, the following logs will be created.

  • ACCESS_LOG
1 192.10.10.10 - - 1288340944.198 1288340944.198 2010/10/29 17:29:04 ~ 2010/10/29 17:29:04 14942 - -1 db1 dba : rejected
  • SQL LOG
10/29 10:28:57.591 (0) CLIENT IP 192.10.10.10 10/29 10:28:57.592 (0) connect db db1 user dba url jdbc:cubrid:192.10.10.10:30000:db1::: - rejected

Note

For details on how to limit an access to the database server, see Limiting Database Server Access.

Managing a Specific Broker

Enter the code below to run broker1 only. Note that broker1 should have already been configured in the shared memory.

% cubrid broker on broker1

The following message is returned if broker1 has not been configured in the shared memory.

% cubrid broker on broker1
Cannot open shared memory

Enter the code below to stop broker1 only. Note that service pool of broker1 can also be removed.

% cubrid broker off broker1

The broker reset feature enables broker application servers (CAS) to disconnect the existing connection and reconnect when the servers are connected to unwanted databases due to failover, etc. in HA. For example, once Read Only broker is connected to active servers, it is not automatically connected to standby servers although standby servers are available. Connecting to standby servers is allowed only with the cubrid broker reset command.

Enter the code below to reset broker1.

% cubrid broker reset broker1
Dynamically Changing Broker Parameters

You can configure the parameters related to running the broker in the configuration file ( cubrid_broker.conf ). You can also modify some broker parameters temporarily while the broker is running by using the broker_changer utility. For details, see Broker Configuration.

The syntax for the broker_changer utility, which is used to change broker parameters while the broker is running, is as follows. Enter the name of the currently running broker for the broker_name . The parameters can be used only for dynamically modifiable parameters. The value must be specified based on the parameter to be modified. You can specify the broker CAS identifier ( cas_id ) to apply the changes to the specific broker CAS.

cas_id is an ID to be output by cubrid broker status command.

broker_changer broker_name [cas_id] parameters value

Enter the following to configure the SQL_LOG parameter to ON so that SQL logs can be written to the currently running broker. Such dynamic parameter change is effective only while the broker is running.

% broker_changer query_editor sql_log on
OK

Enter the following to change the ACCESS_MODE to Read Only and automatically reset the broker in HA environment.

% broker_changer broker_m access_mode ro
OK

Note

If you want to control the service using cubrid utilities on Windows Vista or the later versions of Window, you are recommended to open the command prompt window as an administrator. For details, see the notes of CUBRID Utilities.

Broker configuration information

cubrid broker info dumps the currently "working" broker parameters' configuration information(cubrid_broker.conf). broker parameters' information can be dynamically changed by broker_changer command; with cubrid broker info command, you can see the configuration information of the working broker.

% cubrid broker info

As a reference, to see the configuration information of the currently "working" system(cubrid.conf), use cubrid paramdump database_name command. By SET SYSTEM PARAMETERS syntax, the configuration information of the system parameters can be changed dynamically; with cubrid broker info command, you can see the configuration information of the system parameters.

Broker Logs

There are three types of logs that relate to starting the broker: access, error and SQL logs. Each log can be found in the log directory under the installation directory. You can change the directory where these logs are to be stored through LOG_DIR and ERROR_LOG_DIR parameters of the broker configuration file (cubrid_broker.conf).

Checking the Access Log

The access log file records information on the application client and is stored to $CUBRID/log/broker/<broker_name>.access file. If the LOG_BACKUP parameter is configured to ON in the broker configuration file, when the broker stops properly, the access log file is stored with the date and time that the broker has stopped. For example, if broker1 stopped at 12:27 P.M. on June 17, 2008, an access file named broker1.access.20080617.1227 is generated in the log/broker directory. The following example shows an access log.

The following example and description show an access log file created in the log directory:

1 192.168.1.203 - - 972523031.298 972523032.058 2008/06/17 12:27:46~2008/06/17 12:27:47 7118 - -1
2 192.168.1.203 - - 972523052.778 972523052.815 2008/06/17 12:27:47~2008/06/17 12:27:47 7119 ERR 1025
1 192.168.1.203 - - 972523052.778 972523052.815 2008/06/17 12:27:49~2008/06/17 12:27:49 7118 - -1
  • 1: ID assigned to the application server of the broker
  • 192.168.1.203: IP address of the application client
  • 972523031.298: UNIX timestamp value when the client's request processing started
  • 2008/06/17 12:27:46: Time when the client's request processing started
  • 972523032.058: UNIX timestamp value when the client's request processing finished
  • 2008/06/17 12:27:47: Time when the client's request processing finished
  • 7118: Process ID of the application server
  • -1: No error occurred during the request processing
  • ERR 1025: Error occurred during the request processing. Error information exists in offset=1025 of the error log file
Checking the Error Log

The error log file records information on errors that occurred during the client's request processing and is stored to $CUBRID/log/broker/error_log<broker_name>_<app_server_num>.err file. For error codes and error messages, see CAS Error.

The following example and description show an error log:

Time: 02/04/09 13:45:17.687 - SYNTAX ERROR *** ERROR CODE = -493, Tran = 1, EID = 38
Syntax: Unknown class "unknown_tbl". select * from unknown_tbl
  • Time: 02/04/09 13:45:17.687: Time when the error occurred
    • SYNTAX ERROR: Type of error (e.g. SYNTAX ERROR, ERROR, etc.)
  • *** ERROR CODE = -493: Error code
  • Tran = 1: Transaction ID. -1 indicates that no transaction ID is assigned.
  • EID = 38: Error ID. This ID is used to find the SQL log related to the server or client logs when an error occurs during SQL statement processing.
  • Syntax ...: Error message (An ellipsis ( ... ) indicates omission.)
Managing the SQL Log

The SQL log file records SQL statements requested by the application client and is stored with the name of <broker_name>_<app_server_num>. sql.log. The SQL log is generated in the log/broker/sql_log directory when the SQL_LOG parameter is set to ON. Note that the size of the SQL log file to be generated cannot exceed the value set for the SQL_LOG_MAX_SIZE parameter. CUBRID offers the broker_log_top and cubrid_replay utilities to manage SQL logs. Each utility should be executed in a directory where the corresponding SQL log exists.

The following examples and descriptions show SQL log files:

13-06-11 15:07:39.282 (0) STATE idle
13-06-11 15:07:44.832 (0) CLIENT IP 192.168.10.100
13-06-11 15:07:44.835 (0) CLIENT VERSION 9.2.0.0062
13-06-11 15:07:44.835 (0) session id for connection 0
13-06-11 15:07:44.836 (0) connect db demodb user dba url jdbc:cubrid:192.168.10.200:30000:demodb:dba:********: session id 12
13-06-11 15:07:44.836 (0) DEFAULT isolation_level 3, lock_timeout -1
13-06-11 15:07:44.840 (0) end_tran COMMIT
13-06-11 15:07:44.841 (0) end_tran 0 time 0.000
13-06-11 15:07:44.841 (0) *** elapsed time 0.004

13-06-11 15:07:44.844 (0) check_cas 0
13-06-11 15:07:44.848 (0) set_db_parameter lock_timeout 1000
13-06-11 15:09:36.299 (0) check_cas 0
13-06-11 15:09:36.303 (0) get_db_parameter isolation_level 3
13-06-11 15:09:36.375 (1) prepare 0 CREATE TABLE unique_tbl (a INT PRIMARY key);
13-06-11 15:09:36.376 (1) prepare srv_h_id 1
13-06-11 15:09:36.419 (1) set query timeout to 0 (no limit)
13-06-11 15:09:36.419 (1) execute srv_h_id 1 CREATE TABLE unique_tbl (a INT PRIMARY key);
13-06-11 15:09:38.247 (1) execute 0 tuple 0 time 1.827
13-06-11 15:09:38.247 (0) auto_commit
13-06-11 15:09:38.344 (0) auto_commit 0
13-06-11 15:09:38.344 (0) *** elapsed time 1.968

13-06-11 15:09:54.481 (0) get_db_parameter isolation_level 3
13-06-11 15:09:54.484 (0) close_req_handle srv_h_id 1
13-06-11 15:09:54.484 (2) prepare 0 INSERT INTO unique_tbl VALUES (1);
13-06-11 15:09:54.485 (2) prepare srv_h_id 1
13-06-11 15:09:54.488 (2) set query timeout to 0 (no limit)
13-06-11 15:09:54.488 (2) execute srv_h_id 1 INSERT INTO unique_tbl VALUES (1);
13-06-11 15:09:54.488 (2) execute 0 tuple 1 time 0.001
13-06-11 15:09:54.488 (0) auto_commit
13-06-11 15:09:54.505 (0) auto_commit 0
13-06-11 15:09:54.505 (0) *** elapsed time 0.021

...

13-06-11 15:19:04.593 (0) get_db_parameter isolation_level 3
13-06-11 15:19:04.597 (0) close_req_handle srv_h_id 2
13-06-11 15:19:04.597 (7) prepare 0 SELECT * FROM unique_tbl  WHERE ROWNUM BETWEEN 1 AND 5000;
13-06-11 15:19:04.598 (7) prepare srv_h_id 2 (PC)
13-06-11 15:19:04.602 (7) set query timeout to 0 (no limit)
13-06-11 15:19:04.602 (7) execute srv_h_id 2 SELECT * FROM unique_tbl  WHERE ROWNUM BETWEEN 1 AND 5000;
13-06-11 15:19:04.602 (7) execute 0 tuple 1 time 0.001
13-06-11 15:19:04.607 (0) end_tran COMMIT
13-06-11 15:19:04.607 (0) end_tran 0 time 0.000
13-06-11 15:19:04.607 (0) *** elapsed time 0.009
  • 13-06-11 15:07:39.282: Time when the application sent the request
  • (1): Sequence number of the SQL statement group. If prepared statement pooling is used, it is uniquely assigned to each SQL statement in the file.
  • CLIENT IP: An IP of an application client
  • CLIENT VERSION: A driver's version of an application client
  • prepare 0: Whether or not it is a prepared statement
  • prepare srv_h_id 1: Prepares the SQL statement as srv_h_id 1.
  • (PC): It is displayed if the data in the plan cache is used.
  • Execute 0 tuple 1 time 0.001: One row is executed. The time spent is 0.001 seconds.
  • auto_commit/auto_rollback: Automatically committed or rolled back. The second auto_commit/auto_rollback is an error code. 0 indicates that the transaction has been completed without an error.
broker_log_top

The broker_log_top utility analyzes the SQL logs which are generated for a specific period. As a result, the information of SQL statements and time execution are displayed in files by order of the longest execution time; the results of SQL statements are stored in log.top.q and those of execution time are stored in log.top.res, respectively.

The broker_log_top utility is useful to analyze a long running query. The syntax is as follows:

broker_log_top [options] sql_log_file_list
  • sql_log_file_list: names of log files to analyze.

The following is [options] used on broker_log_top.

-t

The result is displayed in transaction unit.

-F DATETIME

Specifies the execution start date and time of the SQL statements to be analyzed. The input format is YY[-MM[-DD[ hh[:mm[:ss[.msec]]]]]], and the part enclosed by [] can be omitted. If you omit the value, it is regarded as that 01 is input for MM and DD, and 0 is input for hh, mm, ss and msec.

-T DATETIME

Specifies the execution end date and time of the SQL statements to be analyzed. The input format is the same with the DATE in the -F options.

All logs are displayed by SQL statement if any option is not specified.

The following sets the search range to milliseconds

broker_log_top -F "01/19 15:00:25.000" -T "01/19 15:15:25.180" log1.log

The part where the time format is omitted is set to 0 by default. This means that -F "01/19 00:00:00.000" -T "01/20 00:00:00.000" is input.

broker_log_top -F "01/19" -T "01/20" log1.log

The following logs are the results of executing the broker_log_top utility; logs are generated from Nov. 11th to Nov. 12th, and it is displayed in the order of the longest execution of SQL statements. Each month and day are separated by a slash (/) when specifying period. Note that "*.sql.log" is not recognized so the SQL logs should be separated by a white space on Windows.

--Execution broker_log_top on Linux
% broker_log_top -F "11/11" -T "11/12" -t *.sql.log

query_editor_1.sql.log
query_editor_2.sql.log
query_editor_3.sql.log
query_editor_4.sql.log
query_editor_5.sql.log

--Executing broker_log_top on Windows
% broker_log_top -F "11/11" -T "11/12" -t query_editor_1.sql.log query_editor_2.sql.log query_editor_3.sql.log query_editor_4.sql.log query_editor_5.sql.log

The log.top.q and log.top.res files are generated in the same directory where the analyzed logs are stored when executing the example above; In the log.top.q file, you can see each SQL statement, and its line number. In the log.top.res file, you can see the minimum execution time, the maximum execution time, the average execution time, and the number of execution queries for each SQL statement.

--log.top.q file
[Q1]-------------------------------------------
broker1_6.sql.log:137734
11/11 18:17:59.396 (27754) execute_all srv_h_id 34 select a.int_col, b.var_col from dml_v_view_6 a, dml_v_view_6 b, dml_v_view_6 c , dml_v_view_6 d, dml_v_view_6 e where a.int_col=b.int_col and b.int_col=c.int_col and c.int_col=d.int_col and d.int_col=e.int_col order by 1,2;
11/11 18:18:58.378 (27754) execute_all 0 tuple 497664 time 58.982
.
.
[Q4]-------------------------------------------
broker1_100.sql.log:142068
11/11 18:12:38.387 (27268) execute_all srv_h_id 798 drop table list_test;
11/11 18:13:08.856 (27268) execute_all 0 tuple 0 time 30.469

--log.top.res file

              max       min        avg   cnt(err)
-----------------------------------------------------
[Q1]        58.982    30.371    44.676    2 (0)
[Q2]        49.556    24.023    32.688    6 (0)
[Q3]        35.548    25.650    30.599    2 (0)
[Q4]        30.469     0.001     0.103 1050 (0)
cubrid_replay

cubrid_replay utility replays the SQL log in the broker and outputs the results sorted in order from the large difference(from the slower query than the existing one) by comparing the difference in the execution time of playback and the existing execution time.

This utility plays back the queries that are logged in the SQL log, but does not execute the queries to change the data. If any options are not given, only SELECT queries are run; if -r option is given, it changes the UPDATE and DELETE queries into SELECT queries and runs them.

This utility can be used to compare the performance between two different hosts; for example, there can be a performance difference for a same query between master and slave even if their h/w specs are the same.

cubrid_replay -I <broker_host> -P <broker_port> -d <db_name> [options] <sql_log_file> <output_file>
  • broker_host: IP address or host name of the CUBRID broker
  • broker_port: Port number of the CUBRID broker
  • db_name: The name of database to run the query
  • sql_log_file: SQL log file of the CUBRID broker($CUBRID/log/broker/sql_log/*.log, *.log.bak)
  • output_file: File name to save the execution result

The following is [options] used in cubrid_replay.

-u DB_USER

Specifies the DB account(default: public).

-p DB_PASSWORD

Specifies database password

-r

Changes UPDATE and DELETE queries into SELECT queries

-h SECOND

Specifies the term to wait between queries to run(default: 0.01 sec)

-D SECOND

The queries are output to output_file only when the specified term is bigger than (replayed execution time - previous execution time)(default: 0.01 sec).

-F DATETIME

Specifies the execution start date and time of the SQL statements to be replayed. The input format is YY[-MM[-DD[ hh[:mm[:ss[.msec]]]]]], and the part enclosed by [] can be omitted. If you omit the value, it is regarded as that 01 is input for MM and DD, and 0 is input for hh, mm, ss and msec.

-T DATETIME

Specifies the execution end date and time of the SQL statements to be replayed. The input format is the same with the DATE in the -F options.

$ cubrid_replay -I testhost -P 33000 -d testdb -u dba -r testdb_1_11_1.sql.log.bak output.txt

If you run the above command, the summary of execution result is displayed on th console.

------------------- Result Summary --------------------------
* Total queries : 153103
* Skipped queries (see skip.sql) : 5127
* Error queries (see replay.err) : 30
* Slow queries (time diff > 0.000 secs) : 89987
* Max execution time diff : 0.016
* Avg execution time diff : -0.001

cubrid_replay run time : 245.308417 sec
  • Total queries: Number of total queries within the specified date and time. They include DDL and DML
  • Skipped queries: Number of queries which cannot be changed from UPDATE/DELETE into SELECT when -r option is specified. These queries are saved into skip.sql
  • Slow queries: Number of queries of which execution time difference is bigger than the specified value by -D option(the replayed execution time is slower than the previous execution time plus the specified value). If you omit the -D option, this option value is specified as 0.01 second
  • Max execution time diff: The biggest value among the differences of the execution time(unit: sec)
  • Avg execution time diff: Average value of the differences of the execution time(unit: sec)
  • cubrid_replay run time: Execution time of this utility

"Skipped queries" are the cases which query-transform from UPDATE/DELETE to SELECT is impossible by the internal reason; the queries which are written to skip.sql are needed to check separately.

Also, you should consider that the execution time of the transformed queries does not include the data modification time.

In the output.txt file, SQLs that the replayed SQL execution time is slower than the SQL execution time in SQL log are written. That is, {(the replayed SQL execution time) - {(the execution time in SQL log) + (the specified time by -D option)} is sorted in descending order. Because -r option is used, UPDATE/DELETE is rewritten into SELECT and run.

EXEC TIME (REPLAY / SQL_LOG / DIFF): 0.003 / 0.001 / 0.002
SQL: UPDATE NDV_QUOTA_INFO SET last_mod_date = now() , used_quota = ( SELECT IFNULL(sum(file_size),0) FROM NDV_RECYCLED_FILE_INFO WHERE user_id = ? ) + ( SELECT IFNULL(sum(file_size),0) FROM NDV_FILE_INFO WHERE user_id = ? ) WHERE user_id = ? /* SQL : NDVMUpdResetUsedQuota */
REWRITE SQL: select NDV_QUOTA_INFO, class NDV_QUOTA_INFO, cast( SYS_DATETIME as datetime), cast((select ifnull(sum(NDV_RECYCLED_FILE_INFO.file_size), 0) from NDV_RECYCLED_FILE_INFO NDV_RECYCLED_FILE_INFO where (NDV_RECYCLED_FILE_INFO.user_id= ?:0 ))+(select ifnull(sum(NDV_FILE_INFO.file_size), 0) from NDV_FILE_INFO NDV_FILE_INFO where (NDV_FILE_INFO.user_id= ?:1 )) as bigint) from NDV_QUOTA_INFO NDV_QUOTA_INFO where (NDV_QUOTA_INFO.user_id= ?:2 )
BIND 1: 'babaemo'
BIND 2: 'babaemo'
BIND 3: 'babaemo'
  • EXEC TIME: (replay time / execution time in the SQL log / difference between the two execution times)
  • SQL: The original SQL which exists in the SQL log of the broker
  • REWRITE SQL: Transformed SELECT queries from UPDATE/DELETE queries by -r option.

Note

broker_log_runner is deprecated from 9.3. Therefore, instead of broker_log_runner, use cubrid_replay.

CAS Error

CAS error is an error which occurs in broker application server(CAS), and it can happen on all applications which access to CAS with drivers.

Below shows the CAS error code table. CCI and JDBC's error messages can be different each other on the same CAS error code. If there is only one message, they are the same, but if there are two messages, then the first one is CCI error message and the second one is JDBC error message.

Error Code Name(Error Number) Error Message (CCI / JDBC) Note
CAS_ER_INTERNAL(-10001)    
CAS_ER_NO_MORE_MEMORY(-10002) Memory allocation error  
CAS_ER_COMMUNICATION(-10003) Cannot receive data from client / Communication error  
CAS_ER_ARGS(-10004) Invalid argument  
CAS_ER_TRAN_TYPE(-10005) Invalid transaction type argument / Unknown transaction type  
CAS_ER_SRV_HANDLE(-10006) Server handle not found / Internal server error  
CAS_ER_NUM_BIND(-10007) Invalid parameter binding value argument / Parameter binding error The number of data to be bound does not match with the number of data to be transferred.
CAS_ER_UNKNOWN_U_TYPE(-10008) Invalid T_CCI_U_TYPE value / Parameter binding error  
CAS_ER_DB_VALUE(-10009) Cannot make DB_VALUE  
CAS_ER_TYPE_CONVERSION(-10010) Type conversion error  
CAS_ER_PARAM_NAME(-10011) Invalid T_CCI_DB_PARAM value / Invalid database parameter name The name of the system parameter is not valid.
CAS_ER_NO_MORE_DATA(-10012) Invalid cursor position / No more data  
CAS_ER_OBJECT(-10013) Invalid oid / Object is not valid  
CAS_ER_OPEN_FILE(-10014) Cannot open file / File open error  
CAS_ER_SCHEMA_TYPE(-10015) Invalid T_CCI_SCH_TYPE value / Invalid schema type  
CAS_ER_VERSION(-10016) Version mismatch The DB server version does not compatible with the client (CAS) version.
CAS_ER_FREE_SERVER(-10017) Cannot process the request. Try again later The CAS which handles connection request of applications cannot be assigned.
CAS_ER_NOT_AUTHORIZED_CLIENT(-10018) Authorization error Access is denied.
CAS_ER_QUERY_CANCEL(-10019) Cannot cancel the query  
CAS_ER_NOT_COLLECTION(-10020) The attribute domain must be the set type  
CAS_ER_COLLECTION_DOMAIN(-10021) Heterogeneous set is not supported / The domain of a set must be the same data type  
CAS_ER_NO_MORE_RESULT_SET(-10022) No More Result  
CAS_ER_INVALID_CALL_STMT(-10023) Illegal CALL statement  
CAS_ER_STMT_POOLING(-10024) Invalid plan  
CAS_ER_DBSERVER_DISCONNECTED(-10025) Cannot communicate with DB Server  
CAS_ER_MAX_PREPARED_STMT_COUNT_EXCEEDED(-10026) Cannot prepare more than MAX_PREPARED_STMT_COUNT statements  
CAS_ER_HOLDABLE_NOT_ALLOWED(-10027) Holdable results may not be updatable or sensitive  
CAS_ER_HOLDABLE_NOT_ALLOWED_KEEP_CON_OFF(-10028) Holdable results are not allowed while KEEP_CONNECTION is off  
CAS_ER_NOT_IMPLEMENTED(-10100) None / Attempt to use a not supported service  
CAS_ER_IS(-10200) None / Authentication failure  

CUBRID Manager Server

Starting the CUBRID Manager Server

The following example shows how to start the CUBRID Manager server.

% cubrid manager start

The following message is returned if the CUBRID Manager server is already running.

% cubrid manager start
@ cubrid manager server start
++ cubrid manager server is running.
Stopping the CUBRID Manager Server

The following example shows how to stop the CUBRID Manager server.

% cubrid manager stop
@ cubrid manager server stop
++ cubrid manager server stop: success
CUBRID Manager Server Log

The logs of CUBRID Manager server are stored in the log/manager directory under the installation directory. There are four types of log files depending on server process of CUBRID Manager.

  • auto_backupdb.log: Backup log about the backup-automated jobs which was reserved by the CUBRID Manager Client
  • auto_execquery.log: Execution log about the query-automated jobs which was reserved by the CUBRID Manager Client
  • cub_js.access.log: Access log regarding the successful logins and tasks in CUBRID Manager Server.
  • cub_js.error.log: Access log regarding the failed logins and tasks in CUBRID Manager Server.
Configuring CUBRID Manager Server

The configuration file name for the CUBRID Manager server is cm.conf and located in the $CUBRID/conf directory. In the CUBRID Manager server configuration file, where parameter names and values are stored, comments are prefaced by "#." Parameter names and values are separated by spaces or an equal sign (=).

This page describes parameters that are specified in the cm.conf file.

cm_port

cm_port is a parameter used to configure a communication port for the connection between the CUBRID Manager server and the client. The default value is 8001 .

monitor_interval

monitor_interval is a parameter used to configure the monitoring interval of cub_auto in seconds. The default value is 5 .

allow_user_multi_connection

allow_user_multi_connection is a parameter used to have multiple client connections allowed to the CUBRID Manager server. The default value is YES . Therefore, more than one CUBRID Manager client can connect to the CUBRID Manager server, even with the same user name.

server_long_query_time

server_long_query_time is a parameter used to configure delay reference time in seconds when configuring slow_query which is one of server diagnostics items. The default value is 10 . If the execution time of the query performed on the server exceeds this parameter value, the number of the slow_query parameters will increase.

support_web_manager

support_web_manager is a parameter used to configure starting CUBRID Web Manager or not. The default value is NO.

web_manager_path

web_manager_path is a parameter used to configure a path of CUBRID Web Manager. The default value is {CUBRID installed path}/share/webmanager.

auto_job_timeout

auto_job_timeout is a parameter used to configure timeout of auto job for cub_auto. The default value is 43200 (12 hour).

mon_cub_auto

mon_cub_auto is a parameter used to allow cub_js to restart cub_auto process when cub_auto is not running or not. The default value is NO.

token_active_time

token_active_time is a parameter used to configure timeout of token. The default value is 7200 (2 hour).

support_mon_statistic

support_mon_statistic is a parameter used to configure monitoring statistic of system or not. The default value is NO.

cm_process_monitor_interval

cm_process_monitor_interval is an interval time for collecting statistics. The default and the minimum value is 5 (5 minutes).
CUBRID Manager User Management Console

The account and password of CUBRID Manager user are used to access the CUBRID Manager server when starting the CUBRID Manager client, distinguishing this user from the database user. CUBRID Manager Administrator (cm_admin) is a CLI tool that manages user information and it executes commands in the console window to manage users. This utility only supports Linux OS.

The following shows how to use the CUBRID Manager (hereafter, CM) Administrator utilities. The utilities can be used through GUI on the CUBRID Manager client.

cm_admin <utility_name>
<utility_name>:
    adduser [<option>] <cmuser-name> <cmuser-password>   --- Adds a CM user
    deluser <cmuser-name>   --- Deletes a CM user
    viewuser [<cmuser-name>]   --- Displays CM user information
    changeuserauth [<option>] <cmuser-name>  --- Changes the CM user authority
    changeuserpwd [<option>] <cmuser-name>  --- Changes the CM user password
    adddbinfo [<option>] <cmuser-name> <database-name>  --- Adds database information of the CM user
    deldbinfo <cmuser-name> <database-name>  --- Deletes database information of the CM user
    changedbinfo [<option>] <database-name> number-of-pages --- Changes database information of the CM user

CM Users

Information about CM users consists of the following:

  • CM user authority: Includes the following information.
    • The permission to configure broker
    • The permission to create a database. For now, this authority is only given to the admin user.
    • The permission to monitor status
  • Database information: A database that a CM user can use
  • CM user password

The default user authority of CUBRID Manager is admin and its password is admin. Users who has admin authority have full administrative controls.

Adding CM Users

The cm_admin adduser utility creates a CM user who has been granted a specific authority and has database information. The permissions to configure broker, create a database, and monitor status can be granted to the CM user.

cm_admin adduser [options] cmuser-name cmuser-password
  • cm_admin: An integrated utility to manage CUBRID Manager
  • adduser: A command to create a new CM user
  • cmuser-name: Specifies a unique name to a CM user. Usable characters are 0~9, A~Z, a~z and _. Minimum length is 4 and maximum length is 32. If the specified name in cmuser-name is identical to the existing one, cm_admin will stop creating a new CM user.
  • cmuser-password: A password of a CM user. Usable characters are 0~9, A~Z, a~z and _. Minimum length is 4 and maximum length is 32.

The following is [options] of cm_admin adduser.

-b, --broker AUTHORITY

Specifies the broker authority which will be granted to a new CM user.

You can use admin, none (default), and monitor as AUTHORITY

The following example shows how to create a CM user whose name is testcm and password is testcmpwd and then configure broker authority to monitor.

cm_admin adduser -b monitor testcm testcmpwd
-c, --dbcreate AUTHORITY

Specifies the authority to create a database which will be granted to a new CM user.

You can use none (default) and admin as AUTHORITY.

The following example shows how to create a CM user whose name is testcm and password is testcmpwd and then configure database creation authority to admin.

cm_admin adduser -c admin testcm testcmpwd
-m, --monitor AUTHORITY

Specifies the authority to monitor status which will be granted to a new CM user. You can use admin, none (default), and monitor as AUTHORITY

The following example shows how to create a CM user whose name is testcm and password is testcmpwd and then configure monitoring authority to admin.

cm_admin adduser -m admin testcm testcmpwd
-d, --dbinfo INFO_STRING

Specifies database information of a new CM user. The format of INFO_STRING must be "<dbname>;<uid>;<broker_ip>,<broker_port>". The following example shows how to add database information "testdb;dba;localhost,30000" to a CM user named testcm .

cm_admin adduser -d "testdb;dba;localhost,30000" testcm testcmpwd

Deleting CM Users

The cm_admin deluser utility deletes a CM user.

cm_admin deluser cmuser-name
  • cm_admin: An integrated utility to manage CUBRID Manager
  • deluser: A command to delete an existing CM user
  • cmuser-name: The name of a CM user to be deleted

The following example shows how to delete a CM user named testcm.

cm_admin deluser testcm

Displaying CM User information

The cm_admin viewuser utility displays information of a CM user.

cm_admin viewuser cmuser-name
  • cm_admin: An integrated utility to manage CUBRID Manager
  • viewuser: A command to display the CM user information
  • cmuser-name: A CM user name. If this value is entered, information only for the specified user is displayed; if it is omitted, information for all CM users is displayed.

The following example shows how to display information of a CM user named testcm .

cm_admin viewuser testcm

The information will be displayed as follows:

CM USER: testcm
  Auth info:
    broker: none
    dbcreate: none
    statusmonitorauth: none
  DB info:
    ==========================================================================================
     DBNAME                                           UID               BROKER INFO
    ==========================================================================================
     testdb                                           dba               localhost,30000

Changing the Authority of CM Users

The cm_admin changeuserauth utility changes the authority of a CM user.

cm_admin changeuserauth options cmuser-name
  • cm_admin: An integrated utility to manage CUBRID Manager
  • changeuserauth: A command to change the authority of a CM user
  • cmuser-name: The name of a CM user whose authority to be changed

The following is [options] of cm_admin changeuserauth.

-b, --broker AUTHORITY

Specifies the broker authority that will be granted to a CM user. You can use admin, none, and monitor as AUTHORITY.

The following example shows how to change the broker authority of a CM user named testcm to monitor.

cm_admin changeuserauth -b monitor testcm
-c, --dbcreate

Specifies the authority to create a database which will be granted to a CM user. You can use admin and none as AUTHORITY .

The following example shows how to change the database creation authority of a CM user named testcm to admin.

cm_admin changeuserauth -c admin testcm
-m, --monitor

Specifies the authority to monitor status which will be granted to a CM user. You can use admin, none, and monitor as AUTHORITY.

The following example shows how to change the monitoring authority of a CM user named testcm to admin.

cm_admin changeuserauth -m admin testcm

Changing the CM User Password

The cm_admin changeuserpwd utility changes the password of a CM user.

cm_admin changeuserpwd [options] cmuser-name
  • cm_admin: An integrated utility to manage CUBRID Manager
  • changeuserpwd: A command to change the password of a CM user
  • cmuser-name: The name of a CM user whose password to be changed

The following is [options] of cm_admin changeuserpwd.

-o, --oldpass PASSWORD

Specifies the existing password of a CM user.

The following example shows how to change a password of a CM user named testcm .

cm_admin changeuserpwd -o old_password -n new_password testcm
--adminpass PASSWORD

The password of an admin user can be specified instead of old CM user's password that you don't know.

The following example shows how to change a password of a CM user named testcm by using an admin password.

cm_admin changeuserauth --adminpass admin_password -n new_password testcm
-n, --newpass PASSWORD

Specifies a new password of a CM user.

Adding Database Information to CM Users

The cm_admin adddbinfo utility adds database information (database name, UID, broker IP, and broker port) to a CM user.

cm_admin adddbinfo options cmuser-name database-name
  • cm_admin: An integrated utility to manage CUBRID Manager
  • adddbinfo: A command to add database information to a CM user
  • cmuser-name: CM user name
  • database-name: The name of a database to be added

The following example shows how to add a database without specifying any user-defined values to a CM user named testcm .

cm_admin adddbinfo testcm testdb

The following is [options] of cm_admin adddbinfo.

-u, --uid ID

Specifies the ID of a database user to be added. The default value is dba.

The following example shows how to add a database whose name is testdb and user ID is cubriduser to a CM user named testcm.

cm_admin adddbinfo -u cubriduser testcm testdb
-h, --host IP

Specifies the host IP of a broker used when clients access a database. The default value is localhost.

The following example shows how to add a database whose name is testdb and the host IP of is 127.0.0.1 to a CM user named testcm.

cm_admin adddbinfo -h 127.0.0.1 testcm testdb
-p, --port NUMBER

Specifies the port number of a broker used when clients access a database. The default value: 30000.

Deleting database information from CM Users

The cm_admin deldbinfo utility deletes database information of a specified CM user.

cm_admin deldbinfo cmuser-name database-name
  • cm_admin: An integrated utility to manage CUBRID Manager
  • deldbinfo: A command to delete database information of a CM user
  • cmuser-name: CM user name
  • database-name: The name of a database to be deleted

The following example shows how to delete database information whose name is testdb from a CM user named testcm.

cm_admin deldbinfo testcm testdb

Changing Database Information of a CM user

The cm_admin changedbinfo utility changes database information of a specified CM user.

cm_admin changedbinfo [options] cmuser-name database-name
  • cm_admin: An integrated utility to manage CUBRID Manager
  • changedbinfo: A command to change database information of a CM user
  • cmuser-name: CM user name
  • database-name: The name of a database to be changed

The following is [options] of cm_admin changedbinfo.

-u, --uid ID

Specifies the ID of a database user.

The following example shows how to update user ID information to uid in the testdb database which belongs to a CM user named testcm .

cm_admin changedbinfo -u uid testcm testdb
-h, --host IP

Specifies the host of a broker used when clients access a database.

The following example shows how to update host IP information to 10.34.63.132 in the testdb database which belongs to a CM user named testcm .

cm_admin changedbinfo -h 10.34.63.132 testcm testdb
-p, --port NUMBER

Specifies the port number of a broker used when clients access a database.

The following example shows how to update broker port information to 33000 in the testdb database which belongs to a CM user named testcm .

cm_admin changedbinfo -p 33000 testcm testdb

Database Management

Database Users

A CUBRID database user can have members with the same authorization. If authorization A is granted to a user, the same authorization is also granted to all members belonging to the user. A database user and its members are called a "group."; a user who has no members is called a "user."

CUBRID provides DBA and PUBLIC users by default.

  • DBA can access every object in the database, that is, it has authorization at the highest level. Only DBA has sufficient authorization to add, alter and delete the database users.
  • All users including DBA are members of PUBLIC. Therefore, all database users have the authorization granted to PUBLIC . For example, if authorization B is added to PUBLIC group, all database members will automatically have the B authorization.
databases.txt File

CUBRID stores information on the locations of all existing databases in the databases.txt file. This file is called the "database location file." A database location file is used when CUBRID executes utilities for creating, renaming, deleting or replicating databases; it is also used when CUBRID runs each database. By default, this file is located in the databases directory under the installation directory. The directory is located through the environment variable CUBRID_DATABASES.

db_name db_directory server_host logfile_directory

The format of each line of a database location file is the same as defined by the above syntax; it contains information on the database name, database path, server host and the path to the log files. The following example shows how to check the contents of a database location file.

% more databases.txt

dist_testdb /home1/user/CUBRID/bin d85007 /home1/user/CUBRID/bin
dist_demodb /home1/user/CUBRID/bin d85007 /home1/user/CUBRID/bin
testdb /home1/user/CUBRID/databases/testdb d85007 /home1/user/CUBRID/databases/testdb
demodb /home1/user/CUBRID/databases/demodb d85007 /home1/user/CUBRID/databases/demodb

By default, the database location file is stored in the databases directory under the installation directory. You can change the default directory by modifying the value of the CUBRID_DATABASES environment variable. The path to the database location file must be valid so that the cubrid utility for database management can access the file properly. You must enter the directory path correctly and check if you have write permission on the file. The following example shows how to check the value configured in the CUBRID_DATABASES environment variable.

% set | grep CUBRID_DATABASES
CUBRID_DATABASES=/home1/user/CUBRID/databases

An error occurs if an invalid directory path is set in the CUBRID_DATABASES environment variable. If the directory path is valid but the database location file does not exist, a new location information file is created. If the CUBRID_DATABASES environment variable has not been configured at all, CUBRID retrieves the location information file in the current working directory.

Database Volume

The volumes of CUBRID database are classified as permanent volume, temporary volume and backup volume.

  • In the permanent volumes,
    • there are generic, data, index and temp volumes in database volumes.
    • there are an active log, an archiving log and a background archiving log in log volumes.
  • In temporary volume, there is a temporary temp volume.

For more details on volumes, see Database Volume Structure.

The following is an example of files related to the database when testdb database operates.

File name Size Type Classification Description
testdb 40MB generic Database volume The firstly created volume when DB is created. This is used as generic volume and includes the meta information of DB. The file size is 40M because "cubrid createdb" is executed after db_volume_size in cubrid.conf is specified as 40M or the option of "cubrid createdb", --db-volume-size is specified as 40M.
testdb_x001 40MB one of generic, data and index Automatically created generic file or a file created by the user's command for adding a volume. The size of generic file which was automatically created became 40MB because DB was started after specifying db_volume_size in cubrid.conf as 40M.
testdb_x002 40MB one of generic, data and index Automatically created generic file or a file created by the user's command for adding a volume.
testdb_x003 40MB one of generic, data and index Automatically created generic file or a file created by the user's command for adding a volume.
testdb_x004 40MB one of generic, data and index Automatically created generic file or a file created by the user's command for adding a volume.
testdb_x005 40MB one of generic, data and index Automatically created generic file or a file created by the user's command for adding a volume.
testdb_x006 2GB one of generic, data and index Automatically created generic file or a file created by the user's command for adding a volume. The size became 2GB because DB was restarted after specifying db_volume_size in cubrid.conf as 2G or the option of "cubrid addvoldb", --db-volume-size is specified as 2G.
testdb_t32766 360MB temporary temp Temp Volume a file created temporarily when the space of temp volume is insufficient during running the temp volume required query(e.g.: sorting, scanning, index creation). This is removed when DB is restarted. But, this should not be deleted arbitrarily.
testdb_lgar_t 40MB background archiving Log volume A log file which is related to the background archiving feature. This is used when storing the archiving log.
testdb_lgar224 40MB archiving Archiving logs are continuously archived and the files ending with three digits are created. At this time, archiving logs from 001~223 seem to be removed normally by "cubrid backupdb" -r option or the setting of log_max_archives in cubrid.conf. When archiving logs are removed, you can see the removed archiving log numbers in the REMOVE section of lginf file. See Managing Archive Logs.
testdb_lgat 40MB active Active log file
  • Database volume file
    • In the above, testdb, testdb_x001 ~ testdb_x006 are classified as the database volume files.
    • File size is determined by "db_volume_size" in cubrid.conf or the "--db-volume-size" option of "cubrid createdb" and "cubrid addvoldb".
    • The type of an automatically created volume is always generic.
  • Log volume file
    • In the above, testdb_lgar_t, testdb_lgar224 and testdb_lgat are classified as the log volume files.
    • File size is determined by "log_volume_size" in cubrid.conf or the "--log-volume-size" option of "cubrid createdb".

Note

Temp volume is a space where the intermediate and final results of query processing and sorting are temporarily stored; this is separated as temporary temp volume and permanent temp volume.

The examples of queries that can use permanent temp volume or temporary temp volume are as follows:

  • Queries creating the resultset like SELECT
  • Queries including GROUP BY or ORDER BY
  • Queries including a subquery
  • Queries executing sort-merge join
  • Queries including the CREATE INDEX statement

When executing the queries above, the temp volume is used after exhausting the memory space (the space size is determined by the system parameter temp_file_memory_size_in_pages specified in cubrid.conf) assigned to store SELECT results or sort the data. The order in which the storage space is used to store the results of query processing and sorting is as follows: when the current storage space is exhausted, the next storage space is used.

  • temp_file_memory_size_in_pages memory secured by the system parameter
  • Permanent temp volume
  • Temporary temp volume (for details, see the below)

To prevent the system from insufficient disk space (as the size of temporary temp volume is increased than expected because a query which requires a big-sized temp space is executed), we recommend that you should;

  • secure the expected permanent temp volume in advance and
  • limit the size of the space used in the temporary temp volume when a query is executed.

Permanent temp volume secures this space as running "cubrid addvoldb -p temp", and the maximum temporary temp space which is occupied during a query runs can be limited by the temp_file_max_size_in_pages (default is -1, which means infinite) parameter in cubrid.conf.

cubrid Utilities

The following shows how to use the cubrid management utilities.

cubrid utility_name
utility_name:
    createdb [option] <database_name> <locale_name>  --- Creating a database
    deletedb [option] <database_name>   --- Deleting a database
    installdb [option] <database-name>   --- Installing a database
    renamedb [option] <source-database-name> <target-database-name>  --- Renaming a database
    copydb [option] <source-database-name> <target-database-name>  --- Copying a database
    backupdb [option] <database-name>  --- Backing up a database
    restoredb [option] <database-name>  --- Restoring a database
    addvoldb [option] <database-name>  --- Adding a database volume file
    spacedb [option] <database-name>  --- Displaying details of database space
    lockdb [option] <database-name>  --- Displaying details of database lock
    tranlist [option] <database-name>  --- Checking transactions
    killtran [option] <database-name>  --- Removing transactions
    optimizedb [option] <database-name>  --- Updating database statistics
    statdump [option] <database-name>  --- Dumping statistic information of database server execution
    compactdb [option] <database-name>  --- Optimizing space by freeing unused space
    diagdb [option] <database-name>  --- Displaying internal information
    checkdb [option] <database-name>  --- Checking database consistency
    alterdbhost [option] <database-name>  --- Altering database host
    plandump [option] <database-name>  --- Displaying details of the query plan
    loaddb [option] <database-name>  --- Loading data and schema
    unloaddb [option] <database-name>  --- Unloading data and schema
    paramdump [option] <database-name>  --- Checking out the parameter values configured in a database
    changemode [option] <database-name>  --- Displaying or changing the server HA mode
    applyinfo [option] <database-name>   --- Displaying the status of being applied transaction log to the other node in HA replication environment
    synccolldb [option] <database-name>  --- Synchronizing the DB collation with the system collation
    genlocale [option] <database-name>  --- Compiling the locale information to use
    dumplocale [option] <database-name>   --- Printing human readable text for the compiled binary locale information
gen_tz [option] [<database-name>]  --- Generates C source file containing timezone data ready to be compiled into a shared library
dump_tz [option]  --- Displaying timezone related information
cubrid Utility Logging

CUBRID supports logging feature for the execution result of cubrid utilities; for details, see cubrid Utility Logging.

createdb

The cubrid createdb utility creates databases and initializes them with the built-in CUBRID system tables. It can also define initial users to be authorized in the database and specify the locations of the logs and databases. In general, the cubrid createdb utility is used only by DBA.

Warning

When you create database, a locale name and a charset name after a DB name must be specified(e.g. ko_KR.utf8). It affects the length of string type, string comparison operation, etc. The specified charset when creating database cannot be changed later, so you should be careful when specifying it.

For charset, locale and collation setting, see An Overview of Globalization.

cubrid createdb [options] database_name locale_name.charset
  • cubrid: An integrated utility for the CUBRID service and database management.
  • createdb: A command used to create a new database.
  • database_name: Specifies a unique name for the database to be created, without including the path name to the directory where the database will be created. If the specified database name is the same as that of an existing database name, CUBRID halts creation of the database to protect existing files.
  • locale_name: A locale name to use in the database should be input. For a locale name which can be used in CUBRID, refer to Step 1: Selecting a Locale.
  • charset: A characterset to use in the database should be input. A character set which can be used in CUBRID is iso88591, euckr or utf8.
    • If locale_name is en_US and charset is omitted, a character set will be iso88591.
    • If locale_name is ko_KR and charset is omitted, a character set will be utf8.
    • All locale names except en_US and ko_KR cannot omit charset, and a charset can be specified only with utf8.

The maximum length of database name is 17 in English.

The following shows [options] available with the cubrid createdb utility.

--db-volume-size=SIZE

This option specifies the size of the database volume that will be created first. The default value is the value of the system parameter db_volume_size, and the minimum value is 20M. You can set units as K, M, G and T, which stand for kilobytes (KB), megabytes (MB), gigabytes (GB), and terabytes (TB) respectively. If you omit the unit, bytes will be applied.

The following example shows how to create a database named testdb and assign 512 MB to its first volume.

cubrid createdb --db-volume-size=512M testdb en_US
--db-page-size=SIZE

This option specifies the size of the database page; the minimum value is 4K and the maximum value is 16K (default). K stands for kilobytes (KB). The value of page size is one of the following: 4K, 8K, or 16K. If a value between 4K and 16K is specified, system rounds up the number. If a value greater than 16K or less than 4K, the specified number is used.

The following example shows how to create a database named testdb and configure its page size 16K.

cubrid createdb --db-page-size=16K testdb en_US
--log-volume-size=SIZE

This option specifies the size of the database log volume. The default value is the same as database volume size, and the minimum value is 20M. You can set units as K, M, G and T, which stand for kilobytes (KB), megabytes (MB), gigabytes (GB), and terabytes (TB) respectively. If you omit the unit, bytes will be applied.

The following example shows how to create a database named testdb and assign 256 MB to its log volume.

cubrid createdb --log-volume-size=256M testdb en_US
--log-page-size=SIZE

This option specifies the size of the log volume page. The default value is the same as data page size. The minimum value is 4K and the maximum value is 16K. K stands for kilobytes (KB). The value of page size is one of the following: 4K, 8K, or 16K. If a value between 4K and 16K is specified, system rounds up the number. If a value greater than 16K or less than 4K, the specified number is used.

The following example shows how to create a database named testdb and configure its log volume page size 8K.

cubrid createdb --log-page-size=8K testdb en_US
--comment=COMMENT

This option specifies a comment to be included in the database volume header. If the character string contains spaces, the comment must be enclosed in double quotes.

The following example shows how to create a database named testdb and add a comment to the database volume.

cubrid createdb --comment "a new database for study" testdb en_US
-F, --file_path=PATH

The -F option specifies an absolute path to a directory where the new database will be created. If the -F option is not specified, the new database is created in the current working directory.

The following example shows how to create a database named testdb in the directory /dbtemp/new_db.

cubrid createdb -F "/dbtemp/new_db/" testdb en_US
-L, --log_path=PATH

The -L option specifies an absolute path to the directory where database log files are created. If the -L option is not specified, log files are created in the directory specified by the -F option. If neither -F nor -L option is specified, database log files are created in the current working directory.

The following example shows how to create a database named testdb in the directory /dbtemp/newdb and log files in the directory /dbtemp/db_log.

cubrid createdb -F "/dbtemp/new_db/" -L "/dbtemp/db_log/" testdb en_US
-B, --lob-base-path=PATH

This option specifies a directory where LOB data files are stored when BLOB/CLOB data is used. If the --lob-base-path option is not specified, LOB data files are store in <location of database volumes created>/lob directory.

The following example shows how to create a database named testdb in the working directory and specify /home/data1 of local file system as a location of LOB data files.

cubrid createdb --lob-base-path "file:/home1/data1" testdb en_US
--server-name=HOST

This option enables the server of a specific database to run in the specified host when CUBRID client/server is used. The information of a host specified is stored in the databases.txt file. If this option is not specified, the current localhost is specified by default.

The following example shows how to create a database named testdb and register it on the host aa_host.

cubrid createdb --server-name aa_host testdb en_US
-r, --replace

This option creates a new database and overwrites an existing database if one with the same name exists.

The following example shows how to create a new database named testdb and overwrite the existing database with the same name.

cubrid createdb -r testdb en_US
--more-volume-file=FILE

This option creates an additional volume based on the specification contained in the file specified by the option. The volume is created in the same directory where the database is created. Instead of using this option, you can add a volume by using the cubrid addvoldb utility.

The following example shows how to create a database named testdb as well as an additional volume based on the specification stored in the vol_info.txt file.

cubrid createdb --more-volume-file vol_info.txt testdb en_US

The following is a specification of the additional volume contained in the vol_info.txt file. The specification of each volume must be written on a single line.

#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# NAME volname COMMENTS volcmnts PURPOSE volpurp NPAGES volnpgs
NAME data_v1 COMMENTS "data information volume" PURPOSE data NPAGES 1000
NAME data_v2 COMMENTS "data information volume" PURPOSE data NPAGES 1000
NAME data_v3 PURPOSE data NPAGES 1000
NAME index_v1 COMMENTS "index information volume" PURPOSE index NPAGES 500
NAME temp_v1 COMMENTS "temporary information volume" PURPOSE temp NPAGES 500
NAME generic_v1 COMMENTS "generic information volume" PURPOSE generic NPAGES 500
#xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

As shown in the example, the specification of each volume consists following.

NAME volname COMMENTS volcmnts PURPOSE volpurp NPAGES volnpgs
  • volname: The name of the volume to be created. It must follow the UNIX file name conventions and be a simple name not including the directory path. The specification of a volume name can be omitted. If it is, the "database name to be created by the system_volume identifier" becomes the volume name.
  • volcmnts: Comment to be written in the volume header. It contains information on the additional volume to be created. The specification of the comment on a volume can also be omitted.
  • volpurp: It must be one of the following types: data, index, temp, or generic based on the purpose of storing volumes. The specification of the purpose of a volume can be omitted in which case the default value is generic.
  • volnpgs: The number of pages of the additional volume to be created. The specification of the number of pages of the volume cannot be omitted; it must be specified.
--user-definition-file=FILE

This option adds users who have access to the database to be created. It adds a user based on the specification contained in the user information file specified by the parameter. Instead of using the --user-definition-file option, you can add a user by using the CREATE USER statement (for details, see CREATE USER).

The following example shows how to create a database named testdb and add users to testdb based on the user information defined in the user_info.txt file.

cubrid createdb --user-definition-file=user_info.txt testdb en_US

The syntax of a user information file is as follows:

USER user_name [ <groups_clause> | <members_clause> ]

<groups_clause>:
    [ GROUPS <group_name> [ { <group_name> }... ] ]

<members_clause>:
    [ MEMBERS <member_name> [ { <member_name> }... ] ]
  • The user_name is the name of the user who has access to the database. It must not include spaces.
  • The GROUPS clause is optional. The group_name is the upper level group that contains the user_name . Here, the group_name can be multiply specified and must be defined as USER in advance.
  • The MEMBERS clause is optional. The member_name is the name of the lower level member that belongs to the user_name . Here, the member_name can be multiply specified and must be defined as USER in advance.

Comments can be used in a user information file. A comment line must begin with a consecutive hyphen lines (--). Blank lines are ignored.

The following example shows a user information in which grandeur and sonata are included in sedan group, tuscan is included in suv group, and i30 is included in hatchback group. The name of the user information file is user_info.txt.

--
-- Example 1 of a user information file
--
USER sedan
USER suv
USER hatchback
USER grandeur GROUPS sedan
USER sonata GROUPS sedan
USER tuscan GROUPS suv
USER i30 GROUPS hatchback

The following example shows a file that has the same user relationship information as the file above. The difference is that the MEMBERS statement is used in the file below.

--
-- Example 2 of a user information file
--
USER grandeur
USER sonata
USER tuscan
USER i30
USER sedan MEMBERS sonata grandeur
USER suv MEMBERS tuscan
USER hatchback MEMBERS i30
--csql-initialization-file=FILE

This option executes an SQL statement on the database to be created by using the CSQL Interpreter. A schema can be created based on the SQL statement contained in the file specified by the parameter.

The following example shows how to create a database named testdb and execute the SQL statement defined in table_schema.sql through the CSQL Interpreter.

cubrid createdb --csql-initialization-file table_schema.sql testdb en_US
-o, --output-file=FILE

This option stores messages related to the database creation to the file given as a parameter. The file is created in the same directory where the database was created. If the -o option is not specified, messages are displayed on the console screen. The -o option allows you to use information on the creation of a certain database by storing messages, generated during the database creation, to a specified file.

The following example shows how to create a database named testdb and store the output of the utility to the db_output file instead of displaying it on the console screen.

cubrid createdb -o db_output testdb en_US
-v, --verbose

This option displays all information on the database creation operation onto the screen. Like the -o option, this option is useful in checking information related to the creation of a specific database. Therefore, if you specify the -v option together with the -o option, you can store the output messages in the file given as a parameter; the messages contain the operation information about the cubrid createdb utility and database creation process.

The following example shows how to create a database named testdb and display detailed information on the operation onto the screen.

cubrid createdb -v testdb en_US

Note

  • temp_file_max_size_in_pages is a parameter used to configure the maximum number of pages assigned to store the temporary temp volume - used for complicated queries or storing arrays - on the disk. While the default value is -1, the temporary temp volume may be increased up to the amount of extra space on the disk specified by the temp_volume_path parameter. If the value is 0, the temporary temp volume cannot be created. In this case, the permanent temp volume should be added by using the cubrid addvoldb utility. For the efficient management of the volume, it is recommended to add a volume for each usage.
  • By using the cubrid spacedb utility, you can check the reaming space of each volume. By using the cubrid addvoldb utility, you can add more volumes as needed while managing the database. When adding a volume while managing the database, you are advised to do so when there is less system load. Once the assigned volume for a usage is completely in use, a generic volume will be created, so it is suggested to add extra volume for a usage that is expected to require more space.

The following example shows how to create a database, classify volume usage, and add volumes such as data, index, and temp.

cubrid createdb --db-volume-size=512M --log-volume-size=256M cubriddb en_US
cubrid addvoldb -S -p data -n cubriddb_DATA01 --db-volume-size=512M cubriddb
cubrid addvoldb -S -p data -n cubriddb_DATA02 --db-volume-size=512M cubriddb
cubrid addvoldb -S -p index -n cubriddb_INDEX01 cubriddb --db-volume-size=512M cubriddb
cubrid addvoldb -S -p temp -n cubriddb_TEMP01 cubriddb --db-volume-size=512M cubriddb
addvoldb

When the total free space size of the generic volumes has become smaller than the size which is specified at the system parameter generic_vol_prealloc_size (default: 50M) in Disk-Related Parameters, generic volume is added automatically. Automatically adding a volume is done when a new page is required; The volume is not expanded when only a SELECT queries are executed.

CUBRID volumes are separated by the purpose of the usage such as data storage, index storage, temporary result storage; generic volume can be used for data and index storage.

For the each type(purpose) of volumes, see Database Volume Structure.

In comparison, the command for adding a database volume manually is as follows.

cubrid addvoldb [options] database_name
  • cubrid: An integrated utility for CUBRID service and database management.
  • addvoldb: A command that adds a specified number of pages of the new volume to a specified database.
  • database_name: Specifies the name of the database to which a volume is to be added without including the path name to the directory where the database is to be created.

The following example shows how to create a database, classify volume usage, and add volumes such as data, index, and temp.

cubrid createdb --db-volume-size=512M --log-volume-size=256M cubriddb en_US
cubrid addvoldb -S -p data -n cubriddb_DATA01 --db-volume-size=512M cubriddb
cubrid addvoldb -S -p data -n cubriddb_DATA02 --db-volume-size=512M cubriddb
cubrid addvoldb -S -p index -n cubriddb_INDEX01 cubriddb --db-volume-size=512M cubriddb
cubrid addvoldb -S -p temp -n cubriddb_TEMP01 cubriddb --db-volume-size=512M cubriddb

The following shows [options] available with the cubrid addvoldb utility.

--db-volume-size=SIZE

--db-volume-size is an option that specifies the size of the volume to be added to a specified database. If the --db-volume-size option is omitted, the value of the system parameter db_volume_size is used by default. You can set units as K, M, G and T, which stand for kilobytes (KB), megabytes (MB), gigabytes (GB), and terabytes (TB) respectively. If you omit the unit, bytes will be applied.

The following example shows how to add a volume for which 256 MB are assigned to the testdb database.

cubrid addvoldb -p data --db-volume-size=256M testdb
-n, --volume-name=NAME

This option specifies the name of the volume to be added to a specified database. The volume name must follow the file name protocol of the operating system and be a simple one without including the directory path or spaces. If the -n option is omitted, the name of the volume to be added is configured by the system automatically as "database name_volume identifier". For example, if the database name is testdb, the volume name testdb_x001 is automatically configured.

The following example shows how to add a volume for which 256 MB are assigned to the testdb database in standalone mode. The volume name testdb_v1 will be created.

cubrid addvoldb -S -n testdb_v1 --db-volume-size=256M testdb
-F, --file-path=PATH

This option specifies the directory path where the volume to be added will be stored. If the -F option is omitted, the value of the system parameter volume_extension_path is used by default.

The following example shows how to add a volume for which 256 MB are assigned to the testdb database in standalone mode. The added volume is created in the /dbtemp/addvol directory. Because the -n option is not specified for the volume name, the volume name testdb_x001 will be created.

cubrid addvoldb -S -F /dbtemp/addvol/ --db-volume-size=256M testdb
--comment COMMENT

This option facilitates to retrieve information on the added volume by adding such information in the form of comments. It is recommended that the contents of a comment include the name of DBA who adds the volume, or the purpose of adding the volume. The comment must be enclosed in double quotes.

The following example shows how to add a volume for which 256 MB are assigned to the testdb database in standalone mode and inserts a comment about the volume.

cubrid addvoldb -S --comment "data volume added_cheolsoo kim" --db-volume-size=256M testdb
-p, --purpose=PURPOSE

This option specifies the purpose of the volume to be added. The reason for specifying the purpose of the volume is to improve the I/O performance by storing volumes separately on different disk drives according to their purpose. Parameter values that can be used for the -p option are data, index, temp and generic. The default value is generic. For the purpose of each volume, see Database Volume Structure.

The following example shows how to add a volume for which 256 MB are assigned to the testdb database in standalone mode.

cubrid addvoldb -S -p index --db-volume-size=256M testdb
-S, --SA-mode

This option accesses the database in standalone mode without running the server process. This option has no parameter. If the -S option is not specified, the system assumes to be in client/server mode.

cubrid addvoldb -S --db-volume-size=256M testdb
-C, --CS-mode

This option accesses the database in client/server mode by running the server and the client separately. There is no parameter. Even when the -C option is not specified, the system assumes to be in client/server mode by default.

cubrid addvoldb -C --db-volume-size=256M testdb
--max_writesize-in-sec=SIZE

The --max_writesize-in-sec is used to limit the impact of system operating when you add a volume to the database. This can limit the maximum writing size per second. The unit of this option is K(kilobytes) and M(megabytes). The minimum value is 160K. If you set this value as less than 160K, it is changed as 160K. It can be used only in client/server mode.

The below is an example to limit the writing size of the 2GB volume as 1MB. Consuming time will be about 35 minutes(= (2048MB/1MB) /60 sec.).

cubrid addvoldb -C --db-volume-size=2G --max-writesize-in-sec=1M testdb
deletedb

The cubrid deletedb utility is used to delete a database. You must use the cubrid deletedb utility to delete a database, instead of using the file deletion commands of the operating system; a database consists of a few interdependent files.

The cubrid deletedb utility also deletes the information on the database from the database location file (databases.txt). The cubrid deletedb utility must be run offline, that is, in standalone mode when nobody is using the database.

cubrid deletedb  [options] database_name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • deletedb: A command to delete a database, its related data, logs and all backup files. It can be executed successfully only when the database is in a stopped state.
  • database_name: Specifies the name of the database to be deleted without including the path name.

The following shows [options] available with the cubrid deletedb utility.

-o, --output-file=FILE

This option specifies the file name for writing messages:

cubrid deletedb -o deleted_db.out testdb

The cubrid deletedb utility also deletes the database information contained in the database location file (databases.txt). The following message is returned if you enter a utility that tries to delete a non-existing database.

cubrid deletedb testdb
Database "testdb" is unknown, or the file "databases.txt" cannot be accessed.
-d, --delete-backup

This option deletes database volumes, backup volumes and backup information files simultaneously. If the -d option is not specified, backup volume and backup information files are not deleted.

cubrid deletedb -d testdb
renamedb

The cubrid renamedb utility renames a database. The names of information volumes, log volumes and control files are also renamed to conform to the new database one.

In contrast, the cubrid alterdbhost utility configures or changes the host name of the specified database. In other words, it changes the host name configuration in the databases.txt file.

cubrid renamedb [options] src_database_name dest_database_name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • renamedb: A command that changes the existing name of a database to a new one. It executes successfully only when the database is in a stopped state. The names of related information volumes, log volumes and control files are also changed to new ones accordingly.
  • src_database_name: The name of the existing database to be renamed. The path name to the directory where the database is to be created must not be included.
  • dest_database_name: The new name of the database. It must not be the same as that of an existing database. The path name to the directory where the database is to be created must not be included.

The following shows [options] available with the cubrid deletedb utility.

-E, --extended-volume-path=PATH

This option renames an extended volume created in a specific directory path (e.g. /dbtemp/addvol/), and then moves the volume to a new directory. This specifies a new directory path (e.g. /dbtemp/newaddvols/) where the renamed extended volume will be moved.

If it is not specified, the extended volume is only renamed in the existing path without being moved. If a directory path outside the disk partition of the existing database volume or an invalid one is specified, the rename operation is not executed. This option cannot be used together with the -i option.

cubrid renamedb -E /dbtemp/newaddvols/ testdb testdb_1
-i, --control-file=FILE

The option specifies an input file in which directory information is stored to change all database name of volumes or files and assign different directory at once. To perform this work, the -i option is used. The -i option cannot be used together with the -E option.

cubrid renamedb -i rename_path testdb testdb_1

The following are the syntax and example of a file that contains the name of each volume, the current directory path and the directory path where renamed volumes will be stored.

volid source_fullvolname dest_fullvolname
  • volid: An integer that is used to identify each volume. It can be checked in the database volume control file (database_name_vinf).
  • source_fullvolname: The current directory path to each volume.
  • dest_fullvolname: The target directory path where renamed volumes will be moved. If the target directory path is invalid, the database rename operation is not executed.
-5  /home1/user/testdb_vinf       /home1/CUBRID/databases/testdb_1_vinf
-4  /home1/user/testdb_lginf      /home1/CUBRID/databases/testdb_1_lginf
-3  /home1/user/testdb_bkvinf     /home1/CUBRID/databases/testdb_1_bkvinf
-2  /home1/user/testdb_lgat       /home1/CUBRID/databases/testdb_1_lgat
 0  /home1/user/testdb            /home1/CUBRID/databases/testdb_1
 1  /home1/user/backup/testdb_x001/home1/CUBRID/databases/backup/testdb_1_x001
-d, --delete-backup

This option renames the testdb database and at once forcefully delete all backup volumes and backup information files that are in the same location as testdb. Note that you cannot use the backup files with the old names once the database is renamed. If the -d option is not specified, backup volumes and backup information files are not deleted.

cubrid renamedb -d testdb testdb_1
alterdbhost

The cubrid alterdbhost utility sets or changes the host name of the specified database. It changes the host name set in the databases.txt file.

cubrid alterdbhost [option] database_name
  • cubrid: An integrated utility for the CUBRID service and database management
  • alterdbhost: A command used to change the host name of the current database

The following shows the option available with the cubrid alterdbhost utility.

-h, --host=HOST

The -h option specifies the host name to be changed. When this option is omitted, specifies the host name to localhost.

copydb

The cubrid copydb utility copy or move a database to another location. As arguments, source and target name of database must be given. A target database name must be different from a source database name. When the target name argument is specified, the location of target database name is registered in the databases.txt file.

The cubrid copydb utility can be executed only offline (that is, state of a source database stop).

cubrid copydb [options] src-database-name dest-database-name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • copydb: A command that copy or move a database from one to another location.
  • src-database-name: The names of source and target databases to be copied or moved.
  • dest-database-name: A new (target) database name.

If options are omitted, a target database is copied into the same directory of a source database.

The following shows [options] available with the cubrid copydb utility.

--server-name=HOST

The --server-name option specifies a host name of new database. The host name is registered in the databases.txt file. If this option is omitted, a local host is registered.

cubrid copydb --server-name=cub_server1 demodb new_demodb
-F, --file-path=PATH

The -F option specifies a specific directory path where a new database volume is stored with an -F option. It represents specifying an absolute path. If the specified directory does not exist, an error is displayed. If this option is omitted, a new database volume is created in the current working directory. And this information is specified in vol-path of the databases.txt file.

cubrid copydb -F /home/usr/CUBRID/databases demodb new_demodb
-L, --log-path=PATH

The -L option specifies a specific directory path where a new database volume is stored with an -L option. It represents specifying an absolute path. If the specified directory does not exist, an error is displayed. If this option is omitted, a new database volume is created in the current working directory. And this information is specified in log-path of the databases.txt file.

cubrid copydb -L /home/usr/CUBRID/databases/logs demodb new_demodb
-E, --extended-volume-path=PATH

The -E option specifies a specific directory path where a new database extended volume is stored with an -E. If this option is omitted, a new database extended volume is created in the location of a new database volume or in the registered path of controlling file. The -i option cannot be used with this option.

cubrid copydb -E home/usr/CUBRID/databases/extvols demodb new_demodb
-i, --control_file=FILE

The -i option specifies an input file where a new directory path information and a source volume are stored to copy or move multiple volumes into a different directory, respectively. This option cannot be used with the -E option. An input file named copy_path is specified in the example below.

cubrid copydb -i copy_path demodb new_demodb

The following is an example of input file that contains each volume name, current directory path, and new directory and volume names.

# volid   source_fullvolname   dest_fullvolname
0 /usr/databases/demodb        /drive1/usr/databases/new_demodb
1 /usr/databases/demodb_data1  /drive1/usr/databases/new_demodb new_data1
2 /usr/databases/ext/demodb index1 /drive2//usr/databases/new_demodb new_index1
3 /usr/ databases/ext/demodb index2  /drive2/usr/databases/new_demodb new_index2
  • volid: An integer that is used to identify each volume. It can be checked in the database volume control file (database_name_vinf).
  • source_fullvolname: The current directory path to each source database volume.
  • dest_fullvolname: The target directory path where new volumes will be stored. You should specify a valid path.
-r, --replace

If the -r option is specified, a new database name overwrites the existing database name if it is identical, instead of outputting an error.

cubrid copydb -r -F /home/usr/CUBRID/databases demodb new_demodb
-d, --delete-source

If the -d option is specified, a source database is deleted after the database is copied. This execution brings the same the result as executing cubrid deletedb utility after copying a database. Note that if a source database contains LOB data, LOB file directory path of a source database is copied into a new database and it is registered in the lob-base-path of the databases.txt file.

cubrid copydb -d -F /home/usr/CUBRID/databases demodb new_demodb
--copy-lob-path=PATH

If the --copy-lob-path option is specified, a new directory path for LOB files is created and a source database is copied into a new directory path. If this option is omitted, the directory path is not created. Therefore, the lob-base-path of the databases.txt file should be modified separately. This option cannot be used with the -B option.

cubrid copydb --copy-lob-path demodb new_demodb
-B, --lob-base-path=PATH

If the -B option is specified, a specified directory is specified as for LOB files of a new database and a source database is copied. This option cannot be used with the --copy-lob-path option.

cubrid copydb -B /home/usr/CUBRID/databases/new_lob demodb new_demodb
installdb

The cubrid installdb utility is used to register the information of a newly installed database to databases.txt, which stores database location information. The execution of this utility does not affect the operation of the database to be registered.

cubrid installdb [options] database_name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • installdb: A command that registers the information of a moved or copied database to databases.txt.
  • database_name: The name of database to be registered to databases.txt.

If no [options] are used, the command must be executed in the directory where the corresponding database exists.

The following shows [options] available with the cubrid installdb utility.

--server-name=HOST

This option registers the server host information of a database to databases.txt with a specific host name. If this is not specified, the current host information is registered.

cubrid installdb --server-name=cub_server1 testdb
-L, --log-path=PATH

This option registers the absolute directory path of a database log volume to databases.txt by using the -L option. If this option is not specified, the directory path of a volume is registered.

cubrid installdb -L /home/cubrid/CUBRID/databases/logs/testdb testdb
backupdb

A database backup is the procedure of storing CUBRID database volumes, control files and log files, and it is executed by using the cubrid backupdb utility or the CUBRID Manager. DBA must regularly back up the database so that the database can be properly restored in the case of storage media or file errors. The restore environment must have the same operating system and the same version of CUBRID as the backup environment. For such a reason, you must perform a backup in a new environment immediately after migrating a database to a new version.

To recover all database pages, control files and the database to the state at the time of backup, the cubrid backupdb utility copies all necessary log records.

cubrid backupdb [options] database_name[@hostname]
  • @hostname: It is omitted when you do backup in standalone mode. If you do backup on the HA environment, specify "@hostname" after the database name. hostname is a name specified in $CUBRID_DATABASES/databases.txt. If you want to setup a local server, you can specify it as "@localhost".

The following shows options available with the cubrid backupdb utility (options are case sensitive).

-D, --destination-path=PATH

The following shows how to use the -D option to store backup files in the specified directory. The backup file directory must be specified before performing this job. If the -D option is not specified, backup files are stored in the log directory specified in the databases.txt file which stores database location information.

cubrid backupdb -D /home/cubrid/backup demodb

The following shows how to store backup files in the current directory by using the -D option. If you enter a period (.) following the -D option as an argument, the current directory is specified.

cubrid backupdb -D . demodb
-r, --remove-archive

Writes an active log to a new archive log file when the active log is full. If a backup is performed in such a situation and backup volumes are created, backup logs created before the backup will not be used in subsequent backups. The -r option is used to remove archive log files that will not be used anymore in subsequent backups after the current one is complete. The -r option only removes unnecessary archive log files that were created before backup, and does not have any impact on backup; however, if an administrator removes the archive log file after a backup, it may become impossible to restore everything. For this reason, archive logs should be removed only after careful consideration.

If you perform an incremental backup (backup level 1 or 2) with the -r option, there is the risk that normal recovery of the database will be impossible later on. Therefore, it is recommended that the -r option only be used when a full backup is performed.

cubrid backupdb -r demodb
-l, --level=LEVEL

The following shows how to execute an incremental backup of the level specified by using the -l option. If the -l option is not specified, a full backup is performed. For details on backup levels, see Incremental Backup .

cubrid backupdb -l 1 demodb
-o, --output-file=FILE

The following shows how to write the progress of the database backup to the info_backup file by using the -o option.

cubrid backupdb -o info_backup demodb

The following shows the contents of the info_backup file. You can check the information on the number of threads, compression method, backup start time, the number of permanent volumes, backup progress and backup end time.

[ Database(demodb) Full Backup start ]
- num-threads: 1
- compression method: NONE
- backup start time: Mon Jul 21 16:51:51 2008
- number of permanent volumes: 1
- backup progress status
-----------------------------------------------------------------------------
 volume name                  | # of pages | backup progress status    | done
-----------------------------------------------------------------------------
 demodb_vinf                  |          1 | ######################### | done
 demodb                       |      25000 | ######################### | done
 demodb_lginf                 |          1 | ######################### | done
 demodb_lgat                  |      25000 | ######################### | done
-----------------------------------------------------------------------------
# backup end time: Mon Jul 21 16:51:53 2008
[Database(demodb) Full Backup end]
-S, --SA-mode

The following shows how to perform backup in standalone mode (that is, backup offline) by using the -S option. If the -S option is not specified, the backup is performed in client/server mode.

cubrid backupdb -S demodb
-C, --CS-mode

The following shows how to perform backup in client/server mode by using the -C option and the demodb database is backed up online. If the -C option is not specified, a backup is performed in client/server mode.

cubrid backupdb -C demodb
--no-check

The following shows how to execute backup without checking the consistency of the database by using the --no-check option.

cubrid backupdb --no-check demodb
-t, --thread-count=COUNT

The following shows how to execute parallel backup with the number of threads specified by the administrator by using the -t option. Even when the argument of the -t option is not specified, a parallel backup is performed by automatically assigning as many threads as CPUs in the system.

cubrid backupdb -t 4 demodb
-z, --compress

The following shows how to compress the database and stores it in the backup file by using the -z option. The size of the backup file and the time required for backup can be reduced by using the -z option.

cubrid backupdb -z demodb
-e, --except-active-log

The following shows how to execute backup excluding active logs of the database by using the -e option. You can reduce the time required for backup by using the -e option. However, extra caution is required because active logs needed for completing a restore to the state of a certain point from the backup point are not included in the backup file, which may lead to an unsuccessful restore.

cubrid backupdb -e demodb
--sleep-msecs=NUMBER

This option allows you to specify the interval of idle time during the database backup. The default value is 0 in milliseconds. The system becomes idle for the specified amount of time whenever it reads 1 MB of data from a file. This option is used to reduce the performance degradation of an active server during a live backup. The idle time will prevent excessive disk I/O operations.

cubrid backupdb --sleep-msecs=5 demodb
Backup Strategy and Method

The following must be considered before performing a backup:

  • Selecting the data to be backed up
    • Determine whether it is valid data worth being preserved.
    • Determine whether to back up the entire database or only part of it.
    • Check whether there are other files to be backed up along with the database.
  • Choosing a backup method
    • Choose the backup method from one of incremental and online backups. Also, specify whether to use compression backup, parallel backup, and mode.
    • Prepare backup tools and devices available.
  • Determining backup time
    • Identify the time when the least usage in the database occur.
    • Check the size of the archive logs.
    • Check the number of clients using the database to be backed up.

Online Backup

An online backup (or a hot backup) is a method of backing up a currently running database. It provides a snapshot of the database image at a certain point in time. Because the backup target is a currently running database, it is likely that uncommitted data will be stored and the backup may affect the operation of other databases.

To perform an online backup, use the cubrid backupdb -C command.

Offline Backup

An offline backup (or a cold backup) is a method of backing up a stopped database. It provides a snapshot of the database image at a certain point in time.

To perform an offline backup, use the cubrid backupdb -S command.

Incremental Backup

An incremental backup, which is dependent upon a full backup, is a method of only backing up data that have changed since the last backup. This type of backup has an advantage of requiring less volume and time than a full backup. CUBRID supports backup levels 0, 1 and 2. A higher level backup can be performed sequentially only after a lower lever backup is complete.

To perform an incremental backup, use the cubrid backupdb -l LEVEL command.

The following example shows incremental backup. Let's example backup levels in details.

_images/image11.png
  • Full backup (backup level 0) : Backup level 0 is a full backup that includes all database pages.

The level of a backup which is attempted first on the database naturally becomes a 0 level. DBA must perform full backups regularly to prepare for restore situations. In the example, full backups were performed on December 31st and January 5th.

  • First incremental backup (backup level 1) : Backup level 1 is an incremental backup that only stores changes since the level 0 full backup, and is called a "first incremental backup."

Note that the first incremental backups are attempted sequentially such as <1-1>, <1-2> and <1-3> in the example, but they are always performed based on the level 0 full backup.

Suppose that backup files are created in the same directory. If the first incremental backup <1-1> is performed on January 1st and then the first incremental backup <1-2> is attempted again on January 2nd, the incremental backup file created in <1-1> is overwritten. The final incremental backup file is created on January 3rd because the first incremental backup is performed again on that day.

Since there can be a possibility that the database needs to be restored the state of January 1st or January 2nd, it is recommended for DBA to store the incremental backup files <1-1> and <1-2> separately in storage media before overwriting with the final incremental file.

  • Second incremental backup (backup level 2) : Backup level 2 is an incremental backup that only stores data that have changed since the first incremental backup, and is called a "second incremental backup."

A second incremental backup can be performed only after the first incremental backup. Therefore, the second incremental backup attempted on January fourth succeeds; the one attempted on January sixth fails.

Backup files created for backup levels 0, 1 and 2 may all be required for database restore. To restore the database to its state on January fourth, for example, you need the second incremental backup generated at <2-1>, the first incremental backup file generated at <1-3>, and the full backup file generated at <0-1>. That is, for a full restore, backup files from the most recent incremental backup file to the earliest created full backup file are required.

Compress Backup

A compress backup is a method of backing up the database by compressing it. This type of backup reduces disk I/O costs and stores disk space because it requires less backup volume.

To perform a compress backup, use the cubrid backupdb -z | --compress command.

Parallel Backup Mode

A parallel or multi-thread backup is a method of performing as many backups as the number of threads specified. In this way, it reduces backup time significantly. Basically, threads are given as many as the number of CPUs in the system.

To perform a parallel backup, use the cubrid backupdb -t | --thread-count command.

Managing Backup Files

One or more backup files can be created in sequence based on the size of the database to be backed up. A unit number is given sequentially (000, 001-0xx) to the extension of each backup file based in the order of creation.

Managing Disk Capacity during the Backup

During the backup process, if there is not enough space on the disk to store the backup files, a message saying that the backup cannot continue appears on the screen. This message contains the name and path of the database to be backed up, the backup file name, the unit number of backup files and the backup level. To continue the backup process, the administrator can choose one of the following options:

  • Option 0: An administrator enters 0 to discontinue the backup.
  • Option 1: An administrator inserts a new disk into the current device and enters 1 to continue the backup.
  • Option 2: An administrator changes the device or the path to the directory where backup files are stored and enters 2 to continue the backup.
******************************************************************
Backup destination is full, a new destination is required to continue:
Database Name: /local1/testing/demodb
     Volume Name: /dev/rst1
        Unit Num: 1
    Backup Level: 0 (FULL LEVEL)
Enter one of the following options:
Type
   -  0 to quit.
   -  1 to continue after the volume is mounted/loaded. (retry)
   -  2 to continue after changing the volume's directory or device.
******************************************************************
Managing Archive Logs

You must not delete archive logs by using the file deletion command such as rm or del by yourself; the archive logs should be deleted by system configuration or the cubrid backupdb utility. In the following three cases, archive logs can be deleted.

  • In non-HA environment (ha_mode=off):

    If you configure the force_remove_log_archives value to yes, archive logs are kept only the number specified in log_max_archives value; and the left logs are automatically deleted. However, if tehre is an active tranaction in the oldest archive log file, this file is not deleted until the transaction is completed.

  • In an HA environment (ha_mode=on):

    If you configure the force_remove_log_archives values to no and specify the number specfied in log_max_archives value, archive logs are automatically deleted after replication is applied.

    Note

    If you set force_remove_log_archives as yes when "ha_mode=on", unapplied archive logs can be deleted; therefore, this setting is not recommended. However, if keeping disk space is prior to keeping replication, set force_remove_log_archives as yes and set log_max_archives as a proper value.

  • Use cubrid backupdb -r and run this command then archive logs are deleted; note that -r option should not be used in an HA environment.

If you want to delete logs as much as possible while operating a database, configure the value of log_max_archives to a small value or 0 and configure the value of force_remove_log_archives to yes. Note that in an HA environment, if the value of force_remove_log_archives is yes, archive logs that have not replicated in a slave node are deleted, which can cause replication errors. Therefore, it is recommended that you configure it to no. Although the value of force_remove_log_archives is set to no, files that are complete for replication can be deleted by HA management process.

restoredb

A database restore is the procedure of restoring the database to its state at a certain point in time by using the backup files, active logs and archive logs which have been created in an environment of the same CUBRID version. To perform a database restore, use the cubrid restoredb utility or the CUBRID Manager.

The cubrid restoredb utility (restordb.exe on Windows) restores the database from the database backup by using the information written to all the active and archive logs since the execution of the last backup.

cubrid restoredb [options] database_name

If no option is specified, a database is restored to the point of the last commit by default. If no active/archive log files are required to restore to the point of the last commit, the database is restored only to the point of the last backup.

cubrid restoredb demodb

The following table shows options available with the cubrid restoredb utility (options are case sensitive).

-d, --up-to-date=DATE

A database can be restored to the given point by the date-time specified by the -d option. The user can specify the restoration point manually in the dd-mm-yyyy:hh:mi:ss (e.g. 14-10-2008:14:10:00) format. If no active log/archive log files are required to restore to the point specified, the database is restored only to the point of the last backup.

cubrid restoredb -d 14-10-2008:14:10:00 demodb

If the user specifies the restoration point by using the backuptime keyword, it restores a database to the point of the last backup.

cubrid restoredb -d backuptime demodb
--list

This option displays information on backup files of a database; restoration procedure is not performed. This option is available even if the database is working, from CUBRID 9.3.

cubrid restoredb --list demodb

The following example shows how to display backup information by using the --list option. You can specify the path to which backup files of the database are originally stored as well as backup levels.

*** BACKUP HEADER INFORMATION ***
Database Name: /local1/testing/demodb
 DB Creation Time: Mon Oct 1 17:27:40 2008
         Pagesize: 4096
Backup Level: 1 (INCREMENTAL LEVEL 1)
        Start_lsa: 513|3688
         Last_lsa: 513|3688
Backup Time: Mon Oct 1 17:32:50 2008
 Backup Unit Num: 0
Release: 8.1.0
     Disk Version: 8
Backup Pagesize: 4096
Zip Method: 0 (NONE)
        Zip Level: 0 (NONE)
Previous Backup level: 0 Time: Mon Oct 1 17:31:40 2008
(start_lsa was -1|-1)
Database Volume name: /local1/testing/demodb_vinf
     Volume Identifier: -5, Size: 308 bytes (1 pages)
Database Volume name: /local1/testing/demodb
     Volume Identifier: 0, Size: 2048000 bytes (500 pages)
Database Volume name: /local1/testing/demodb_lginf
     Volume Identifier: -4, Size: 165 bytes (1 pages)
Database Volume name: /local1/testing/demodb_bkvinf
     Volume Identifier: -3, Size: 132 bytes (1 pages)

With the backup information displayed by using the --list option, you can check that backup files have been created at the backup level 1 as well as the point where the full backup of backup level 0 has been performed. Therefore, to restore the database in the example, you must prepare backup files for backup levels 0 and 1.

-B, --backup-file-path=PATH

You can specify the directory where backup files are to be located by using the -B option. If this option is not specified, the system retrieves the backup information file (dbname _bkvinf) generated upon a database backup; the backup information file in located in the log-path directory specified in the database location information file (databases.txt). And then it searches the backup files in the directory path specified in the backup information file. However, if the backup information file has been damaged or the location information of the backup files has been deleted, the system will not be able to find the backup files. Therefore, the administrator must manually specify the directory where the backup files are located by using the -B option.

cubrid restoredb -B /home/cubrid/backup demodb

If the backup files of a database is in the current directory, the administrator can specify the directory where the backup files are located by using the -B option.

cubrid restoredb -B . demodb
-l, --level=LEVEL

You can perform restoration by specifying the backup level of the database to 0, 1, or 2. For details on backup levels, see Incremental Backup .

cubrid restoredb -l 1 demodb
-p, --partial-recovery

You can perform partial restoration without requesting for the user's response by using the -p option. If active or archive logs written after the backup point are not complete, by default the system displays a request message informing that log files are needed and prompting the user to enter an execution option. The partial restoration can be performed directly without such a request message by using the -p option. Therefore, if the -p option is used when performing restoration, data is always restored to the point of the last backup.

cubrid restoredb -p demodb

When the -p option is not specified, the message requesting the user to select the execution option is as follows:

***********************************************************
Log Archive /home/cubrid/test/log/demodb_lgar002
 is needed to continue normal execution.
   Type
   -  0 to quit.
   -  1 to continue without present archive. (Partial recovery)
   -  2 to continue after the archive is mounted/loaded.
   -  3 to continue after changing location/name of archive.
***********************************************************
  • Option 0: Stops restoring
  • Option 1: Performing partial restoration without log files.
  • Option 2: Performing restoration after locating a log to the current device.
  • Option 3: Resuming restoration after changing the location of a log
-o, --output-file=FILE

The following syntax shows how to write the restoration progress of a database to the info_restore file by using the -o option.

cubrid restoredb -o info_restore demodb
-u, --use-database-location-path

This option restores a database to the path specified in the database location file(databases.txt). The -u option is useful when you perform a backup on server A and store the backup file on server B.

cubrid restoredb -u demodb

NOTIFICATION messages, log recovery starting time and ending time are written into the server error log file or the restoredb error log file when database server is started or backup volume is restored; so you can check the elapsed time of these operations. In this message, the number of log records to be applied(redo) and the number of log pages are written together.

To print out the NOTIFICATION message, error_log_level parameter in cubrid.conf should be specified as NOTIFICATION.

Time: 06/14/13 21:29:04.059 - NOTIFICATION *** file ../../src/transaction/log_recovery.c, line 748 CODE = -1128 Tran = -1, EID = 1
Log recovery is started. The number of log records to be applied: 96916. Log page: 343 ~ 5104.
.....
Time: 06/14/13 21:29:05.170 - NOTIFICATION *** file ../../src/transaction/log_recovery.c, line 843 CODE = -1129 Tran = -1, EID = 4
Log recovery is finished.
Restoring Strategy and Procedure

You must consider the following before restoring databases.

  • Preparing backup files
    • Identify the directory where the backup and log files are to be stored.
    • If the database has been incrementally backed up, check whether an appropriate backup file for each backup level exists.
    • Check whether the backed-up CUBRID database and the CUBRID database to be backed up are the same version.
  • Choosing restore method
    • Determine whether to perform a partial or full restore.
    • Determine whether or not to perform a restore using incremental backup files.
    • Prepare restore tools and devices available.
  • Determining restore point
    • Identify the point in time when the database server was terminated.
    • Identify the point in time when the last backup was performed before database failure.
    • Identify the point in time when the last commit was made before database failure.

Database Restore Procedure

The following procedure shows how to perform backup and restoration described in the order of time.

  1. Performs a full backup of demodb which stopped running at 2008/8/14 04:30.
  2. Performs the first incremental backup of demodb running at 2008/8/14 10:00.
  3. Performs the first incremental backup of demodb running at 2008/8/14 15:00. Overwrites the first incremental backup file in step 2.
  4. A system failure occurs at 2008/8/14 15:30, and the system administrator prepares the restore of demodb. Sets the restore time as 15:25, which is the time when the last commit was made before database failure
  5. The system administrator prepares the full backup file created in Step 1 and the first incremental backup file created in Step 3, restores the demodb database up to the point of 15:00, and then prepares the active and archive logs to restore the database up to the point of 15:25.
Time Command Description
2008/8/14 04:25 cubrid server stop demodb Shuts down demodb.
2008/8/14 04:30 cubrid backupdb -S -D /home/backup -l 0 demodb Performs a full backup of demodb in offline mode and creates backup files in the specified directory.
2008/8/14 05:00 cubrid server start demodb Starts demodb.
2008/8/14 10:00 cubrid backupdb -C -D /home/backup -l 1 demodb Performs the first incremental backup of demodb online and creates backup files in the specified directory.
2008/8/14 15:00 cubrid backupdb -C -D /home/backup -l 1 demodb Performs the first incremental backup of demodb online and creates backup files in the specified directory. Overwrites the first incremental backup file created at 10:00.
2008/8/14 15:30   A system failure occurs.
2008/8/14 15:40 cubrid restoredb -l 1 -d 08/14/2008:15:25:00 demodb Restores demodb based on the full backup file, first incremental backup file, active logs and archive logs. The database is restored to the point of 15:25 by the full and first incremental backup files, the active and archive logs.
Restoring Database to Different Server

The following shows how to back up demodb on server A and restore it on server B with the backed up files.

Backup and Restore Environments

Suppose that demodb is backed up in the /home/cubrid/db/demodb directory on server A and restored into /home/cubrid/data/demodb on server B.

_images/image12.png
  1. Backing up on server A

    Back up demodb on server A. If a backup has been performed earlier, you can perform an incremental backup for data only that have changed since the last backup. The directory where the backup files are created, if not specified in the -D option, is created by default in the location where the log volume is stored. The following is a backup command with recommended options. For details on the options, see backupdb .

    cubrid backupdb -z demodb
    
  2. Editing the database location file on Server B

    Unlike a general scenario where a backup and restore are performed on the same server, in a scenario where backup files are restored using a different server, you need to add the location information on database restore in the database location file (databases.txt) on server B. In the diagram above, it is supposed that demodb is restored in the /home/cubrid/data/demodb directory on server B (hostname: pmlinux); edit the location information file accordingly and create the directory on server B.

    Put the database location information in one single line. Separate each item with a space. The line should be written in [database name]. [data volume path] [host name] [log volume path] format; that is, write the location information of demodb as follows:

    demodb /home/cubrid/data/demodb pmlinux /home/cubrid/data/demodb
    
  3. Transferring backup files to server B

    For a restore, you must prepare backup files. Therefore, transfer a backup file (e.g. demodb_bk0v000) from server A to server B. That is, a backup file must be located in a directory (e.g. /home/cubrid/temp) on server B.

    Note

    If you want to restore until the current time after the backup, logs after backup, that is, an active log (e.g. demodb_lgat) and archive logs (e.g. demodb_lgar000) are additionally required to copy.

    An active log and archive logs should be located to the log directory of the database to be restored; that is, the directory of log files specified in $CUBRID/databases/databases.txt. (e.g. $CUBRID/databases/demodb/log)

    Also, if you want to apply the added logs after backup, archive logs should be copied before they are removed. By the way, the default of log_max_archives, which is a system parameter related to delete archive logs, is 0; therefore, archive logs after backup can be deleted. To prevent this situation, the value of log_max_archives should be big enough. See log_max_archives.

  4. Restoring the database on server B

    Perform database restore by calling the cubrid restoredb utility from the directory into which the backup files which were transferred to server B had been stored. With the -u option, demodb is restored in the directory path from the databases.txt file.

    cubrid restoredb -u demodb
    

    To call the cubrid restoredb utility from a different path, specify the directory path to the backup file by using the -B option as follows:

    cubrid restoredb -u -B /home/cubrid/temp demodb
    
unloaddb

The purposes of loading/unloading databases are as follows:

  • To rebuild databases by volume reconfiguration
  • To migrate database in different system environments
  • To migrate database in different versions
cubrid unloaddb [options] database_name

cubrid unloaddb utility creates the following files:

  • Schema file(database-name_schema): A file that contains information on the schema defined in the database.
  • Object file(database-name_objects): A file that contains information on the records in the database.
  • Index file(database-name_indexes): A file that contains information on the indexes defined in the database.
  • Trigger file(database-name_trigger): A file that contains information on the triggers defined in the database. If you don't want triggers to be running while loading the data, load the trigger definitions after the data loading has completed.

The schema, object, index, and trigger files are created in the same directory.

The following is [options] used in cubrid unloaddb.

-u, --user=ID

Specify a user account of a database to be unloaded. If this is not specified, the default is DBA.

cubrid unloaddb -u dba -i table_list.txt demodb
-p, --password=PASS

Specify a user's password of a database to be unloaded. If this is not specified, it is regarded as the empty string is entered.

cubrid unloaddb -u dba -p dba_pwd -i table_list.txt demodb
-i, --input-class-file FILE

Unload all schema and index of all tables; however, only the data of specified tables in this file are unloaded.

cubrid unloaddb -i table_list.txt demodb

The following example shows an input file (table_list.txt).

table_1
table_2
..
table_n

If this option is used together with the --input-class-only option, it creates schema, index, and data files of tables only specified in the input file of -i option.

cubrid unloaddb --input-class-only -i table_list.txt demodb

If this option is used together with the --include-reference option, it unloads the referenced tables as well.

cubrid unloaddb --include-reference -i table_list.txt demodb
--include-reference

This option is used together with the -i option, and also unloads the referenced tables.

--input-class-only

This option is used together with the -i option, and creates only a schema file of tables specified in the input file of -i option.

--estimated-size=NUMBER

This option allows you to assign hash memory to store records of the database to be unloaded. If the --estimated-size option is not specified, the number of records of the database is determined based on recent statistics information. This option can be used if the recent statistics information has not been updated or if a large amount of hash memory needs to be assigned. Therefore, if the number given as the argument for the option is too small, the unload performance deteriorates due to hash conflicts.

cubrid unloaddb --estimated-size=1000 demodb
--cached-pages=NUMBER

The --cached-pages option specifies the number of pages of tables to be cached in the memory. Each page is 4,096 bytes. The administrator can configure the number of pages taking into account the memory size and speed. If this option is not specified, the default value is 100 pages.

cubrid unloaddb --cached-pages 500 demodb
-O, --output-path=PATH

This option specifies the directory in which to create schema and object files. If this is not specified, files are created in the current directory.

cubrid unloaddb -O ./CUBRID/Databases/demodb demodb

If the specified directory does not exist, the following error message will be displayed.

unloaddb: No such file or directory.
-s, --schema-only

This option specifies that only the schema file will be created from amongst all the output files which can be created by the unload operation.

cubrid unloaddb -s demodb
-d, --data-only

This option specifies that only the data file will be created from amongst all of the output files which can be created by the unload operation.

cubrid unloaddb -d demodb
--output-prefix=PREFIX

This option specifies the prefix for the names of schema and object files created by the unload operation. Once the example is executed, the schema file name becomes abcd_schema and the object file name becomes abcd_objects. If the --output-prefix option is not specified, the name of the database to be unloaded is used as the prefix.

cubrid unloaddb --output-prefix abcd demodb
--hash-file=FILE

This option specifies the name of the hash file.

-v, --verbose

This option displays detailed information on the database tables and records being unloaded while the unload operation is under way.

cubrid unloaddb -v demodb
--use-delimiter

This option writes the double quot(") on the beginning and end of an identifier. The default is not to write the double quot(").

-S, --SA-mode

The -S option performs the unload operation by accessing the database in standalone mode.

cubrid unloaddb -S demodb
-C, --CS-mode

The -C option performs the unload operation by accessing the database in client/server mode.

cubrid unloaddb -C demodb
--datafile-per-class

This option specifies that the output file generated through unload operation creates a data file per each table. The file name is generated as <Database Name>_<Table Name>_ objects for each table. However, all column values in object types are unloaded as NULL and %id class_name class_id part is not written in the unloaded file (see How to Write Files to Load Database).

cubrid unloaddb --datafile-per-class demodb
loaddb

You can load a database by using the cubrid loaddb utility in the following situations:

  • Migrating previous version of CUBRID database to new version of CUBRID database
  • Migrating a third-party DBMS database to a CUBRID database
  • Inserting massive amount of data faster than using the INSERT statement

In general, the cubrid loaddb utility uses files (schema definition, object input, and index definition files) created by the cubrid unloaddb utility.

cubrid loaddb [options] database_name

Input Files

  • Schema file(database-name_schema): A file generated by the unload operation; it contains schema information defined in the database.
  • Object file(database-name_objects): A file created by an unload operation. It contains information on the records in the database.
  • Index file(database-name_indexes): A file created by an unload operation. It contains information on the indexes defined in the database.
  • Trigger file(database-name_trigger): A file created by an unload operation. It contains information on the triggers defined in the database.
  • User-defined object file(user_defined_object_file): A file in table format written by the user to enter mass data. (For details, see How to Write Files to Load Database .)

The following table shows [options] available with the cubrid loaddb utility.

-u, --user=ID

This option specifies the user account of a database where records are loaded. If the option is not specified, the default value is PUBLIC.

cubrid loaddb -u admin -d demodb_objects newdb
-p, --password=PASS

This option specifies the password of a database user who will load records. If the option is not specified, you will be prompted to enter the password.

cubrid loaddb -p admin -d demodb_objects newdb
--data-file-check-only

This option checks only the syntax of the data contained in demodb_objects, and does not load the data to the database.

cubrid loaddb --data-file-check-only -d demodb_objects newdb
-l, --load-only

This option loads data directly without checking the syntax of the data to be loaded. If the -l option is used, loading speed increases because data is loaded without checking the syntax included in demodb_objects, but an error might occur.

cubrid loaddb -l -d demodb_objects newdb
--estimated-size=NUMBER

This option can be used to improve loading performance when the number of records to be unloaded exceeds the default value of 5,000. You can improve the load performance by assigning large hash memory for record storage with this option.

cubrid loaddb --estimated-size 8000 -d demodb_objects newdb
-v, --verbose

This option shows how to display detailed information on the tables and records of the database being loaded while the database loading operation is performed. You can check the detailed information such as the progress, the class being loaded and the number of records to be entered.

cubrid loaddb -v -d demodb_objects newdb
-c, --periodic-commit=COUNT

This option commits periodically every time COUNT records are entered into the database. If this option is not specified, all records included in demodb_objects are loaded to the database before the transaction is committed. If this option is used together with the -s or -i option, commit is performed periodically every time 100 DDL statements are loaded.

The recommended commit interval varies depending on the data to be loaded. It is recommended that the parameter of the -c option be configured to 50 for schema loading, 1,000 for record loading, and 1 for index loading.

cubrid loaddb -c 100 -d demodb_objects newdb
--no-oid

The following is a command that loads records into newdb ignoring the OIDs in demodb_objects.

cubrid loaddb --no-oid -d demodb_objects newdb
--no-statistics

The following is a command that does not update the statistics information of newdb after loading demodb_objects. It is useful especially when small data is loaded to a relatively big database; you can improve the load performance by using this command.

cubrid loaddb --no-statistics -d demodb_objects newdb
-s, --schema-file=FILE[:LINE]

This option loads the schema information or the trigger information defined in the schema file or the trigger file, from the LINE-th. You can load the actual records after loading the schema information first by using the -s option.

On the following example, demodb_schema is a file created by the unload operation and contains the schema information of the unloaded database.

    cubrid loaddb -u dba -s demodb_schema newdb

    Start schema loading.
    Total       86 statements executed.
    Schema loading from demodb_schema finished.
    Statistics for Catalog classes have been updated.

The following loads the triggers defined in *demodb* into the newly created newdb database. demodb_trigger is a file created by the unload operation and contains the trigger information of the unloaded database. It is recommended to load the schema information after loading the records. ::

    cubrid loaddb -u dba -s demodb_trigger newdb
-i, --index-file=FILE[:LINE]

The following loads the index information defined in the index file, from the LINE-th. On the following example, demo_indexes is a file created by the unload operation and contains the index information of the unloaded database. You can create indexes with the -i option, after loading records with the -d option.

cubrid loaddb -c 100 -d demodb_objects newdb
cubrid loaddb -u dba -i demodb_indexes newdb
-d, --data-file=FILE

This option loads the record information into newdb by specifying the data file or the user-defined object file. demodb_objects is either an object file created by the unload operation or a user-defined object file written by the user for mass data loading.

cubrid loaddb -u dba -d demodb_objects newdb
-t, --table=TABLE

This option specifies the table name if a table name header is omitted in the data file to be loaded.

cubrid loaded -u dba -d demodb_objects -t tbl_name newdb
--error-control-file=FILE

This option specifies the file that describes how to handle specific errors occurring during database loading.

cubrid loaddb --error-control-file=error_test -d demodb_objects newdb

For the server error code name, see the $CUBRID/include/dbi.h file.

For error messages by error code (error number), see the number under $set 5 MSGCAT_SET_ERROR in the $CUBRID/msg/<character set name>/cubrid.msg file.

vi $CUBRID/msg/en_US/cubrid.msg

$set 5 MSGCAT_SET_ERROR
1 Missing message for error code %1$d.
2 Internal system failure: no more specific information is available.
3 Out of virtual memory: unable to allocate %1$ld memory bytes.
4 Has been interrupted.
...
670 Operation would have caused one or more unique constraint violations.
...

The format of a file that details specific errors is as follows:

  • -<error code>: Configures to ignore the error that corresponds to the <error code> (loaddb is continuously executed even when an error occurs while it is being executed).
  • +<error code>: Configures not to ignore the error that corresponds to the <error code> (loaddb is stopped when an error occurs while it is being executed).
  • +DEFAULT: Configures not to ignore errors from 24 to 33.

If the file that details errors is not specified by using the --error-control-file option, the loaddb utility is configured to ignore errors from 24 to 33 by default. As a warning error, it indicates that there is no enough space in the database volume. If there is no space in the assigned database volume, a generic volume is automatically created.

The following example shows a file that details errors.

  • The warning errors from 24 to 33 indicating DB volume space is insufficient are not ignored by configuring +DEFAULT.

  • The error code 2 is not ignored because +2 has been specified later, even when -2 has been specified first.

  • -670 has been specified to ignore the error code 670, which is a unique violation error.

  • #-115 has been processed as a comment since # is added.

    vi error_file
    
    +DEFAULT
    -2
    -670
    #-115 --> comment
    +2
    
--ignore-class-file=FILE

You can specify a file that lists classes to be ignored during loading records. All records of classes except ones specified in the file will be loaded.

cubrid loaddb --ignore-class-file=skip_class_list -d demodb_objects newdb

Warning

The --no-logging option enables to load data file quickly when loaddb is executed by not storing transaction logs; however, it has risk, which data cannot be recovered in case of errors occurred such as incorrect file format or system failure. In this case, you must rebuild database to solve the problem. Thus, in general, it is not recommended to use this option exception of building a new database which does not require data recovery. If you use this option, loaddb does not check the errors like unique violation. To use this option, you should consider these issues.

How to Write Files to Load Database

You can add mass data to the database more rapidly by writing the object input file used in the cubrid loaddb utility. An object input file is a text file in simple table form that consists of comments and command/data lines.

Comment

In CUBRID, a comment is represented by two hyphens (--).

-- This is a comment!
Command Line

A command line begins with a percent character (%) and consists of %class and %id commands; the former defines classes, and the latter defines aliases and identifiers used for class identification.

  • Assigning an Identifier to a Class

    You can assign an identifier to class reference relations by using the %id command.

    %id class_name class_id
    class_name:
        identifier
    class_id:
        integer
    

    The class_name specified by the %id command is the class name defined in the database, and class_id is the numeric identifier which is assigned for object reference.

    %id employee 2
    %id office 22
    %id project 23
    %id phone 24
    
  • Specifying the Class and Attribute

    You can specify the classes (tables) and attributes (columns) upon loading data by using the %class command. The data line should be written based on the order of attributes specified. When a class name is provided by using the -t option while executing the cubrid loaddb utility, you don't have to specify the class and attribute in the data file. However, the order of writing data must comply with the order of the attribute defined when creating a class.

    %class class_name ( attr_name [attr_name... ] )
    

    The schema must be pre-defined in the database to be loaded.

    The class_name specified by the %class command is the class name defined in the database and the attr_name is the name of the attribute defined.

    The following example shows how to specify a class and three attributes by using the %class command to enter data into a class named employee. Three pieces of data should be entered on the data lines after the %class command. For this, see Configuring Reference Relation.

    %class employee (name age department)
    
Data Line

A data line comes after the %class command line. Data loaded must have the same type as the class attributes specified by the %class command. The data loading operation stops if these two types are different.

Data for each attribute must be separated by at least one space and be basically written as a single line. However, if the data to be loaded takes more than one line, you should specify the plus sign (+) at the end of the first data line to enter data continuously on the following line. Note that no space is allowed between the last character of the data and the plus sign.

  • Loading an Instance

    As shown below, you can load an instance that has the same type as the specified class attribute. Each piece of data is separated by at least one space.

    %class employee (name)
    'jordan'
    'james'
    'garnett'
    'malone'
    
  • Assigning an Instance Number

    You can assign a number to a given instance at the beginning of the data line. An instance number is a unique positive number in the specified class. Spaces are not allowed between the number and the colon (:). Assigning an instance number is used to configure the reference relation for later.

    %class employee (name)
    1: 'jordan'
    2: 'james'
    3: 'garnett'
    4: 'malone'
    
  • Configuring Reference Relation

    You can configure the object reference relation by specifying the reference class after an "at sign (@)" and the instance number after the "vertical line (|)."

    @class_ref | instance_no
    class_ref:
         class_name
         class_id
    

    Specify a class name or a class id after the @ sign, and an instance number after a vertical line (|). Spaces are not allowed before and after a vertical line (|).

    The following example shows how to load class instances into the paycheck class. The name attribute references an instance of the employee class. As in the last line, data is loaded as NULL if you configure the reference relation by using an instance number not specified earlier.

    %class paycheck(name department salary)
    @employee|1   'planning'   8000000
    @employee|2   'planning'   6000000
    @employee|3   'sales'   5000000
    @employee|4   'development'   4000000
    @employee|5   'development'   5000000
    

    Since the id 21 was assigned to the employee class by using the %id command in the Assigning an Identifier to a Class section, the above example can be written as follows:

    %class paycheck(name department salary)
    @21|1   'planning'   8000000
    @21|2   'planning'   6000000
    @21|3   'sales'   5000000
    @21|4   'development'   4000000
    @21|5   'development'   5000000
    
Migrating Database

To use a new version of CUBRID database, you may need to migrate an existing data to a new one. For this purpose, you can use the "Export to an ASCII text file" and "Import from an ASCII text file" features provided by CUBRID.

The following section explains migration steps using the cubrid unloaddb and cubrid loaddb utilities.

Recommended Scenario and Procedures

The following steps describes migration scenario that can be applied while the existing version of CUBRID is running. For database migration, you should use the cubrid unloaddb and cubrid loaddb utilities. For details, see unloaddb and loaddb.

  1. Stop the existing CUBRID service

    Execute cubrid service stop to stop all service processes running on the existing CUBRID and then check whether all CUBRID-related processes have been successfully stopped.

    To verify whether all CUBRID-related processes have been successfully stopped, execute ps -ef | grep cub_ in Linux. If there is no process starting with cub_, all CUBRID-related processes have been successfully stopped. In Windows, press the <Ctrl+Alt+Delete> key and select [Start Task Manager]. If there is no process starting with cub_ in the [Processes] tab, all CUBRID-related processes have been successfully stopped. In Linux, when the related processes remain even after the CUBRID service has been terminated, use kill command to forcibly terminate them, and use ipcs -m command to check and release the memory shard by CUBRID broker. To forcibly terminate related processes in Windows, go to the [Processes] tab of Task Manager, right-click the image name, and then select [End Process].

  2. Back up the existing database

    Perform backup of the existing version of the database by using the cubrid backupdb utility. The purpose of this step is to safeguard against failures that might occur during the database unload/load operations. For details on the database backup, see backupdb.

  3. Unload the existing database

    Unload the database created for the existing version of CUBRID by using the cubrid unloaddb utility. For details on unloading a database, see unloaddb .

  4. Store the existing CUBRID configuration files

    Store the configurations files such as cubrid.conf, cubrid_broker.conf and cm.conf ** in the **CUBRID/conf directory. The purpose of this step is to conveniently apply parameter values for the existing CUBRID database environment to the new one.

  5. Install a new version of CUBRID

    Once backing up and unloading of the data created by the existing version of CUBRID have been completed, delete the existing version of CUBRID and its databases and then install the new version of CUBRID. For details on installing CUBRID, see Getting Started.

  6. Configure the new CUBRID environment

    Configure the new version of CUBRID by referring to configuration files of the existing database stored in the step 3, " Store the existing CUBRID configuration files ." For details on configuring new environment, see Installing and Running CUBRID in "Getting Started."

  7. Load the new database

    Create a database by using the cubrid createdb utility and then load the data which had previously been unloaded into the new database by using the cubrid loaddb utility. Please see createdb for creating a database and loaddb for loading a database.

  8. Back up the new database

    Once the data has been successfully loaded into the new database, back up the database created for the new version of CUBRID by using the cubrid backupdb utility. The reason for this step is because you cannot restore the data backed up in the existing version of CUBRID when using the new version. For details on backing up the database, see backupdb .

Warning

Even if the version is identical, the 32-bit database volume and the 64-bit database volume are not compatible for backup and recovery. Therefore, it is not recommended to recover a 32-bit database backup on the 64-bit CUBRID or vice versa.

spacedb

The cubrid spacedb utility is used to check how much space of database volumes is being used. It shows a brief description of all permanent data volumes in the database. Information returned by the cubrid spacedb utility includes the ID, name, purpose and total/free space of each volume. You can also check the total number of volumes and used/unused database pages.

cubrid spacedb [options] database_name
  • cubrid : An integrated utility for the CUBRID service and database management.
  • spacedb : A command that checks the space in the database. It executes successfully only when the database is in a stopped state.
  • database_name : The name of the database whose space is to be checked. The path-name to the directory where the database is to be created must not be included.

The following shows [options] available with the cubrid spacedb utility.

-o FILE

This option stores the result of checking the space information of testdb to a file named db_output.

cubrid spacedb -o db_output testdb
-S, --SA-mode

This option is used to access a database in standalone, which means it works without processing server; it does not have an argument. If -S is not specified, the system recognizes that a database is running in client/server mode.

cubrid spacedb --SA-mode testdb
-C, --CS-mode

This option is used to access a database in client/server mode, which means it works in client/server process respectively; it does not have an argument. If -C is not specified, the system recognize that a database is running in client/server mode by default.

cubrid spacedb --CS-mode testdb
--size-unit={PAGE|M|G|T|H}

This option specifies the size unit of the space information of the database to be one of PAGE, M(MB), G(GB), T(TB), H(print-friendly). The default value is H. If you set the value to H, the unit is automatically determined as follows: M if 1 MB = DB size < 1024 MB, G if 1 GB = DB size < 1024 GB.

$ cubrid spacedb --size-unit=M testdb
$ cubrid spacedb --size-unit=H testdb

Space description for database 'testdb' with pagesize 16.0K. (log pagesize: 16.0K)

Volid  Purpose    total_size   free_size  Vol Name

    0   GENERIC       20.0 M      17.0 M  /home1/cubrid/testdb
    1      DATA       20.0 M      19.5 M  /home1/cubrid/testdb_x001
    2     INDEX       20.0 M      19.6 M  /home1/cubrid/testdb_x002
    3      TEMP       20.0 M      19.6 M  /home1/cubrid/testdb_x003
    4      TEMP       20.0 M      19.9 M  /home1/cubrid/testdb_x004
-------------------------------------------------------------------------------
    5                100.0 M      95.6 M
Space description for temporary volumes for database 'testdb' with pagesize 16.0K.

Volid  Purpose    total_size   free_size  Vol Name

LOB space description file:/home1/cubrid/lob
-s, --summarize

This option aggregates total_pages, used_pages and free_pages by DATA, INDEX, GENERIC, TEMP and TEMP TEMP, and outputs them.

$ cubrid spacedb -s testdb

Summarized space description for database 'testdb' with pagesize 16.0K. (log pagesize: 16.0K)

Purpose     total_size   used_size   free_size  volume_count
-------------------------------------------------------------
      DATA      20.0 M       0.5 M      19.5 M          1
     INDEX      20.0 M       0.4 M      19.6 M          1
   GENERIC      20.0 M       3.0 M      17.0 M          1
      TEMP      40.0 M       0.5 M      39.5 M          2
 TEMP TEMP       0.0 M       0.0 M       0.0 M          0
-------------------------------------------------------------
     TOTAL     100.0 M       4.4 M      95.6 M          5
-p, --purpose

This option separates the used space as data_size, index_size and temp_size, and outputs them.

Space description for database 'testdb' with pagesize 16.0K. (log pagesize: 16.0K)

Volid  Purpose    total_size   free_size   data_size  index_size   temp_size  Vol Name

    0   GENERIC       20.0 M      17.0 M       2.1 M       0.9 M       0.0 M  /home1/cubrid/testdb
    1      DATA       20.0 M      19.5 M       0.4 M       0.0 M       0.0 M  /home1/cubrid/testdb_x001
    2     INDEX       20.0 M      19.6 M       0.0 M       0.4 M       0.0 M  /home1/cubrid/testdb_x002
    3      TEMP       20.0 M      19.6 M       0.0 M       0.0 M       0.3 M  /home1/cubrid/testdb_x003
    4      TEMP       20.0 M      19.9 M       0.0 M       0.0 M       0.1 M  /home1/cubrid/testdb_x004
----------------------------------------------------------------------------------------------------
    5                100.0 M      95.6 M       2.5 M       1.2 M       0.4 M
Space description for temporary volumes for database 'testdb' with pagesize 16.0K.

Volid  Purpose    total_size   free_size   data_size  index_size   temp_size  Vol Name

LOB space description file:/home1/cubrid/lob

Note

If you use -p and -s together, the summarized information of the used space will be separated as data_size, index_size and temp_size.

$ cubrid spacedb -s -p testdb
Summarized space description for database 'testdb' with pagesize 16.0K. (log pagesize: 16.0K)

Purpose     total_size   used_size   free_size   data_size  index_size   temp_size  volume_count
-------------------------------------------------------------------------------------------------
      DATA      20.0 M       0.5 M      19.5 M       0.4 M       0.0 M       0.0 M          1
     INDEX      20.0 M       0.4 M      19.6 M       0.0 M       0.4 M       0.0 M          1
   GENERIC      20.0 M       3.0 M      17.0 M       2.1 M       0.9 M       0.0 M          1
      TEMP      40.0 M       0.5 M      39.5 M       0.0 M       0.0 M       0.4 M          2
 TEMP TEMP       0.0 M       0.0 M       0.0 M       0.0 M       0.0 M       0.0 M          0
-------------------------------------------------------------------------------------------------
     TOTAL     100.0 M       4.4 M      95.6 M       2.5 M       1.2 M       0.4 M          5
compactdb

The cubrid compactdb utility is used to secure unused space of the database volume. In case the database server is not running (offline), you can perform the job in standalone mode. In case the database server is running, you can perform it in client-server mode.

Note

The cubrid compactdb utility secures the space being taken by OIDs of deleted objects and by class changes. When an object is deleted, the space taken by its OID is not immediately freed because there might be other objects that refer to the deleted one.

Therefore, when you make a table to reuse OIDs, it is recommended to use a REUSE_OID option as below.

CREATE TABLE tbl REUSE_OID
(
    id INT PRIMARY KEY,
    b VARCHAR
);

However, a table with a REUSE_OID option cannot be referred by the other table. That is, this table cannot be used as a type of the other table.

CREATE TABLE reuse_tbl (a INT PRIMARY KEY) REUSE_OID;
CREATE TABLE tbl_1 ( a reuse_tbl);
ERROR: The class 'reuse_tbl' is marked as REUSE_OID and is non-referable. Non-referable classes can't be the domain of an attribute and their instances' OIDs cannot be returned.

To see details of REUSE_OID, please refer to REUSE_OID.

Reference to the object deleted during compacting is displayed as NULL, which means this can be reused by OIDs.

cubrid compactdb [options] database_name [class_name], class_name2, ...]
  • cubrid: An integrated utility for the CUBRID service and database management.
  • compactdb: A command that compacts the space of the database so that OIDs assigned to deleted data can be reused.
  • database_name: The name of the database whose space is to be compacted. The path name to the directory where the database is to be created must not be included.
  • class_name_list: You can specify the list of tables names that you want to compact space after a database name; the -i option cannot be used together. It is used in client/server mode only.

-I, -i, -c, -d, -p options are applied in client/server mode only.

The following shows [options] available with the cubrid compactdb utility.

-v, --verbose

You can output messages that shows which class is currently being compacted and how many instances have been processed for the class by using the -v option.

cubrid compactdb -v testdb
-S, --SA-mode

This option specifies to compact used space in standalone mode while database server is not running; no argument is specified. If the -S option is not specified, system recognizes that the job is executed in client/server mode.

cubrid compactdb --SA-mode testdb
-C, --CS-mode

This option specifies to compact used space in client/server mode while database server is running; no argument is specified. Even though this option is omitted, system recognizes that the job is executed in client/server mode.

The following options can be used in client/server mode only.

-i, --input-class-file=FILE

You can specify an input file name that contains the table name with this option. Write one table name in a single line; invalid table name is ignored. Note that you cannot specify the list of the table names after a database name in case of you use this option.

-p, --pages-commited-once=NUMBER

You can specify the number of maximum pages that can be committed once with this option. The default value is 10, the minimum value is 1, and the maximum value is 10. The less option value is specified, the more concurrency is enhanced because the value for class/instance lock is small; however, it causes slowdown on operation, and vice versa.

cubrid compactdb --CS-mode -p 10 testdb tbl1, tbl2, tbl5
-d, --delete-old-repr

You can delete an existing table representation (schema structure) from catalog with this option. Generally you'd better keep the existing table representation because schema updating cost will be saved when you keep the status as referring to the past schema for the old records.

-I, --Instance-lock-timeout=NUMBER

You can specify a value of instance lock timeout with this option. The default value is 2 (seconds), the minimum value is 1, and the maximum value is 10. The less option value is specified, the more operation speeds up. However, the number of instances that can be processed becomes smaller, and vice versa.

-c, --class-lock-timeout=NUMBER

You can specify a value of instance lock timeout with this option. The default value is 10 (seconds), the minimum value is 1, and the maximum value is 10. The less option value is specified, the more operation speeds up. However, the number of tables that can be processed becomes smaller, and vice versa.

optimizedb

Updates statistical information such as the number of objects, the number of pages to access, and the distribution of attribute values.

cubrid optimizedb [option] database_name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • optimizedb: Updates the statistics information, which is used for cost-based query optimization of the database. If the option is specified, only the information of the specified class is updated.
  • database_name: The name of the database whose cost-based query optimization statistics are to be updated.

The following shows [option] available with the cubrid optimizedb utility.

-n, --class-name

The following example shows how to update the query statistics information of the given class by using the -n option.

cubrid optimizedb -n event_table testdb

The following example shows how to update the query statistics information of all classes in the database.

cubrid optimizedb testdb
plandump

The cubrid plandump utility is used to display information on the query plans stored (cached) on the server.

cubrid plandump [options] database_name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • plandump: A utility that displays the query plans stored in the current cache of a specific database.
  • database_name: The name of the database where the query plans are to be checked or dropped from its server cache.

If no option is used, it checks the query plans stored in the cache.

cubrid plandump testdb

The following shows [options] available with the cubrid plandump utility.

-d, --drop

This option drops the query plans stored in the cache.

cubrid plandump -d testdb
-o, --output-file=FILE

This option stores the results of the query plans stored in the cache to a file.

cubrid plandump -o output.txt testdb
statdump

cubrid statdump utility checks statistics information processed by the CUBRID database server. The statistics information mainly consists of the following: File I/O, Page buffer, Logs, Transactions, Concurrency/Lock, Index, and Network request.

You can also use CSQL's session commands to check the statistics information only about the CSQL's connection. For details, see Dumping CSQL execution statistics information.

cubrid statdump [options] database_name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • installdb: A command that dumps the statistics information on the database server execution.
  • database_name: The name of database which has the statistics data to be dumped.

The following shows [options] available with the cubrid statdump utility.

-i, --interval=SECOND

This option specifies the periodic number of Dumping statistics as seconds.

The following outputs the accumulated values per second.

cubrid statdump -i 1 -c demodb

The following outputs the accumulated values during 1 second, as starting with 0 value per every 1 second.

cubrid statdump -i 1 demodb

The following outputs the last values which were executed with -i option.

cubrid statdump demodb

The following outputs the same values with the above. -c option doesn't work if it is not used with -i option together.

cubrid statdump -c demodb

The following outputs the values per every 5 seconds.

$ cubrid statdump -i 5 -c testdb


Thu January 07 16:46:05 GTB Standard Time 2016

 *** SERVER EXECUTION STATISTICS ***
Num_file_creates              =          0
Num_file_removes              =          0
Num_file_ioreads              =          0
Num_file_iowrites             =          2
Num_file_iosynches            =          2
Num_file_page_allocs          =          0
Num_file_page_deallocs        =          0
Num_data_page_fetches         =       1742
Num_data_page_dirties         =         60
Num_data_page_ioreads         =          0
Num_data_page_iowrites        =          0
Num_data_page_victims         =          0
Num_data_page_iowrites_for_replacement =          0
Num_data_page_hash_anchor_waits =          0
Time_data_page_hash_anchor_wait =          0
Num_data_page_fixed           =          0
Num_data_page_dirty           =         15
Num_data_page_lru1            =          0
Num_data_page_lru2            =          0
Num_data_page_ain             =        128
Num_data_page_avoid_dealloc   =          0
Num_data_page_avoid_victim    =          0
Num_data_page_victim_cand     =          0
Num_log_page_fetches          =          0
Num_log_page_fetch_ioreads    =          0
Num_log_page_ioreads          =          0
Num_log_page_iowrites         =          2
Num_log_append_records        =         45
Num_log_archives              =          0
Num_log_start_checkpoints     =          0
Num_log_end_checkpoints       =          0
Num_log_wals                  =          0
Num_log_page_iowrites_for_replacement =          0
Num_page_locks_acquired       =          0
Num_object_locks_acquired     =         65
Num_page_locks_converted      =          0
Num_object_locks_converted    =         10
Num_page_locks_re-requested   =          0
Num_object_locks_re-requested =         46
Num_page_locks_waits          =          0
Num_object_locks_waits        =          0
Num_object_locks_time_waited_usec =          0
Num_tran_commits              =          3
Num_tran_rollbacks            =          1
Num_tran_savepoints           =          2
Num_tran_start_topops         =          6
Num_tran_end_topops           =          6
Num_tran_interrupts           =          0
Num_btree_inserts             =          3
Num_btree_deletes             =          0
Num_btree_updates             =          0
Num_btree_covered             =          0
Num_btree_noncovered          =          0
Num_btree_resumes             =          0
Num_btree_multirange_optimization =          0
Num_btree_splits              =          0
Num_btree_merges              =          0
Num_btree_get_stats           =          0
Num_heap_stats_sync_bestspace =          0
Num_query_selects             =          2
Num_query_inserts             =          0
Num_query_deletes             =          0
Num_query_updates             =          2
Num_query_sscans              =          2
Num_query_iscans              =          0
Num_query_lscans              =          1
Num_query_setscans            =          0
Num_query_methscans           =          0
Num_query_nljoins             =          1
Num_query_mjoins              =          0
Num_query_objfetches          =          0
Num_query_holdable_cursors    =          0
Num_sort_io_pages             =          0
Num_sort_data_pages           =          0
Num_network_requests          =         79
Num_adaptive_flush_pages      =          0
Num_adaptive_flush_log_pages  =          2
Num_adaptive_flush_max_pages  =     116610
Num_prior_lsa_list_size       =          5
Num_prior_lsa_list_maxed      =          0
Num_prior_lsa_list_removed    =          2
Num_heap_stats_bestspace_entries =          5
Num_heap_stats_bestspace_maxed =          0
Time_ha_replication_delay     =          0
Num_plan_cache_add            =          1
Num_plan_cache_lookup         =          2
Num_plan_cache_hit            =          0
Num_plan_cache_miss           =          2
Num_plan_cache_full           =          0
Num_plan_cache_delete         =          0
Num_plan_cache_invalid_xasl_id =          0
Num_plan_cache_query_string_hash_entries =          5
Num_plan_cache_xasl_id_hash_entries =          5
Num_plan_cache_class_oid_hash_entries =         10
Num_vacuum_log_pages_vacuumed =          0
Num_vacuum_log_pages_to_vacuum =          0
Num_vacuum_prefetch_requests_log_pages =          0
Num_vacuum_prefetch_hits_log_pages =          0
Num_heap_home_inserts         =          0
Num_heap_big_inserts          =          0
Num_heap_assign_inserts       =          4
Num_heap_home_deletes         =          0
Num_heap_home_mvcc_deletes    =          0
Num_heap_home_to_rel_deletes  =          0
Num_heap_home_to_big_deletes  =          0
Num_heap_rel_deletes          =          0
Num_heap_rel_mvcc_deletes     =          0
Num_heap_rel_to_home_deletes  =          0
Num_heap_rel_to_big_deletes   =          0
Num_heap_rel_to_rel_deletes   =          0
Num_heap_big_deletes          =          0
Num_heap_big_mvcc_deletes     =          0
Num_heap_new_ver_inserts      =          0
Num_heap_home_updates         =          6
Num_heap_home_to_rel_updates  =          0
Num_heap_home_to_big_updates  =          0
Num_heap_rel_updates          =          0
Num_heap_rel_to_home_updates  =          0
Num_heap_rel_to_rel_updates   =          0
Num_heap_rel_to_big_updates   =          0
Num_heap_big_updates          =          0
Num_heap_home_vacuums         =          0
Num_heap_big_vacuums          =          0
Num_heap_rel_vacuums          =          0
Num_heap_insid_vacuums        =          0
Num_heap_remove_vacuums       =          0
Num_heap_next_ver_vacuums     =          0
Time_heap_insert_prepare      =       1962
Time_heap_insert_execute      =      10007
Time_heap_insert_log          =         44
Time_heap_delete_prepare      =          0
Time_heap_delete_execute      =          0
Time_heap_delete_log          =          0
Time_heap_update_prepare      =        497
Time_heap_update_execute      =        972
Time_heap_update_log          =        267
Time_heap_vacuum_prepare      =          0
Time_heap_vacuum_execute      =          0
Time_heap_vacuum_log          =          0
Num_bt_find_unique            =          2
Num_btrange_search            =          0
Num_bt_insert_obj             =          3
Num_bt_delete_obj             =          0
Num_bt_mvcc_delete            =          0
Num_bt_mark_delete            =          0
Num_bt_update_sk_cnt          =          0
Num_bt_undo_insert            =          0
Num_bt_undo_delete            =          0
Num_bt_undo_mvcc_delete       =          0
Num_bt_undo_update_sk         =          0
Num_bt_vacuum                 =          0
Num_bt_vacuum_insid           =          0
Num_bt_vacuum_update_sk       =          0
Num_bt_fix_ovf_oids_cnt       =          0
Num_bt_unique_rlocks_cnt      =          0
Num_bt_unique_wlocks_cnt      =          0
Time_bt_find_unique           =         17
Time_bt_range_search          =          0
Time_bt_insert                =       1845
Time_bt_delete                =          0
Time_bt_mvcc_delete           =          0
Time_bt_mark_delete           =          0
Time_bt_update_sk             =          0
Time_bt_undo_insert           =          0
Time_bt_undo_delete           =          0
Time_bt_undo_mvcc_delete      =          0
Time_bt_undo_update_sk        =          0
Time_bt_vacuum                =          0
Time_bt_vacuum_insid          =          0
Time_bt_vacuum_update_sk      =          0
Time_bt_traverse              =       1616
Time_bt_find_unique_traverse  =        716
Time_bt_range_search_traverse =          0
Time_bt_insert_traverse       =        900
Time_bt_delete_traverse       =          0
Time_bt_mvcc_delete_traverse  =          0
Time_bt_mark_delete_traverse  =          0
Time_bt_update_sk_traverse    =          0
Time_bt_undo_insert_traverse  =          0
Time_bt_undo_delete_traverse  =          0
Time_bt_undo_mvcc_delete_traverse =          0
Time_bt_undo_update_sk_traverse =          0
Time_bt_vacuum_traverse       =          0
Time_bt_vacuum_insid_traverse =          0
Time_bt_vacuum_update_sk_traverse =          0
Time_bt_fix_ovf_oids          =          0
Time_bt_unique_rlocks         =          0
Time_bt_unique_wlocks         =          0
Time_vacuum_master            =     152858
Time_vacuum_worker_process_log =          0
Time_vacuum_worker_execute    =          0

 *** OTHER STATISTICS ***
Data_page_buffer_hit_ratio    =     100.00
Log_page_buffer_hit_ratio     =       0.00
Vacuum_data_page_buffer_hit_ratio =       0.00
Vacuum_page_efficiency_ratio  =       0.00
Vacuum_page_fetch_ratio       =       0.00
Data_page_fix_lock_acquire_time_msec =       0.00
Data_page_fix_hold_acquire_time_msec =       0.00
Data_page_fix_acquire_time_msec =      11.80
Data_page_allocate_time_ratio =     100.00
Data_page_total_promote_success =       3.00
Data_page_total_promote_fail  =       0.00
Data_page_total_promote_time_msec =       0.00
Num_data_page_fix_ext:
WORKER,PAGE_FTAB     ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =         17
WORKER,PAGE_FTAB     ,OLD_PAGE_IN_PB    ,WRITE,UNCOND      =          2
WORKER,PAGE_HEAP     ,OLD_PAGE_IN_PB    ,READ ,COND        =        194
WORKER,PAGE_HEAP     ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =          9
WORKER,PAGE_HEAP     ,OLD_PAGE_IN_PB    ,WRITE,COND        =         18
WORKER,PAGE_HEAP     ,OLD_PAGE_IN_PB    ,WRITE,UNCOND      =          2
WORKER,PAGE_VOLHEADER,OLD_PAGE_IN_PB    ,READ ,COND        =          8
WORKER,PAGE_VOLHEADER,OLD_PAGE_IN_PB    ,READ ,UNCOND      =        914
WORKER,PAGE_VOLBITMAP,OLD_PAGE_IN_PB    ,READ ,COND        =          4
WORKER,PAGE_VOLBITMAP,OLD_PAGE_IN_PB    ,READ ,UNCOND      =        457
WORKER,PAGE_XASL     ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =          2
WORKER,PAGE_XASL     ,OLD_PAGE_IN_PB    ,WRITE,UNCOND      =          1
WORKER,PAGE_CATALOG  ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =         75
WORKER,PAGE_CATALOG  ,OLD_PAGE_IN_PB    ,WRITE,UNCOND      =         10
WORKER,PAGE_BTREE_R  ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =         29
Num_data_page_promote_ext:
WORKER,PAGE_BTREE_R  ,SHARED_READER,READ ,SUCCESS =          3
Num_data_page_promote_time_ext:
WORKER,PAGE_BTREE_R  ,SHARED_READER,READ ,SUCCESS =          3
Num_data_page_unfix_ext:
WORKER,PAGE_FTAB     ,BUF_NON_DIRTY,HOLDER_NON_DIRTY,READ  =         16
WORKER,PAGE_FTAB     ,BUF_NON_DIRTY,HOLDER_DIRTY    ,WRITE =          2
WORKER,PAGE_FTAB     ,BUF_DIRTY    ,HOLDER_NON_DIRTY,READ  =          1
WORKER,PAGE_HEAP     ,BUF_NON_DIRTY,HOLDER_NON_DIRTY,READ  =        185
WORKER,PAGE_HEAP     ,BUF_NON_DIRTY,HOLDER_DIRTY    ,WRITE =          9
WORKER,PAGE_HEAP     ,BUF_NON_DIRTY,HOLDER_DIRTY    ,MIXED =          2
WORKER,PAGE_HEAP     ,BUF_DIRTY    ,HOLDER_NON_DIRTY,READ  =         14
WORKER,PAGE_HEAP     ,BUF_DIRTY    ,HOLDER_NON_DIRTY,WRITE =          4
WORKER,PAGE_HEAP     ,BUF_DIRTY    ,HOLDER_DIRTY    ,WRITE =          3
WORKER,PAGE_HEAP     ,BUF_DIRTY    ,HOLDER_DIRTY    ,MIXED =          6
WORKER,PAGE_VOLHEADER,BUF_NON_DIRTY,HOLDER_NON_DIRTY,READ  =         14
WORKER,PAGE_VOLHEADER,BUF_DIRTY    ,HOLDER_NON_DIRTY,READ  =        908
WORKER,PAGE_VOLBITMAP,BUF_NON_DIRTY,HOLDER_NON_DIRTY,READ  =        461
WORKER,PAGE_XASL     ,BUF_NON_DIRTY,HOLDER_DIRTY    ,WRITE =          1
WORKER,PAGE_XASL     ,BUF_DIRTY    ,HOLDER_NON_DIRTY,READ  =          2
WORKER,PAGE_CATALOG  ,BUF_NON_DIRTY,HOLDER_NON_DIRTY,READ  =         47
WORKER,PAGE_CATALOG  ,BUF_NON_DIRTY,HOLDER_DIRTY    ,WRITE =          1
WORKER,PAGE_CATALOG  ,BUF_DIRTY    ,HOLDER_NON_DIRTY,READ  =         28
WORKER,PAGE_CATALOG  ,BUF_DIRTY    ,HOLDER_NON_DIRTY,WRITE =          1
WORKER,PAGE_CATALOG  ,BUF_DIRTY    ,HOLDER_DIRTY    ,WRITE =          8
WORKER,PAGE_BTREE_R  ,BUF_NON_DIRTY,HOLDER_NON_DIRTY,READ  =         18
WORKER,PAGE_BTREE_R  ,BUF_NON_DIRTY,HOLDER_DIRTY    ,MIXED =          3
WORKER,PAGE_BTREE_R  ,BUF_DIRTY    ,HOLDER_NON_DIRTY,READ  =          8
Time_data_page_lock_acquire_time:
Time_data_page_hold_acquire_time:
Time_data_page_fix_acquire_time:
WORKER,PAGE_FTAB     ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =               65
WORKER,PAGE_FTAB     ,OLD_PAGE_IN_PB    ,WRITE,UNCOND      =               12
WORKER,PAGE_HEAP     ,OLD_PAGE_IN_PB    ,READ ,COND        =              617
WORKER,PAGE_HEAP     ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =               42
WORKER,PAGE_HEAP     ,OLD_PAGE_IN_PB    ,WRITE,COND        =               81
WORKER,PAGE_HEAP     ,OLD_PAGE_IN_PB    ,WRITE,UNCOND      =                9
WORKER,PAGE_VOLHEADER,OLD_PAGE_IN_PB    ,READ ,COND        =               36
WORKER,PAGE_VOLHEADER,OLD_PAGE_IN_PB    ,READ ,UNCOND      =             3277
WORKER,PAGE_VOLBITMAP,OLD_PAGE_IN_PB    ,READ ,COND        =               18
WORKER,PAGE_VOLBITMAP,OLD_PAGE_IN_PB    ,READ ,UNCOND      =             1533
WORKER,PAGE_XASL     ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =                5
WORKER,PAGE_XASL     ,OLD_PAGE_IN_PB    ,WRITE,UNCOND      =             5644
WORKER,PAGE_CATALOG  ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =              260
WORKER,PAGE_CATALOG  ,OLD_PAGE_IN_PB    ,WRITE,UNCOND      =               43
WORKER,PAGE_BTREE_R  ,OLD_PAGE_IN_PB    ,READ ,UNCOND      =              164
Num_mvcc_snapshot_ext:
DELETE  ,INS_VACUUMED      ,VISIBLE   =                7
DIRTY   ,INS_VACUUMED      ,VISIBLE   =                3
DIRTY   ,INS_CURR          ,VISIBLE   =                2
SNAPSHOT,INS_VACUUMED      ,VISIBLE   =               87
SNAPSHOT,DELETED_COMMITED  ,INVISIBLE =                1
Time_obj_lock_acquire_time:
Time_get_snapshot_acquire_time:
WORKER =               14
Count_get_snapshot_retry:
WORKER =               11
Time_tran_complete_time:
WORKER =               19
Time_get_oldest_mvcc_acquire_time:
SYSTEM =           112110
Count_get_oldest_mvcc_retry:
WORKER =                1

The following are the explanation about the above statistical information.

Category Item Description
File I/O Num_file_removes The number of files removed
Num_file_creates The number of files created
Num_file_ioreads The number of files read
Num_file_iowrites The number of files stored
Num_file_iosynches The number of file synchronization
Page buffer Num_data_page_fetches The number of fetched pages
Num_data_page_dirties The number of dirty pages
Num_data_page_ioreads The number of pages read from disk (more means less efficient, it correlates with lower hit ratio)
Num_data_page_iowrites The number of pages write to disk (more means less efficient)
Num_data_page_victims The number of times the flushing thread is wake up (NOT the number of victims or flushed pages)
Num_data_page_iowrites_for_replacement The number of the written data pages specified as victim
Num_data_page_hash_anchor_waits The number of instances any hash anchor had to wait for mutex acquisition
Time_data_page_hash_anchor_wait The total time in microseconds any hash anchor had to wait for mutex acquisition
Num_data_page_fixed The number of fixed pages in data buffer (snapshot counter)
Num_data_page_dirty The number of dirty pages in data buffer (snapshot counter)
Num_data_page_lru1 The number of pages in LRU1 zone in data buffer (snapshot counter)
Num_data_page_lru2 The number of pages in LRU2 zone in data buffer (snapshot counter)
Num_data_page_ain The number of pages in AIN zone in data buffer (snapshot counter)
Num_data_page_avoid_dealloc The number of pages in data buffer having 'avoid_dealloc_cnt > 0' (snapshot counter)
Num_data_page_avoid_victim The number of pages in data buffer having 'avoid_victim' flag set (snapshot counter)
Num_data_page_victim_cand The number of pages in data buffer which are victim candidates (snapshot counter)
Num_data_page_victim_cand The number of pages in data buffer which are victim candidates (snapshot counter)
Num_adaptive_flush_pages The number of data pages flushed from the data buffer to the disk
Num_adaptive_flush_log_pages The number of log pages flushed from the log buffer to the disk
Num_adaptive_flush_max_pages The maximum number of pages allowed to flush from data and the log buffer to the disk
Num_prior_lsa_list_size Current size of the prior LSA(Log Sequence Address) list. CUBRID write the order of writing into the prior LSA list, before writing operation from the log buffer to the disk; this list is used to raise up the concurrency by reducing the waiting time of the transaction from writing to disk
Num_prior_lsa_list_maxed The count of the prior LSA list being reached at the maximum size. The maximum size of the prior LSA list is log_buffer_size * 2. If this value is big, we can assume that log writing jobs happen a lot at the same time
Num_prior_lsa_list_removed The count of LSA being moved from prior LSA list into log buffer. We can assume that the commits have happened at the similar count with this value
Logs Num_log_page_fetches The number of fetched log pages
Num_log_page_fetch_ioreads The number of I/O reads of fetched log pages
Num_log_page_ioreads The number of log pages read
Num_log_page_iowrites The number of log pages stored
Num_log_append_records The number of log records appended
Num_log_archives The number of logs archived
Num_log_start_checkpoints The number of started checkpoints
Num_log_end_checkpoints The number of ended checkpoints
Num_log_wals Not used
Num_log_page_iowrites_for_replacement The number of log data pages discarded from log page buffer due to page replacements
Concurrency/lock Num_page_locks_acquired The number of locked pages acquired
Num_object_locks_acquired The number of locked objects acquired
Num_page_locks_converted The number of locked pages converted
Num_object_locks_converted The number of locked objects converted
Num_page_locks_re-requested The number of locked pages requested
Num_object_locks_re-requested The number of locked objects requested
Num_page_locks_waits The number of locked pages waited
Num_object_locks_waits The number of locked objects waited
Num_object_locks_time_waited_usec The time in microseconds spent on waiting for all object locks
Transactions Num_tran_commits The number of commits
Num_tran_rollbacks The number of rollbacks
Num_tran_savepoints The number of savepoints
Num_tran_start_topops The number of top operations started
Num_tran_end_topops The number of top operations stopped
Num_tran_interrupts The number of interruptions
Index Num_btree_inserts The number of nodes inserted
Num_btree_deletes The number of nodes deleted
Num_btree_updates The number of nodes updated
Num_btree_covered The number of cases in which an index includes all data upon query execution
Num_btree_noncovered The number of cases in which an index includes some or no data upon query execution
Num_btree_resumes The exceeding number of index scan specified in index_scan_oid_buffer_pages
Num_btree_multirange_optimization The number of executions on multi-range optimization for the WHERE ... IN ... LIMIT condition query statement
Num_btree_splits The number of B-tree split-operations
Num_btree_merges The number of B-tree merge-operations
Num_bt_find_unique The number of B-tree 'find-unique' operations
Num_btrange_search The number of B-tree 'range-search' operations
Num_bt_insert_obj The number of B-tree 'insert object' operations
Num_bt_delete_obj The number of B-tree 'physical delete object' operations
Num_bt_mvcc_delete The number of B-tree 'mvcc delete' operations
Num_bt_mark_delete The number of B-tree mark delete operations
Num_bt_update_sk_cnt The number of B-tree 'update same key' operations
Num_bt_undo_insert The number of B-tree 'undo insert' operations
Num_bt_undo_delete The number of B-tree 'undo physical delete' operations
Num_bt_undo_mvcc_delete The number of B-tree 'undo mvcc delete' operations
Num_bt_undo_update_sk The number of B-tree 'undo update same key' operations
Num_bt_vacuum The number of B-tree vacuum deleted object operations
Num_bt_vacuum_insid The number of vacuum operations on B-tree 'insert id'
Num_bt_vacuum_update_sk The number of vacuum operations on B-tree 'update same key'
Num_bt_fix_ovf_oids_cnt The number of B-tree overflow page fixes
Num_bt_unique_rlocks_cnt The number of blocked read locks on unique indexes
Num_bt_unique_wlocks_cnt The number of blocked write locks on unique indexes
Time_bt_find_unique Time consumed on B-tree 'find-unique' operations
Time_bt_range_search Time consumed on B-tree 'range search' operations
Time_bt_insert Time consumed on B-tree insert object operations
Time_bt_delete Time consumed on B-tree physical delete operations
Time_bt_mvcc_delete Time consumed on B-tree mvcc delete operations
Time_bt_mark_delete Time consumed on B-tree mark delete operations
Time_bt_update_sk Time consumed on B-tree 'update same key' operations
Time_bt_undo_insert Time consumed on B-tree 'undo insert' operations
Time_bt_undo_delete Time consumed on B-tree 'undo physical delete' operations
Time_bt_undo_mvcc_delete Time consumed on B-tree 'undo mvcc delete' operations
Time_bt_undo_update_sk Time consumed on B-tree 'undo update same key' operations
Time_bt_vacuum Time consumed on B-tree vacuum deleted object operations
Time_bt_vacuum_insid Time consumed on B-tree vacuum operations of 'insert id'
Time_bt_vacuum_update_sk Time consumed on B-tree vacuum operations of 'update same key'
Time_bt_traverse Time consumed on B-tree traverse operations
Time_bt_find_unique_traverse Time consumed on B-tree traverse operations for 'find unique'
Time_bt_range_search_traverse Time consumed on B-tree traverse operations for 'range search'
Time_bt_insert_traverse Time consumed on B-tree traverse operations for 'insert'
Time_bt_delete_traverse Time consumed on B-tree traverse operations for 'physical delete'
Time_bt_mvcc_delete_traverse Time consumed on B-tree traverse operations for 'mvcc delete'
Time_bt_mark_delete_traverse Time consumed on B-tree traverse operations for 'mark delete'
Time_bt_update_sk_traverse Time consumed on B-tree traverse operations for 'update same key'
Time_bt_undo_insert_traverse Time consumed on B-tree traverse operations for 'undo physical insert'
Time_bt_undo_delete_traverse Time consumed on B-tree traverse operations for 'undo physical delete'
Time_bt_undo_mvcc_delete_traverse Time consumed on B-tree traverse operations for 'undo delete'
Time_bt_undo_update_sk_traverse Time consumed on B-tree traverse operations for 'undo update same key'
Time_bt_vacuum_traverse Time consumed on B-tree traverse operations for vacuum deleted object
Time_bt_vacuum_insid_traverse Time consumed on B-tree traverse operations for vacuum 'insert id'
Time_bt_vacuum_update_sk_traverse Time consumed on B-tree traverse operations for vacuum 'update same key'
Time_bt_fix_ovf_oids Time consumed on B-tree overflow pages fix
Time_bt_unique_rlocks Time consumed on read locks on unique indexes
Time_bt_unique_wlocks Time consumed on write locks on unique indexes
Query Num_query_selects The number of SELECT query execution
Num_query_inserts The number of INSERT query execution
Num_query_deletes The number of DELETE query execution
Num_query_updates The number of UPDATE query execution
Num_query_sscans The number of sequential scans (full scan)
Num_query_iscans The number of index scans
Num_query_lscans The number of LIST scans
Num_query_setscans The number of SET scans
Num_query_methscans The number of METHOD scans
Num_query_nljoins The number of nested loop joins
Num_query_mjoins The number of parallel joins
Num_query_objfetches The number of fetch objects
Num_query_holdable_cursors The number of holdable cursors in the current server.
Sort Num_sort_io_pages The number of pages fetched on the disk during sorting(more means less efficient)
Num_sort_data_pages The number of pages found on the page buffer during sorting(more means more efficient)
Network request Num_network_requests The number of network requested
Heap Num_heap_stats_bestspace_entries The number of best pages which are saved on the "best page" list
Num_heap_stats_bestspace_maxed The maximum number of best pages which can be saved on the "best page" list
Num_heap_stats_sync_bestspace

The updated number of the "best page" list.

"Best pages" means that the data pages of which the free space is more than 30% in the environment of multiple INSERTs and DELETEs. Only some information of these pages are saved as the "best page" list. In the "best page" list, the information of a million pages is saved at once. This list is searched when INSERTing a record, and then this list is updated when there are no free space to store this record on the pages. If there are still no free space to store this record even this list is updated for several times, this recored is stored into a new page.

Num_heap_home_inserts The number of inserts in heap HOME type records
Num_heap_big_inserts The number of inserts in heap BIG type records
Num_heap_assign_inserts The number of inserts in heap ASSIGN type records
Num_heap_home_deletes The number of deletes from heap HOME type records in non-MVCC mode
Num_heap_home_mvcc_deletes The number of deletes from heap HOME type records in MVCC mode
Num_heap_home_to_rel_deletes The number of deletes from heap HOME to RELOCATION type records in MVCC mode
Num_heap_home_to_big_deletes The number of deletes from heap HOME to BIG type records in MVCC mode
Num_heap_rel_deletes The number of deletes from heap RELOCATION type records in non-MVCC mode
Num_heap_rel_mvcc_deletes The number of deletes from heap RELOCATION type records in MVCC mode
Num_heap_rel_to_home_deletes The number of deletes from heap RELOCATION to HOME type records in MVCC mode
Num_heap_rel_to_big_deletes The number of deletes from heap RELOCATION to BIG type records in MVCC mode
Num_heap_rel_to_rel_deletes The number of deletes from heap RELOCATION to RELOCATION type records in MVCC mode
Num_heap_big_deletes The number of deletes from heap BIG type records in non-MVCC mode
Num_heap_big_mvcc_deletes The number of deletes from heap BIG type records in MVCC mode
Num_heap_new_ver_inserts The number of inserts of new versions of the same object in MVCC mode
Num_heap_home_updates The number of updates in place of heap HOME type records in non-MVCC mode(*)
Num_heap_home_to_rel_updates The number of updates of heap HOME to RELOCATION type records in non-MVCC mode(*)
Num_heap_home_to_big_updates The number of updates of heap HOME to BIG type records in non-MVCC mode(*)
Num_heap_rel_updates The number of updates of heap RELOCATION type records in non-MVCC mode(*)
Num_heap_rel_to_home_updates The number of updates of heap RELOCATION to HOME type records in non-MVCC mode(*)
Num_heap_rel_to_rel_updates The number of updates of heap RELOCATION to RELOCATION type records in non-MVCC mode(*)
Num_heap_rel_to_big_updates The number of updates of heap RELOCATION to BIG type records in non-MVCC mode(*)
Num_heap_big_updates The number of updates of heap BIG type records in non-MVCC mode(*)
Num_heap_home_vacuums The number of vacuumed heap HOME type records
Num_heap_big_vacuums The number of vacuumed heap BIG type records
Num_heap_rel_vacuums The number of vacuumed heap RELOCATION type records
Num_heap_insid_vacuums The number of vacuumed heap newly inserted records
Num_heap_remove_vacuums The number of vacuum operations that remove version and don’t keep next version
Num_heap_next_ver_vacuums The number of vacuum operations that remove version and keep their next version
Time_heap_insert_prepare The time spend on preparing heap insert operation
Time_heap_insert_execute The time spend on executing heap insert operation
Time_heap_insert_log The time spend on logging heap insert operation
Time_heap_delete_prepare The time spend on preparing heap delete operation
Time_heap_delete_execute The time spend on executing heap delete operation
Time_heap_delete_log The time spend on logging heap delete operation
Time_heap_update_prepare The time spend on preparing heap update operation
Time_heap_update_execute The time spend on executing heap update operation
Time_heap_update_log The time spend on logging heap update operation
Time_heap_vacuum_prepare The time spend on preparing heap vacuum operation
Time_heap_vacuum_execute The time spend on executing heap vacuum operation
Time_heap_vacuum_log The time spend on logging heap vacuum operation
Query plan cache Num_plan_cache_add The number of newly added cache entry
Num_plan_cache_lookup The number of lookup try with a special key
Num_plan_cache_hit The number of the hit entries in the query string hash table
Num_plan_cache_miss The number of the missed entries in the query string hash table
Num_plan_cache_full The number of the victim retrieval by the full plan cache
Num_plan_cache_delete The number of victimized cache entries
Num_plan_cache_invalid_xasl_id The number of missed entries in the xasl_id hash table. The number of errors occurred when some entries are requested in the client during those entries are victimized in the server
Num_plan_cache_query_string_hash_entries The current entry number of the query string hash table
Num_plan_cache_xasl_id_hash_entries The current entry number of xasl id hash table
Num_plan_cache_class_oid_hash_entries The current entry number of class oid hash table
HA Time_ha_replication_delay Replication latency time (sec.)
Vacuuming Num_vacuum_log_pages_vacuumed The number of data pages vacuumed by vacuum workers. This counter is not update in real-time.
Num_vacuum_log_pages_to_vacuum The number of data pages to be vaccumed by vacuum workers
Num_vacuum_prefetch_requests_log_pages The number of requests to prefetch buffer for log pages from vacuum
Num_vacuum_prefetch_hits_log_pages The number of hits to prefetch buffer for log pages from vacuum
Time_vacuum_master Time consumed by vacuum master thread
Time_vacuum_worker_process_log Time consumed by vacuum worker thread for logging
Time_vacuum_worker_execute Time consumed by vacuum worker thread for execution
Other Data_page_buffer_hit_ratio Hit ratio of data page buffers (Num_data_page_fetches - Num_data_page_ioreads)*100 / Num_data_page_fetches
Log_page_buffer_hit_ratio Hit ratio of log page buffers (Num_log_page_fetches - Num_log_page_fetch_ioreads)*100 / Num_log_page_fetches
Vacuum_data_page_buffer_hit_ratio Hit ratio of vacuuming data page buffers
Vacuum_page_efficiency_ratio Ratio between number of page unfix of vacuum with dirty flag and total number of page unfix of vacuum. Ideally, the vacuum process performs only write operations since it cleans up all unused records. Even with an optimized vacuum process, 100% eficiency is not possible.
Vacuum_page_fetch_ratio Ratio (percentage) of page unfix from vacuum module and total page unfix.
Data_page_fix_lock_acquire_time_msec Cumulated time to acquire page lock
Data_page_fix_hold_acquire_time_msec Cumulated time to acquire page hold
Data_page_fix_acquire_time_msec Cumulated time to acquire fix
Data_page_allocate_time_ratio Ratio of cumulated time necessary for page allocation (Data_page_fix_acquire_time_msec - Data_page_fix_hold_acquire_time_msec - Data_page_fix_lock_acquire_time_msec)*100 / Data_page_fix_acquire_time_msec Large values indicate the IO as main bottleneck, small value indicate concurrency as main bottleneck (page hold and lock times).
Data_page_total_promote_success Cumulated number of successfully latch promote
Data_page_total_promote_fail Cumulated number of failed latch promote
Data_page_total_promote_time_msec Cumulated time to promote latch
Num_data_page_fix_ext: The number of data page fix by module, page type, and if page is new old or if is found in page buffer.
Num_data_page_unfix_ext: The number of data page unfix by module, page type, and if page was dirtied or clean.
Time_data_page_lock_acquire_time: time to acquire page lock (partitioned by module,page type and mode, latch mode, condition mode).
Time_data_page_hold_acquire_time: Time to acquire page hold (partitioned by module,page type and mode, latch mode).
Time_data_page_fix_acquire_time: Time to acquire page fix (partitioned by module,page type and mode, latch mode, condition mode).
Num_mvcc_snapshot_ext: The number of snapshot validation functions are called (partitioned by snapshot type, record type, visibility result upon validation).
Time_obj_lock_acquire_time: Time required to acquire object lock (partitioned by module, lock type)
Time_get_snapshot_acquire_time: Time required by snapshot validation functions (partitioned by snapshot type, record type, visibility result upon validation).
Count_get_snapshot_retry: The number of retries to acquire MVCC snapshot (partitioned by module)
Time_tran_complete_time: Time spent to invalidate snapshot and MVCCID on transaction commit/rollback (partitioned by module)
Time_get_oldest_mvcc_acquire_time: Time spend to acquire "oldest MVCC ID" (partitioned by module)
Count_get_oldest_mvcc_retry: The number of retries to acquire "oldest MVCC ID" (partitioned by module)

Note

(*) : These statistics measure the non-MVCC operations or MVCC operations which are performed in-place (decided internally)

-o, --output-file=FILE

-o options is used to store statistics information of server processing for the database to a specified file.

cubrid statdump -o statdump.log testdb
-c, --cumulative

You can display the accumulated operation statistics information of the target database server by using the -c option.

Num_data_page_fix_ext, Num_data_page_unfix_ext, Time_data_page_hold_acquire_time, Time_data_page_fix_acquire_time information can be output only when this option is specified; however, these informations will be omitted because they are for CUBRID Engine developers.

By combining this with the -i option, you can check the operation statistics information at a specified interval.

cubrid statdump -i 5 -c testdb
-s, --substr=STRING

You can display statistics about items, the names of which include the specified string by using -s option.

The following example shows how to display statistics about items, the names of which include "data".

cubrid statdump -s data testdb

*** SERVER EXECUTION STATISTICS ***
Num_data_page_fetches         =        135
Num_data_page_dirties         =          0
Num_data_page_ioreads         =          0
Num_data_page_iowrites        =          0
Num_data_page_victims         =          0
Num_data_page_iowrites_for_replacement =          0

 *** OTHER STATISTICS ***
Data_page_buffer_hit_ratio    =     100.00

Note

Each status information consists of 64-bit INTEGER data and the corresponding statistics information can be lost if the accumulated value exceeds the limit.

lockdb

The cubrid lockdb utility is used to check the information on the lock being used by the current transaction in the database.

cubrid lockdb [options] database_name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • lockdb: A command used to check the information on the lock being used by the current transaction in the database.
  • database_name: The name of the database where lock information of the current transaction is to be checked.

The following example shows how to display lock information of the testdb database on a screen without any option.

cubrid lockdb testdb

The following shows [options] available with the cubrid statdump utility.

-o, --output-file=FILE

The -o option displays the lock information of the testdb database as a output.txt.

cubrid lockdb -o output.txt testdb
Output Contents

The output contents of cubrid lockdb are divided into three logical sections.

  • Server lock settings
  • Clients that are accessing the database
  • The contents of an object lock table

Server lock settings

The first section of the output of cubrid lockdb is the database lock settings.

*** Lock Table Dump ***
 Lock Escalation at = 100000, Run Deadlock interval = 0

The lock escalation level is 100,000 records, and the interval to detect deadlock is set to 0 seconds.

For a description of the related system parameters, lock_escalation and deadlock_detection_interval, see Concurrency/Lock-Related Parameters.

Clients that are accessing the database

The second section of the output of cubrid lockdb includes information on all clients that are connected to the database. This includes the transaction index, program name, user ID, host name, process ID, isolation level and lock timeout settings of each client.

Transaction (index 1, csql, dba@cubriddb|12854)
Isolation COMMITTED READ
Timeout_period : Infinite wait

Here, the transaction index is 1, the program name is csql, the user ID is dba, the host name is cubriddb, the client process identifier is 12854, the isolation level is COMMITTED READ and the lock timeout is unlimited.

A client for which transaction index is 0 is the internal system transaction. It can obtain the lock at a specific time, such as the processing of a checkpoint by a database. In most cases, however, this transaction will not obtain any locks.

Because cubrid lockdb utility accesses the database to obtain the lock information, the cubrid lockdb is an independent client and will be output as such.

Object lock table

The third section of the output of the cubrid lockdb includes the contents of the object lock table. It shows which client has the lock for which object in which mode, and which client is waiting for which object in which mode. The first part of the result of the object lock table shows how many objects are locked.

Object lock Table:
    Current number of objects which are locked = 2001

cubrid lockdb outputs the OID, object type and table name of each object that obtained lock. In addition, it outputs the number of transactions that hold lock for the object (Num holders), the number of transactions (Num blocked-holders) that hold lock but are blocked since it could not convert the lock to the upper lock (e.g., conversion from SCH_S_LOCK to SCH_M_LOCK), and the number of different transactions that are waiting for the lock of the object (Num waiters). It also outputs the list of client transactions that hold lock, blocked client transactions and waiting client transactions. For rows, but not class, MVCC information is also shown.

The example below shows an object in which the object type is a class, that will be blocked because the class OID( 0| 62| 5 ) that has IX_LOCK for transaction 1 and SCH_S_LOCK for transaction 2 cannot be converted into SCH_M_LOCK. It also shows that transaction 3 is blocked because transaction 2 is waiting for SCH_M_LOCK even when transaction 3 is only waiting for SCH_S_LOCK.

OID = 0| 62| 5
Object type: Class = athlete.
Num holders = 1, Num blocked-holders= 1, Num waiters = 1
LOCK HOLDERS :
    Tran_index = 1, Granted_mode = IX_LOCK, Count = 1, Nsubgranules = 1
BLOCKED LOCK HOLDERS :
    Tran_index = 2, Granted_mode = SCH_S_LOCK, Count = 1, Nsubgranules = 0
    Blocked_mode = SCH_M_LOCK
                    Start_waiting_at = Wed Feb 3 14:44:31 2016
                    Wait_for_secs = -1
LOCK WAITERS :
    Tran_index = 3, Blocked_mode = SCH_S_LOCK
                    Start_waiting_at = Wed Feb 3 14:45:14 2016
                    Wait_for_secs = -1

The next example shows an instance of class, object OID( 2| 50| 1 ), that was inserted by transaction 1 which holds X_LOCK on the object. The class has a unique index and the key of inserted instance is about to be modified by transaction 2, which is blocked until transaction 1 is completed.

OID = 2| 50| 1
Object type: instance of class ( 0| 62| 5) = athlete.
MVCC info: insert ID = 6, delete ID = missing.
Num holders = 1, Num blocked-holders= 1, Num waiters = 1
LOCK HOLDERS :
    Tran_index =   1, Granted_mode =   X_LOCK, Count =   1
LOCK WAITERS :
    Tran_index =   2, Blocked_mode = X_LOCK
                      Start_waiting_at = Wed Feb 3 14:45:14 2016
                      Wait_for_secs = -1

Granted_mode refers to the mode of the obtained lock, and Blocked_mode refers to the mode of the blocked lock. Starting_waiting_at refers to the time at which the lock was requested, and Wait_for_secs refers to the waiting time of the lock. The value of Wait_for_secs is determined by lock_timeout, a system parameter.

When the object type is a class (table), Nsubgranules is displayed, which is the sum of the record locks and the key locks obtained by a specific transaction in the table.

OID = 0| 62| 5
Object type: Class = athlete.
Num holders = 2, Num blocked-holders= 0, Num waiters= 0
LOCK HOLDERS:
Tran_index = 3, Granted_mode = IX_LOCK, Count = 2, Nsubgranules = 0
Tran_index = 1, Granted_mode = IX_LOCK, Count = 3, Nsubgranules = 1
Tran_index = 2, Granted_mode = IX_LOCK, Count = 2, Nsubgranules = 1
tranlist

The cubrid tranlist is used to check the transaction information of the target database. Only DBA or DBA group can use this utility.

cubrid tranlist [options] database_name

If you omit the [options], it displays the total information about each transaction.

"cubrid tranlist demodb" outputs the similar result with "cubrid killtran -q demodb", but tranlist outputs more items; "User name" and "Host name". "cubrid tranlist -s demodb" outputs the same result with "cubrid killtran -d demodb".

The following shows what information is displayed when you run "cubrid tranlist demodb".

$ cubrid tranlist demodb

Tran index          User name      Host name      Process id    Program name              Query time    Tran time       Wait for lock holder      SQL_ID       SQL Text
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   1(ACTIVE)           public     test-server           1681    broker1_cub_cas_1               0.00         0.00                       -1     *** empty ***
   2(ACTIVE)           public     test-server           1682    broker1_cub_cas_2               0.00         0.00                       -1     *** empty ***
   3(ACTIVE)           public     test-server           1683    broker1_cub_cas_3               0.00         0.00                       -1     *** empty ***
   4(ACTIVE)           public     test-server           1684    broker1_cub_cas_4               1.80         1.80                  3, 2, 1     e5899a1b76253   update ta set a = 5 where a > 0
   5(ACTIVE)           public     test-server           1685    broker1_cub_cas_5               0.00         0.00                       -1     *** empty ***
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

SQL_ID: e5899a1b76253
Tran index : 4
update ta set a = 5 where a > 0

In the above example, when each three transaction is running INSERT statement, UPDATE statement is tried to run in the other transaction. In the above, UPDATE statement with "Tran index" 4 waits for the transactions 3,2,1, which are found in "Wait for lock holder", to be ended.

"SQL Text" is SQLs which are stored into the query plan cache; this is printed out as empty when this query's execution is terminated.

Each column's meaning is as following.

  • Tran index : the index of transaction
  • User name: database user's name
  • Host name: host name of CAS which running this transaction
  • Process id : client's process id
  • Program name : program name of a client
  • Query time : total execution time for the running query (unit: second)
  • Tran time : total run time for the current transaction (unit: second)
  • Wait for lock holder : the list of transactions which own the lock when the current transaction is waiting for a lock
  • SQL_ID: an ID for SQL Text
  • SQL Text : running SQL text (maximum 30 characters)

Transaction status messages, which are shown on "Tran index", are as follows.

  • ACTIVE : active state
  • RECOVERY : recovering transaction
  • COMMITTED : transaction which is already committed and will be ended soon.
  • COMMITTING : transaction which is committing
  • ABORTED : transaction which is rolled back and will be ended soon.
  • KILLED : transaction which is forcefully killed by the server.

The following shows [options] available with the cubrid tranlist utility.

-u, --user=USER

USER is DB user's ID to log-in. It only allows DBA and DBA group users.(The default: DBA)

-p, --password=PASSWORD

PASSWORD is DB user's password.

-s, --summary

This option outputs only summarized information(it omits query execution information or locking information).

$ cubrid tranlist -s demodb

Tran index          User name      Host name      Process id      Program name
-------------------------------------------------------------------------------
   1(ACTIVE)           public     test-server           1681 broker1_cub_cas_1
   2(ACTIVE)           public     test-server           1682 broker1_cub_cas_2
   3(ACTIVE)           public     test-server           1683 broker1_cub_cas_3
   4(ACTIVE)           public     test-server           1684 broker1_cub_cas_4
   5(ACTIVE)           public     test-server           1685 broker1_cub_cas_5
-------------------------------------------------------------------------------
--sort-key=NUMBER

This option outputs the ascending values sorted by the NUMBERth column. If the type of the column is the number, it is sorted by the number; if not, it is sorted by the string. If this option is omitted, the output is sorted by "Tran index".

The following is an example which outputs the sorted information by specifying the "Process id", the 4th column.

$ cubrid tranlist --sort-key=4 demodb

Tran index          User name      Host name      Process id    Program name              Query time    Tran time       Wait for lock holder      SQL_ID       SQL Text
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   1(ACTIVE)           public     test-server           1681    broker1_cub_cas_1               0.00         0.00                       -1     *** empty ***
   2(ACTIVE)           public     test-server           1682    broker1_cub_cas_2               0.00         0.00                       -1     *** empty ***
   3(ACTIVE)           public     test-server           1683    broker1_cub_cas_3               0.00         0.00                       -1     *** empty ***
   4(ACTIVE)           public     test-server           1684    broker1_cub_cas_4               1.80         1.80                  3, 1, 2     e5899a1b76253   update ta set a = 5 where a > 0
   5(ACTIVE)           public     test-server           1685    broker1_cub_cas_5               0.00         0.00                       -1     *** empty ***
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

SQL_ID: e5899a1b76253
Tran index : 4
update ta set a = 5 where a > 0
--reverse

This option outputs the reversely sorted values.

The following is an example which outputs the reversely sorted values by the "Tran index".

Tran index          User name      Host name      Process id    Program name              Query time    Tran time     Wait for lock holder      SQL_ID       SQL Text
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   5(ACTIVE)           public     test-server           1685    broker1_cub_cas_5               0.00         0.00                     -1     *** empty ***
   4(ACTIVE)           public     test-server           1684    broker1_cub_cas_4               1.80         1.80                3, 2, 1     e5899a1b76253   update ta set a = 5 where a > 0
   3(ACTIVE)           public     test-server           1683    broker1_cub_cas_3               0.00         0.00                     -1     *** empty ***
   2(ACTIVE)           public     test-server           1682    broker1_cub_cas_2               0.00         0.00                     -1     *** empty ***
   1(ACTIVE)           public     test-server           1681    broker1_cub_cas_1               0.00         0.00                     -1     *** empty ***
------------------------------------------------------------------------------------------------------------------------------------------------------------------------

SQL_ID: e5899a1b76253
Tran index : 4
update ta set a = 5 where a > 0
killtran

The cubrid killtran is used to check transactions or abort specific transaction. Only a DBA can execute this utility.

cubrid killtran [options] database_name
  • cubrid: An integrated utility for the CUBRID service and database management
  • killtran: A utility that manages transactions for a specified database
  • database_name: The name of database whose transactions are to be killed

Some [options] refer to killing specified transactions; others refer to print active transactions. If no option is specified, -d is specified by default so all transactions are displayed on the screen.

cubrid killtran demodb

Tran index      User name   Host name      Process id      Program name
-------------------------------------------------------------------------------
   1(ACTIVE)          dba      myhost             664           cub_cas
   2(ACTIVE)          dba      myhost            6700              csql
   3(ACTIVE)          dba      myhost            2188           cub_cas
   4(ACTIVE)          dba      myhost             696              csql
   5(ACTIVE)       public      myhost            6944              csql
-------------------------------------------------------------------------------

The following shows [options] available with the cubrid killtran utility.

-i, --kill-transaction-index=ID1,ID2,ID3

This option kills transactions in a specified index. Several transaction indexes can be specified by separating with comma(,). If there is an invalid transaction ID among several IDs, it is ignored.

$ cubrid killtran -i 1 demodb
Ready to kill the following transactions:

Tran index          User name      Host name      Process id      Program name
-------------------------------------------------------------------------------
   1(ACTIVE)              DBA         myhost           15771              csql
   2(ACTIVE)              DBA         myhost            2171              csql
-------------------------------------------------------------------------------
Do you wish to proceed ? (Y/N)y
Killing transaction associated with transaction index 1
Killing transaction associated with transaction index 2
--kill-user-name=ID

This option kills transactions for a specified OS user ID.

cubrid killtran --kill-user-name=os_user_id demodb
--kill- host-name=HOST

This option kills transactions of a specified client host.

cubrid killtran --kill-host-name=myhost demodb
--kill-program-name=NAME

This option kills transactions for a specified program.

cubrid killtran --kill-program-name=cub_cas demodb
--kill-sql-id=SQL_ID

This option kills transactions for a specified SQL ID.

cubrid killtran --kill-sql-id=5377225ebc75a demodb
-p PASSWORD

A value followed by the -p option is a password of the DBA, and should be entered in the prompt.

-q, --query-exec-info

The difference with the output of "cubrid tranlist" command is that there are no "User name" column and "Host name" column. See tranlist.

-d, --display

This is the default option and it displays the summary of transactions. Its output is the same as the output of "cubrid tranlist" with -s option. See tranlist -s

-f, --force

This option omits a prompt to check transactions to be stopped.

cubrid killtran -f -i 1 demodb
checkdb

The cubrid checkdb utility is used to check the consistency of a database. You can use cubrid checkdb to identify data structures that are different from indexes by checking the internal physical consistency of the data and log volumes. If the cubrid checkdb utility reveals any inconsistencies, you must try automatic repair by using the --repair option.

cubrid checkdb [options] database_name [table_name1 table_name2 ...]
  • cubrid: An integrated utility for CUBRID service and database management.
  • checkdb: A utility that checks the data consistency of a specific database.
  • database_name: The name of the database whose consistency status will be either checked or restored.
  • table_name1 table_name2: List the table names for consistency check or recovery

The following shows [options] available with the cubrid checkdb utility.

-S, --SA-mode

This option is used to access a database in standalone, which means it works without processing server; it does not have an argument. If -S is not specified, the system recognizes that a database is running in client/server mode.

cubrid checkdb -S demodb
-C, --CS-mode

This option is used to access a database in client/server mode, which means it works in client/server process respectively; it does not have an argument. If -C is not specified, the system recognize that a database is running in client/server mode by default.

cubrid checkdb -C demodb
-r, --repair

This option is used to restore an issue if a consistency error occurs in a database.

cubrid checkdb -r demodb

This option is used to check if there are errors on previous links of an index.

$ cubrid checkdb --check-prev-link demodb

This option is used to restore if there are errors on previous links of an index.

$ cubrid checkdb --repair-prev-link demodb
-i, --input-class-file=FILE

You can specify tables to check the consistency or to restore, by specifying the -i FILE option or listing the table names after a database name. Both ways can be used together. If a target is not specified, entire database will be a target of consistency check or restoration.

cubrid checkdb demodb tbl1 tbl2
cubrid checkdb -r demodb tbl1 tbl2
cubrid checkdb -r -i table_list.txt demodb tbl1 tbl2

Empty string, tab, carriage return and comma are separators among table names in the table list file specified by -i option. The following example shows the table list file; from t1 to t10, it is recognized as a table for consistency check or restoration.

t1 t2 t3,t4 t5
t6, t7 t8   t9

     t10
--check-file-tracker

Check about all pages of all files in file-trackers.

--check-heap

Check about all heap-files.

--check-catalog

Check the consistency about catalog information.

--check-btree

Check the validity about all B-tree indexes.

--check-class-name

Check the identical between the hash table of a class name and the class information(oid) brought from a heap file.

--check-btree-entries

Check the consistency of all B-tree entries.

-I, --index-name=INDEX_NAME

Check if the index specified with this option about checking table. If you use this option, there is no heap validation check. Only one table and one index are permitted when you use this option; if you don't input a table name or input two tables, an error occurs.

diagdb

You can check various pieces of internal information on the database with the cubrid diagdb utility. Information provided by cubrid diagdb is helpful in diagnosing the current status of the database or figuring out a problem.

cubrid diagdb options database_name
  • cubrid: An integrated utility for the CUBRID service and database management.
  • diagdb: A command that is used to check the current storage state of the database by Dumping the information contained in the binary file managed by CUBRID in text format. It normally executes only when the database is in a stopped state. You can check the whole database or the file table, file size, heap size, class name or disk bitmap selectively by using the provided option.
  • database_name: The name of the database whose internal information is to be diagnosed.

The following shows [options] available with the cubrid diagdb utility.

-d, --dump-type=TYPE

This option specifies the output range when you display the information of all files in the demodb database. If any option is not specified, the default value of -1 is used.

cubrid diagdb -d 1 demodb

The utility has 9 types of -d options as follows:

Type Description
-1 Displays all database information.
1 Displays file table information.
2 Displays file capacity information.
3 Displays heap capacity information.
4 Displays index capacity information.
5 Displays class name information.
6 Displays disk bitmap information.
7 Displays catalog information.
8 Displays log information.
9 Displays heap information.
paramdump

The cubrid paramdump utility outputs parameter information used in the server/client process.

cubrid paramdump [options] database_name
  • cubrid: An integrated utility for the CUBRID service and database management
  • paramdump: A utility that outputs parameter information used in the server/client process
  • database_name: The name of the database in which parameter information is to be displayed.

The following shows [options] available with the cubrid paramdump utility.

-o, --output-file=FILE

The -o option is used to store information of the parameters used in the server/client process of the database into a specified file. The file is created in the current directory. If the -o option is not specified, the message is displayed on a console screen.

cubrid paramdump -o db_output demodb
-b, --both

The -b option is used to display parameter information used in server/client process on a console screen. If the -b option is not specified, only server-side information is displayed.

cubrid paramdump -b demodb
-S, --SA-mode

This option displays parameter information of the server process in standalone mode.

cubrid paramdump -S demodb
-C, --CS-mode

This option displays parameter information of the server process in client/server mode.

cubrid paramdump -C demodb
HA Commands

cubrid changemode utility prints or changes the HA mode.

cubrid applyinfo utility prints the information of applied transaction logs in the HA environment.

For more details, see Registering HA to cubrid service.

Locale Commands

cubrid genlocale utility compiles the locale information to use. This utility is executed in the make_locale.sh script ( .bat for Windows).

cubrid dumplocale utility dumps the compiled binary locale (CUBRID locale library) file as a human-readable format on the console. It is better to save the output as a file by output redirection.

cubrid synccolldb utility checks if the collations between database and locale library are consistent or not, and synchronize them.

For more detailed usage, see Locale Setting.

Timezone Commands

cubrid gen_tz utility compiles the IANA timezone information included in tzdata folder into a C source code. This utility is executed in the make_tz.sh script ( .bat for Windows).

cubrid dump_tz utility dumps the compiled CUBRID timezone library file as a human-readable format on the console. It is better to save the output as a file by output redirection.

System Parameters

This chapter provides information about configuring system parameters that can affect the system performance. System parameters determine overall performance and operation of the system. This chapter explains how to use configuration files for database server and broker as well as a description of each parameter. For CUBRID Manager server configuration, see CUBRID Manager Manual.

This chapter covers the following topics:

  • Configuring the database server
  • Configuring the broker
Configuring the Database Server
Scope of Database Server Configuration

CUBRID consists of the database server, the broker and the CUBRID Manager. Each component has its configuration file. The system parameter configuration file for the database server is cubrid.conf located in the $CUBRID/conf directory. System parameters configured in cubrid.conf affect overall performance and operation of the database system. Therefore, it is very important to understand the database server configuration.

The CUBRID database server has a client/server architecture. To be more specific, it is divided into a database server process linked to the server library and the broker process linked to the client library. The server process manages the database storage structure and provides concurrency and transaction functionalities. The client process prepares for query execution and manages object/schema.

System parameters for the database server, which can be set in the cubrid.conf file, are classified into a client parameter, a server parameter and a client/server parameter according to the range to which they are applied. A client parameter is only applied to client processes such as the broker. A server parameter affects the behaviors of the server processes. A client/server parameter must be applied to both server and client.

Note

Location of cubrid.conf File and How It Works

The cubrid.conf file ls localted on the $CUBRID/conf directory. For setting by database, it divides into a section in the cubrid.conf file.

Changing Database Server Configuration
Editing the Configuration File

You can add/delete parameters or change parameter values by manually editing the system parameter configuration file (cubrid.conf) in the $CUBRID/conf directory.

The following parameter syntax rules are applied when configuring parameters in the configuration file:

  • Parameter names are not case-sensitive.
  • The name and value of a parameter must be entered in the same line.
  • An equal sign (=) can be to configure the parameter value. Spaces are allowed before and after the equal sign.
  • If the value of a parameter is a character string, enter the character string without quotes. However, use quotes if spaces are included in the character string.
Using SQL Statements

You can configure a parameter value by using SQL statements in the CSQL Interpreter or CUBRID Manager's Query Editor. Note that you cannot change every parameter. For updatable parameters, see cubrid.conf Configuration File and Default Parameters.

SET SYSTEM PARAMETERS 'parameter_name=value [{; name=value}...]'

parameter_name is the name of a client parameter whose value is editable. In this syntax, value is the value of the given parameter. You can change multiple parameter values by separating them with semicolons (;). You must take caution when you apply changes of parameter values.

The following example shows how to retrieve the result of an index scan in OID order and configure the number of queries to be stored in the history of the CSQL Interpreter to 70.

SET SYSTEM PARAMETERS 'index_scan_in_oid_order=1; csql_history_num=70';

DEFAULT for value will reset the parameter to its default value with an exception of call_stack_dump_activation_list parameter.

SET SYSTEM PARAMETERS 'lock_timeout=DEFAULT';
Using Session Commands of the CSQL Interpreter

You can configure system parameter values by using session commands (;SET) in the CSQL Interpreter. Note that you cannot change every parameter. For updatable parameters, see cubrid.conf Configuration File and Default Parameters.

The following example shows how to configure the block_ddl_statement parameter to 1 so that execution of DDL statements is not allowed.

csql> ;se block_ddl_statement=1
=== Set Param Input ===
block_ddl_statement=1
cubrid.conf Configuration File and Default Parameters

CUBRID consists of the database server, the broker and the CUBRID Manager. The name of the configuration file for each component is as follows. These files are all located in the $CUBRID/conf directory.

  • Database server configuration file: cubrid.conf
  • Broker configuration file: cubrid_broker.conf
  • CUBRID Manager server configuration file: cm.conf

cubrid.conf is a configuration file that sets system parameters for the CUBRID database server and determines overall performance and operation of the database system. In the cubrid.conf file, some important parameters needed for system installation are provided, having their default values.

Database Server System Parameters

The following are database server system parameters that can be used in the cubrid.conf configuration file. On the following table, "Applied" column's "client parameter" means that they are applied to CAS, CSQL, cubrid utilities. Its "server parameter" means that they are applied to the DB server (cub_server process). For the scope of client and server parameters, see Scope of Database Server Configuration.

You can change the parameters that are capable of changing dynamically the setting value through the SET SYSTEM PARAMETERS statement or a session command of the CSQL Interpreter, ;set while running the DB. If you are a DBA, you can change parameters regardless of the applied classification. However, if you are not a DBA, you can only change "session" parameters. (on the below table, a parameter of which "session" item's value is O.)

On the below table, if "Applied" is "server parameter", that parameter affects to cub_server process; If "client parameter", that parameter affects to CAS, CSQL or "cubrid" utilities which run on client/server mode (--CS-mode). "Client/server parameter" affects to all of cub_server, CAS, CSQL and "cubrid" utilities.

"Dynamic Change" and "Session or not" are marked on the below table. The affected range of the parameter which "Dynamic Change" is "available" depends on "Applied" and "Session" items.

  • If "Dynamic Change" is "available" and "Applied" is "server parameter", that parameter's changed value is applied to DB server. Then applications use the changed value of the parameter until the DB server is restarted.
  • If "Dynamic Change" is "available" and "Applied" is "client parameter", this belongs to the "session" parameter and that parameter's changed value is applied only to that DB session. In other words, the changed value is only applied to the application which requested to change that value. For example, if block_ddl_statement parameter's value is changed into yes, then only the application requested to change that parameter cannot use DDL statements.
  • If "Dynamic Change" is "available", "Applied" is "client parameter" and;
    • this belongs to the "session" parameter, that parameter's changed value is applied only to that DB session. In other words, the changed value is only applied to the application requested to change that value. For example, if add_column_update_hard_default parameter's value is changed into yes, then only the application requested to change that parameter lets the newly added column with NOT NULL constraint have hard default value.
    • this does not belong to the "session" parameter, the values of "client" side and "server" side are changed. For example, error_log_level parameter is applied to each of "server" side and "client" side; if this value is changed from "ERROR" into "WARNING", this is applied only to "server" (cub_server process) and "client" (CAS or CSQL) which requested to change this value. Other "clients" keeps the value of "ERROR".

Note

If you want to change the value of a parameter permanently, restart all of DB server and broker after changing configuration values of cubrid.conf.

Category Parameter Name Applied Session Type Default Value Dynamic Change
Connection-Related Parameters cubrid_port_id client parameter   int 1,523  
check_peer_alive client/server parameter O string both available
db_hosts client parameter O string NULL available
max_clients server parameter   int 100  
tcp_keepalive client/server parameter   bool yes  
Memory-Related Parameters data_buffer_size server parameter   byte 32,768 * db_page_size  
index_scan_oid_buffer_size server parameter   byte 4 * db_page_size  
max_agg_hash_size server parameter   byte 2,097,152(2M)  
sort_buffer_size server parameter   byte 128 * db_page_size  
temp_file_memory_size_in_pages server parameter   int 4  
thread_stacksize server parameter   byte 1,048,576  
Disk-Related Parameters db_volume_size server parameter   byte 512M  
dont_reuse_heap_file server parameter   bool no  
generic_vol_prealloc_size server parameter   byte 50M  
log_volume_size server parameter   byte 512M  
temp_file_max_size_in_pages server parameter   int -1  
temp_volume_path server parameter   string NULL  
unfill_factor server parameter   float 0.1  
volume_extension_path server parameter   string NULL  
Error Message-Related Parameters call_stack_dump_activation_list client/server parameter   string DEFAULT DBA only
call_stack_dump_deactivation_list client/server parameter   string NULL DBA only
call_stack_dump_on_error client/server parameter   bool no DBA only
error_log client/server parameter   string cub_client.err, cub_server.err  
error_log_level client/server parameter   string SYNTAX DBA only
error_log_warning client/server parameter   bool no DBA only
error_log_size client/server parameter   int 8,000,000 DBA only
Concurrency/Lock-Related Parameters deadlock_detection_interval_in_secs server parameter   float 1.0 DBA only
isolation_level client parameter O int 4 available
lock_escalation server parameter   int 100,000  
lock_timeout client parameter O msec -1 available
rollback_on_lock_escalation server parameter   bool no DBA only
Logging-Related Parameters adaptive_flush_control server parameter   bool yes DBA only
background_archiving server parameter   bool yes DBA only
checkpoint_every_size server parameter   byte 10,000 * log_page_size  
checkpoint_interval server parameter   msec 6min DBA only
checkpoint_sleep_msecs server parameter   msec 1 DBA only
force_remove_log_archives server parameter   bool yes DBA only
log_buffer_size server parameter   byte 128 * log_page_size  
log_max_archives server parameter   int INT_MAX DBA only
log_trace_flush_time server parameter   msec 0 DBA only
max_flush_size_per_second server parameter   byte 10,000 * db_page_size DBA only
remove_log_archive_interval_in_secs server parameter   sec 0 DBA only
sync_on_flush_size server parameter   byte 200 * db_page_size DBA only
Transaction Processing-Related Parameters async_commit server parameter   bool no  
group_commit_interval_in_msecs server parameter   msec 0 DBA only
Statement/Type-Related Parameters add_column_update_hard_default client/server parameter O bool no available
alter_table_change_type_strict client/server parameter O bool no available
ansi_quotes client parameter   bool yes  
block_ddl_statement client parameter O bool no available
block_nowhere_statement client parameter O bool no available
compat_numeric_division_scale client/server parameter O bool no available
default_week_format client/server parameter O int 0 available
group_concat_max_len server parameter O byte 1,024 DBA only
intl_check_input_string client parameter O bool no available
intl_collation client parameter O string   available
intl_date_lang client parameter O string   available
intl_number_lang client parameter O string   available
no_backslash_escapes client parameter   bool yes  
only_full_group_by client parameter O bool no available
oracle_style_empty_string client parameter   bool no  
pipes_as_concat client parameter   bool yes  
plus_as_concat client parameter   bool yes  
require_like_escape_character client parameter   bool no  
return_null_on_function_errors client/server parameter O bool no available
string_max_size_bytes client/server parameter O byte 1,048,576 available
unicode_input_normalization client parameter O bool no available
unicode_output_normalization client parameter O bool no available
update_use_attribute_references client parameter O bool no available
Timezone Parameter server_timezone server parameter   string OS timezone available
timezone client/server parameter O string the value of server_timezone available
tz_leap_second_support server parameter   bool no available
Query Plan Cache-Related Parameters max_plan_cache_entries client/server parameter   int 1,000  
max_filter_pred_cache_entries client/server parameter   int 1,000  
Utility-Related Parameters backup_volume_max_size_bytes server parameter   byte 0  
communication_histogram client parameter O bool no available
compactdb_page_reclaim_only server parameter   int 0  
csql_history_num client parameter O int 50 available
HA-Related Parameters ha_mode server parameter   string off  
Other Parameters access_ip_control server parameter   bool no  
access_ip_control_file server parameter   string    
agg_hash_respect_order client parameter O bool yes available
auto_restart_server server parameter O bool yes DBA only
index_scan_in_oid_order client parameter O bool no available
index_unfill_factor server parameter   float 0.05  
java_stored_procedure server parameter   bool no  
multi_range_optimization_limit server parameter O int 100 DBA only
optimizer_enable_merge_join client parameter O bool no available
pthread_scope_process server parameter   bool yes  
server server parameter   string    
service server parameter   string    
session_state_timeout server parameter   sec 21,600  
sort_limit_max_count client parameter O int 1,000 available
sql_trace_slow server parameter O msec -1 DBA only
sql_trace_execution_plan server parameter O bool no DBA only
use_orderby_sort_limit server parameter O bool yes DBA only
vacuum_prefetch_log_mode server parameter   int 1 DBA only
vacuum_prefetch_log_buffer_size server parameter   int 3200 * log_page_size DBA only
data_buffer_neighbor_flush_pages server parameter   int 8 DBA only
data_buffer_neighbor_flush_nondirty server parameter   bool no DBA only
  • log_page_size: A log volume page size specified by --log-page-size option when you are creating database. Default: 16KB. log page related parameter's value is rounded off by page unit. For example, the value of checkpoint_every_size is divided by 16KB and its decimal point is dropped, then it is multiplied by 16KB.
  • log_page_size: A DB volume page size specified by --db-page-size option when you are creating database. Default: 16KB. DB page related parameter's value is rounded off by page unit. For example, the value of data_buffer_size is divided by 16KB and its decimal point is dropped, then it is multiplied by 16KB.
Section by Parameter

Parameters specified in cubrid.conf have the following four sections:

  • Used when the CUBRID service starts: [service] section
  • Applied commonly to all databases: [common] section
  • Applied individually to each database: [@<database>] section
  • Used only when the cubrid utilities are run with stand-alone mode(--SA-mode): [standalone] section

Where <database> is the name of the database to which each parameter applies. If a parameter configured in [common] is the same as the one configured in [@<database>], the one configured in [@<database>] is applied.

.....
[common]
.....
sort_buffer_size=2M
.....
[standalone]

sort_buffer_size=256M
.....

Configuration defined in [standalone] is used only when cubrid utilities started with "cubrid" are run with stand-alone mode. For example, on the above configuration, if DB is started with --CS-mode(default)(cubrid databases start db_name), "sort_buffer_size=2M" is applied. However, if DB is stopped and "cubrid loaddb --SA-mode" is executed, "sort_buffer_size=256M" is applied. If you run "cubrid loaddb --SA-mode", bigger size of sort buffer will be required during index creation; therefore, increasing sort buffer size will be better for the performance of "loaddb" execution.

Default Parameters

cubrid.conf, a default database configuration file created during the CUBRID installation, includes some default database server parameters that must be changed. You can change the value of a parameter that is not included as a default parameter by manually adding or editing one.

The following is the content of the cubrid.conf file.

# Copyright (C) 2008 Search Solution Corporation. All rights reserved by Search Solution.
#
# $Id$
#
# cubrid.conf#

# For complete information on parameters, see the CUBRID
# Database Administration Guide chapter on System Parameters

# Service section - a section for 'cubrid service' command
[service]

# The list of processes to be started automatically by 'cubrid service start' command
# Any combinations are available with server, broker and manager.
service=server,broker,manager

# The list of database servers in all by 'cubrid service start' command.
# This property is effective only when the above 'service' property contains 'server' keyword.
#server=demodb,testdb

# Common section - properties for all databases
# This section will be applied before other database specific sections.
[common]

# Read the manual for detailed description of system parameters
# Manual > System Configuration > Database Server Configuration > Default Parameters

# Size of data buffer are using K, M, G, T unit
data_buffer_size=512M

# Size of log buffer are using K, M, G, T unit
log_buffer_size=4M

# Size of sort buffer are using K, M, G, T unit
# The sort buffer should be allocated per thread.
# So, the max size of the sort buffer is sort_buffer_size * max_clients.
sort_buffer_size=2M

# The maximum number of concurrent client connections the server will accept.
# This value also means the total # of concurrent transactions.
max_clients=100

# TCP port id for the CUBRID programs (used by all clients).
cubrid_port_id=1523

If you want to set data_buffer_size as 128M and max_clients as 10 only on testdb, set as follows.

[service]

service=server,broker,manager

[common]

data_buffer_size=512M
log_buffer_size=4M
sort_buffer_size=2M
max_clients=100

# TCP port id for the CUBRID programs (used by all clients).
cubrid_port_id=1523

[@testdb]
data_buffer_size=128M
max_clients=10
Timezone Parameter

The following are the parameters related to timezone. The type and the value range for each parameter are as follows:

Parameter Name Type Default Min Max
server_timezone string OS timezone    
timezone string server_timezone    
tz_leap_second_support bool no    
  • timezone

    Specifies a timezone for a session. The default is a value of server_timezone. This value can be specified by a timezone offset (e.g. +01:00, +02) or a timezone region name (e.g. Asia/Seoul). This value can be changed during operating database.

  • server_timezone

    Specifies a timezone for a server. The default is a OS timezone. To apply the changed value, database should be restarted. The timezone of operating system is read depending on the operating system and information found in operating system configuration files:

    • on Windows, the API tzset() function and tzname[0] variable are used to retrieve an Windows style timezone name. This name is translated into IANA/CUBRID style name using the CUBRID mapping data (the mapping file is %CUBRID%\timezones\tzdata\windowsZones.xml).
    • on Linux, CUBRID attempts to read and parse the file "/etc/sysconfig/clock". If this file is not available, then the value of link "/etc/localtime" is read and used.
    • on AIX, the value of "TZ" operating system environment variable is used.

    On all operating systems, if the server_timezone is not specified, and the value for timezone from operating system cannot be read, then "Asia/Seoul" zone is used as server timezone.

  • tz_leap_second_support

    Specifies to support a leap second or not as yes or no. The default is no.

    A leap second is a one-second adjustment that is occasionally applied to Coordinated Universal Time (UTC) in order to keep its time of day close to the mean solar time.

    To apply the changed value, database should be restarted.

Other Parameters

The following are other parameters. The type and value range for each parameter are as follows:

Parameter Name Type Default Min Max
access_ip_control bool no    
access_ip_control_file string      
agg_hash_respect_order bool yes    
auto_restart_server bool yes    
index_scan_in_oid_order bool no    
index_unfill_factor float 0.05 0 0.5
java_stored_procedure bool no    
multi_range_optimization_limit int 100 0 10,000
optimizer_enable_merge_join bool no    
pthread_scope_process bool yes    
server string      
service string      
session_state_timeout sec 21,600 (6 hours) 60(1 minute) 31,536,000 (1 year)
sort_limit_max_count int 1000 0 INT_MAX
sql_trace_slow msec -1(inf) 0 86,400,000 (24 hours)
sql_trace_execution_plan bool no    
use_orderby_sort_limit bool yes    
vacuum_prefetch_log_mode int 1 0 1
vacuum_prefetch_log_buffer_size int 50M 25M INT_MAX
data_buffer_neighbor_flush_pages int 8 0 32
data_buffer_neighbor_flush_nondirty bool no    

access_ip_control

access_ip_control is a parameter to configure whether to use feature limiting the IP addresses that allow server access. The default value is no. For details, see Limiting Database Server Access.

access_ip_control_file

access_ip_control_file is a parameter to configure the file name in which the list of IP addresses allowed by servers is stored. If access_ip_control value is set to yes, database server allows the list of IP addresses only stored in the file specified by this parameter. For details, see Limiting Database Server Access.

agg_hash_respect_order

agg_hash_respect_order is a parameter to configure whether the groups in an aggregate function will be returned ordered or not. The default is yes. As a reference, see max_agg_hash_size.

If all the groups (keys and accumulators) can fit into hash memory, then "agg_hash_respect_order=no" will skip sorting them before writing to output, so it is fair to assume that the order cannot be guaranteed in this case. However, when overflows occur, then a sort step must be performed and you will get the results in-order even with "agg_hash_respect_order=no".

auto_restart_server

auto_restart_server is a parameter to configure whether to restart the process when it stops due to fatal errors being occurred in database server process. If auto_restart_server value is set to yes, the server process automatically restarts when it has stopped due to errors; it does not restart in case it stops by following normal process (by using STOP command).

index_scan_in_oid_order

index_scan_in_oid_order is a parameter to configure the result data to be retrieved in OID order after the index scan. If the parameter is set to no, which is the default value, results are retrieved in data order; if it is set to yes, they are retrieved in OID order.

index_unfill_factor

If there is no free space because index pages are full when the INSERT or UPDATE operation is executed after the first index is created, the split of index page nodes occurs. This substantially affects the performance by increasing the operation time. index_unfill_factor is a parameter to configure the percent of free space defined for each index page node when an index is created. The index_unfill_factor value is applied only when an index is created for the first time. The percent of free space defined for the page is not maintained dynamically. Its value ranges between 0 and 0.5. The default value is 0.05.

If an index is created without any free space for the index page node (index_unfill_factor is set to 0), the split of index page nodes occurs every time an additional insertion is made. This may degrade the performance.

If the value of index_unfill_factor is large, a large amount of free space is available when an index is created. Therefore, better performance can be obtained because the split of index nodes does not occur for a relatively long period of time until the free space for the nodes is filled after the first index is created.

If this value is small, the amount of free space for the nodes is small when an index is created. Therefore, it is likely that the index nodes are spilt by INSERT or UPDATE because free space for the index nodes is filled in a short period of time.

java_stored_procedure

java_stored_procedure is a parameter to configure whether to use Java stored procedures by running the Java Virtual Machine (JVM). If the parameter is set to no, which is the default value, JVM is not executed; if it is set to yes, JVM is executed so you can use Java stored procedures. Therefore, configure the parameter to yes if you plan to use Java stored procedures.

multi_range_optimization_limit

If the number of rows specified by the LIMIT clause in the query, which has multiple ranges (col IN (?, ?, ... ,?)) and is available to use an index, is within the number specified in the multi_range_optimization_limit parameter, the optimization for the way of index sorting will be performed. The default value is 100.

For example, if a value for this parameter is set to 50, LIMIT 10 means that it is within the value specified by this parameter, so that the values that meet the conditions will be sorted to produce the result. If LIMIT is 60, it means that it exceeds the parameter configuration value, so that it gets and sorts out all values that meet the conditions.

Depending on the setting value, the differences are made between collecting the result with on-the-fly sorting of the intermediate values and sorting the result values after collecting them, and the bigger value could make more unfavorable performance.

optimizer_enable_merge_join

optimizer_enable_merge_join is a parameter to specify whether to include sort merge join plan as a candidate of query plans or not. The default is no. Regarding sort merge join, see Using SQL Hint.

pthread_scope_process

pthread_scope_process is a parameter to configure the contention scope of threads. It only applies to AIX systems. If the parameter is set to no, the contention scope becomes PTHREAD_SCOPE_SYSTEM; if it is set to yes, it becomes PTHREAD_SCOPE_PROCESS. The default value is yes.

server

server is a parameter used to register the name of database server process which will run automatically when CUBRID server starts.

service

service is a parameter to configure process that starts automatically when the CUBRID service starts. There are four types of processes: server, broker, manager, and heartbeat. Three processes are usually registered as in service=server,broker,manager.

  • If the parameter is set to server, the database process specified by the @server parameter gets started.
  • If the parameter is set to broker, the broker process gets started.
  • If the parameter is set to manager, the manager process gets started.
  • If the parameter is set to heartbeat, the HA-related processes get started.

session_state_timeout

session_state_timeout is a parameter used to define how long the CUBRID session data will be kept. The session data will be deleted when the driver terminates the connection or the session time expires. The session time will expire after the specified time if a client terminates abnormally.

Custom variables defined by SET and PREPARE statements can be deleted by DROP / DEALLOCATE statements before session timeout.

The default value is 21,600 seconds(6 hours), and this parameter's unit is second.

sort_limit_max_count

Regarding SORT-LIMIT optimization which can be applied when top-N rows are sorted by "ORDER BY ... LIMIT N" statement, this parameter specifies the LIMIT count to limit applying this optimization. When the value of N is smaller than a value of sort_limit_max_count, SORT-LIMIT optimization is applied. The default is 1000, the minimum is 0(which means that this optimization is disabled), and the maximum is INT_MAX.

For more details, see SORT-LIMIT optimization.

sql_trace_slow

sql_trace_slow is a parameter to configure the execution time of a query which will be judged as a long time execution. You can set a unit as ms, s, min or h, which stands for milliseconds, seconds, minutes or hours respectively. If you omit the unit, milliseconds(ms) will be applied. The default value is -1 and the maximum value is 86,400,000 msec (24 hour). -1 means that the infinite time, so any queries will not be judged as a long duration query. For details, see the below sql_trace_execution_plan.

Note

The system parameter sql_trace_slow judges the query execution time based on the server, but the broker parameter MAX_QUERY_TIMEOUT judges the query execution time based on the broker.

sql_trace_execution_plan

sql_trace_execution_plan is a parameter to configure if the query plan of the long running query is written to the log or not. The default value is no.

If it is set to yes, a long running SQL, a query plan and the output of cubrid statdump command are written to the server error log file(located on $CUBRID/log/server directory) and CAS log file(located on $CUBRID/log/broker/sql_log directory) .

If it is set to no, only a long running SQL is written to the server error log file and CAS log file, and this SQL is displayed when you execute cubrid statdump command.

For example, if you want to write the execution plan of the slow query to the log file, and specify the query which executes more than 5 seconds as the slow query, then configure the value of the sql_trace_slow parameter as 5000(ms) and configure the value of the sql_trace_execution_plan parameter as yes.

But, on the server error log file, the related information is written only when the value of error_log_level is NOTIFICATION.

use_orderby_sort_limit

use_orderby_sort_limit is a parameter to configure whether to keep the intermediate result of sorting and merging process in the statement including the ORDER BY ... LIMIT row_count clause as many as row_count. If it is set to yes, you can decrease unnecessary comparing and merging processes because as many as intermediate results will be kept as the value of row_count. The default value is yes.

vacuum_prefetch_log_mode

vacuum_prefetch_log_mode is a parameter to configure the prefetch mode of log pages on behalf of vacuum.

In mode 0, the vacuum master thread prefetch the required log pages in a shared buffer. In mode 1 (default), each vacuum worker prefetches the required log pages in its own buffer. Mode 0 also requires that vacuum_prefetch_log_buffer_size system parameter is configured, in mode 0 this parameter is ignored and each vacuum worker prefetches an entire vacuum log block (default 32 log pages).

vacuum_prefetch_log_buffer_size

vacuum_prefetch_log_buffer_size is a parameter to configure the log prefetch buffer size of vacuum (it is used only if vacuum_prefetch_log_mode is set to 0).

data_buffer_neighbor_flush_pages

data_buffer_neighbor_flush_pages is a parameter to control the number of neighbour pages to be flushed with background flush (victim candidates flushing). When is less or equal to 1, the neighbour flush feature is considered deactivated.

data_buffer_neighbor_flush_nondirty

data_buffer_neighbor_flush_nondirty is a parameter to control the flushing of non-dirty neighbour pages. When victim candidates pages are flushed, and neighbour flush is activated (data_buffer_neighbor_flush_pages is greater than 1), than single non-dirty pages which completes a chain of neighbour (dirty) pages are also flushed.
Broker Configuration
cubrid_broker.conf Configuration File and Default Parameters
Broker System Parameters

The following table shows the broker parameters available in the broker configuration file (cubrid_broker.conf). For details, see Common Parameters and Parameter by Broker. You can temporarily change the parameter of which configuration values can be dynamically changed by using the broker_changer utility. To apply configuration values even after restarting all brokers with cubrid broker restart, you should change the values in the cubrid_broker.conf file.

Category Use Parameter Name Type Default Value Dynamic Changes
Common Parameters Access ACCESS_CONTROL bool no  
ACCESS_CONTROL_FILE string    
Logging ADMIN_LOG_FILE string log/broker/cubrid_broker.log  
Broker server (cub_broker) MASTER_SHM_ID int 30,001  
Parameter by Broker Access ACCESS_LIST string    
ACCESS_MODE string RW available
BROKER_PORT int 30,000(max : 65,535)  
CONNECT_ORDER string SEQ available
ENABLE_MONITOR_HANG string OFF  
KEEP_CONNECTION string AUTO available
MAX_NUM_DELAYED_HOSTS_LOOKUP int -1  
PREFERRED_HOSTS string   available
RECONNECT_TIME sec 600 available
REPLICA_ONLY string OFF  
Broker App. Server(CAS) APPL_SERVER_MAX_SIZE MB Windows 32bit: 40, Windows 64bit: 80, Linux: 0(max: 2,097,151) available
APPL_SERVER_MAX_SIZE_HARD_LIMIT MB 1,024 available
APPL_SERVER_PORT int BROKER_PORT+1  
APPL_SERVER_SHM_ID int 30,000  
AUTO_ADD_APPL_SERVER string ON  
MAX_NUM_APPL_SERVER int 40  
MIN_NUM_APPL_SERVER int 5  
TIME_TO_KILL sec 120 available
Transaction & Query CCI_DEFAULT_AUTOCOMMIT string ON  
LONG_QUERY_TIME sec 60(max: 86,400) available
LONG_TRANSACTION_TIME sec 60(max: 86,400) available
MAX_PREPARED_STMT_COUNT int 2,000(min: 1) available
MAX_QUERY_TIMEOUT sec 0(max: 86,400) available
SESSION_TIMEOUT sec 300 available
STATEMENT_POOLING string ON available
TRIGGER_ACTION string ON available
Logging ACCESS_LOG string OFF available
ACCESS_LOG_DIR string log/broker  
ACCESS_LOG_MAX_SIZE KB 10M(max: 2G) available
ERROR_LOG_DIR string log/broker/error_log available
LOG_DIR string log/broker/sql_log available
SLOW_LOG string ON available
SLOW_LOG_DIR string log/broker/sql_log available
SQL_LOG string ON available
SQL_LOG_MAX_SIZE KB 10,000 available
Etc MAX_STRING_LENGTH int -1  
SERVICE string ON  
SOURCE_ENV string cubrid.env  
Default Parameters

The cubrid_broker.conf file, the default broker configuration file created when installing CUBRID, includes some parameters that must be modified by default. If you want to modify the values of parameters that are not included in the configuration file by default, you can add or modify one yourself.

The following is the content of the cubrid_broker.conf file provided by default.

[broker]
MASTER_SHM_ID           =30001
ADMIN_LOG_FILE          =log/broker/cubrid_broker.log

[%query_editor]
SERVICE                 =ON
BROKER_PORT             =30000
MIN_NUM_APPL_SERVER     =5
MAX_NUM_APPL_SERVER     =40
APPL_SERVER_SHM_ID      =30000
LOG_DIR                 =log/broker/sql_log
ERROR_LOG_DIR           =log/broker/error_log
SQL_LOG                 =ON
TIME_TO_KILL            =120
SESSION_TIMEOUT         =300
KEEP_CONNECTION         =AUTO

[%BROKER1]
SERVICE                 =ON
BROKER_PORT             =33000
MIN_NUM_APPL_SERVER     =5
MAX_NUM_APPL_SERVER     =40
APPL_SERVER_SHM_ID      =33000
LOG_DIR                 =log/broker/sql_log
ERROR_LOG_DIR           =log/broker/error_log
SQL_LOG                 =ON
TIME_TO_KILL            =120
SESSION_TIMEOUT         =300
KEEP_CONNECTION         =AUTO
Common Parameters

The following are parameters commonly applied to entire brokers; it is written under [broker] section.

Access

ACCESS_CONTROL

ACCESS_CONTROL is a parameter used to limit applications which are trying to connect a broker. The default value is OFF. For details, see Limiting Broker Access.

ACCESS_CONTROL_FILE

ACCESS_CONTROL_FILE is a parameter to configure the name of a file in which a database name, database user ID, and the list of IPs are stored. List of IPs can be written up to the maximum of 256 lines per <db_name>:<db_user> in a broker. For details, see Limiting Broker Access.
Logging

ADMIN_LOG_FILE

ADMIN_LOG_FILE is a parameter to configure the file in which time of running CUBRID broker is stored. The default value is a log/broker/cubrid_broker.log file.
Broker Server(cub_broker)

MASTER_SHM_ID

MASTER_SHM_ID is a parameter used to specify the identifier of shared memory which is used to manage the CUBRID broker. Its value must be unique in the system. The default value is 30001.
Parameter by Broker

The following describes parameters to configure the environment variables of brokers; each parameter is located under [%broker_name]. The maximum length of broker_name is 63 characters in English.

Access

ACCESS_LIST

ACCESS_LIST is a parameter to configure the name of a file where the list of IP addresses of an application which allows access to the CUBRID broker is stored. To allow access by IP addresses access 210.192.33.* and 210.194.34.*, store them to a file (ip_lists.txt) and then assign the file name with the value of this parameter.

ACCESS_MODE

ACCESS_MODE is a parameter to configure default mode of the broker. The default value is RW. For details, see cubrid_broker.conf.

BROKER_PORT

BROKER_PORT is a parameter to configure the port number of the broker; the value must be unique and smaller than 65,535. The default port value of query_editor' broker is 30,000 and the port value of the broker1 is 33,000.

CONNECT_ORDER

CONNECT_ORDER is a parameter to specify whether a CAS tries to connect to one of hosts in the order or randomly in $CUBRID_DATABASES/databases.txt, when a CAS decides the order of connecting to a host. The default is SEQ; a CAS tries to connect to a host in the order. if this value is RANDOM, a CAS tries to connect to a host randomly. If PREFERRED_HOSTS parameter is specified, firstly a CAS tries to connect to one of hosts specified in PREFERRED_HOSTS, then uses db-host values in $CUBRID_DATABASES/databases.txt only when the connection is failed.

ENABLE_MONITOR_HANG

ENABLE_MONITOR_HANG is a parameter to configure whether to block the access from the application to the broker or not, when more than a certain ratio of CASes on that broker are hung. If the ENABLE_MONITOR_HANG parameter value is ON, blocking feature is processed. The default value is OFF. If its OFF, don't do the behavior.

The broker process judges the CAS as hung if the hanging status of the CAS keeps more than one minute, then block the access from applications to that broker; it brings the behavior which the applications try to access to the alternative hosts(altHosts) configured by the connection URL.

KEEP_CONNECTION

KEEP_CONNECTION is a parameter to configure the way of connection between CAS and application clients; it is set to one of the following: ON or AUTO. If this value is ON, it is connected in connection unit. If it is AUTO and the number of servers is more than that of clients, transaction unit is used; in the reverse case, connection unit is used. The default value is AUTO.

MAX_NUM_DELAYED_HOSTS_LOOKUP

When almost all DB servers have the delay of replication in the HA environment where multiple DB servers on db-host of databases.txt are specified, check if the connection is established or not until the number of delayed replication servers; the number is specified in MAX_NUM_DELAYED_HOSTS_LOOKUP (whether the delay of replication in the DB server is judged only with the standby hosts; it is determined by the setting of ref:ha_delay_limit <ha_delay_limit>). See MAX_NUM_DELAYED_HOSTS_LOOKUP for further information.

PREFERRED_HOSTS

PREFERRED_HOSTS is a parameter to specify the order of a host to which a CAS tries to connect in a first priority. If the connection is failed after trying connection in the order specified in PREFERRED_HOSTS, a CAS tries to connect to the one of hosts specified in $CUBRID_DATABASES/databases.txt. The default value is NULL. For details, see cubrid_broker.conf.

RECONNECT_TIME

If the time specified by RECONNECT_TIME is elapsed in a certain status, CAS will try to reconnect to the other DB server. The default of this parameter is 600s(10min). You can set a unit as ms, s, min or h, which stands for milliseconds, seconds, minutes or hours respectively. If you omit the unit, s will be applied.

a certain status which CAS tries to reconnect is as follows.

  • when CAS is connected to not a DB server in PREFERRED_HOSTS, but the DB server of db-host in databases.txt.
  • when CAS with "ACCESS_MODE=RO"(Read Only) is connected to not the standby DB server, but the active DB server.
  • when CAS is connected to the DB server of which replication is delayed.

When RECONNECT_TIME is 0, CAS does not try to reconnect.

REPLICA_ONLY

If a value of REPLICA_ONLY is ON, CAS is connected only to replicas. The default is OFF. Even though the value of REPLICA_ONLY is ON, when a value of ACCESS_MODE is RW, it is possible to write directly to the replica DB. However, the data to be written directly to the replica DB are not replicated.

Note

Please note that replication mismatch occurs when you write the data directly to the replica DB.

Broker App. Server(CAS)

APPL_SERVER_MAX_SIZE

APPL_SERVER_MAX_SIZE is a parameter to configure the maximum size of the process memory usage handled by CAS. You can set a unit as B, K, M or G, which stands for bytes, kilobytes(KB), megabytes(MB) or gigabytes(GB) respectively. If you omit the unit, M will be applied.

Specifying this parameter makes transactions terminate (commit or rollback) only when it is executed by a user. In contrast to this, specifying APPL_SERVER_MAX_SIZE_HARD_LIMIT makes transactions forcibly terminate (rollback) and restart CAS.

Note that the default values of Windows and Linux are different from each other.

For 32-bit Windows, the default value is 40 MB; for 64-bit Windows, it is 80 MB. The maximum value is the same on Windows and Linux as 2,097,151 MB. When current process size exceeds the value of APPL_SERVER_MAX_SIZE, broker restarts the corresponding CAS.

For Linux, the default value of APPL_SERVER_MAX_SIZE is 0; CAS restarts in the following conditions.

  • APPL_SERVER_MAX_SIZE is zero or negative: At the point when current process size becomes twice as large as initial memory
  • APPL_SERVER_MAX_SIZE is positive: At the point when it exceeds the value specified in APPL_SERVER_MAX_SIZE

Note

Be careful not to make the value too small because application servers may restart frequently and unexpectedly. In general, the value of APPL_SERVER_MAX_SIZE_HARD_LIMIT is greater than that of APPL_SERVER_MAX_SIZE. For details, see description of APPL_SERVER_MAX_SIZE_HARD_LIMIT.

APPL_SERVER_MAX_SIZE_HARD_LIMIT

APPL_SERVER_MAX_SIZE_HARD_LIMIT is a parameter to configure the maximum size of process memory usage handled by CAS. You can set a unit as B, K, M or G, which stands for bytes, kilobytes(KB), megabytes(MB) or gigabytes(GB) respectively. If you omit the unit, M will be applied. The default value is 1,024 (MB), and the maximum value is 2,097,151 (MB).

Specifying this parameter makes transactions being processed forcibly terminate (rollback) and restart CAS. In contrast to this, specifying APPL_SERVER_MAX_SIZE makes transactions terminate only when it is executed by a user.

Note

Be careful not to make the value too small because application servers may restart frequently and unexpectedly. When restarting CAS, APPL_SERVER_MAX_SIZE is specified to wait for normal termination of transactions although memory usage increases; APPL_SERVER_MAX_SIZE_HARD_LIMIT is specified to forcibly terminate transactions if memory usage exceeds the maximum value allowed. Therefore, in general, the value of APPL_SERVER_MAX_SIZE_HARD_LIMIT is greater than that of APPL_SERVER_MAX_SIZE.

APPL_SERVER_PORT

APPL_SERVER_PORT is a parameter to configure the connection port of CAS that communicates with application clients; it is used only in Windows. In Linux, the application clients and CAS use the UNIX domain socket for communication; therefore, APPL_SERVER_PORT is not used. The default value is determined by adding plus 1 to the BROKER_PORT parameter value. The number of ports used is the same as the number of CAS, starting from the specified port's number plus 1. For example, when the value of BROKER_PORT is 30,000 and the APPL_SERVER_PORT parameter value has been configured, and if the MIN_NUM_APPL_SERVER value is 5, five CASes uses the ports numbering between 30,001 and 30,005, respectively. The maximum number of CAS specified in the MAX_NUM_APPL_SERVER parameter in cubrid_broker_conf; therefore, the maximum number of connection ports is also determined by the value of MAX_NUM_APPL_SERVER parameter.

On the Windows system, if a firewall exists between an application and a CUBRID broker, the communication port specified in BROKER_PORT and APPL_SERVER_PORT must be opened.

Note

For the CUBRID_TMP environment variable that specifies the UNIX domain socket file path of cub_master and cub_broker processes, see Configuring Environment Variables.

APPL_SERVER_SHM_ID

APPL_SERVER_SHM_ID is a parameter to configure the ID of shared memory used by CAS; the value must be unique within system. The default value is the same as the port value of the broker.

AUTO_ADD_APPL_SERVER

AUTO_ADD_APPL_SERVER is a parameter to configure whether CAS increase automatically to the value specified in MAX_NUM_APPL_SERVER in case of needed; the value will be either ON or OFF (default: ON).

MAX_NUM_APPL_SERVER

MAX_NUM_APPL_SERVER is a parameter to configure the maximum number of simultaneous connections allowed. The default value is 40.

MIN_NUM_APPL_SERVER

MIN_NUM_APPL_SERVER is a parameter to configure the minimum number of CAS even if any request to connect the broker has not been made. The default value is 5.

TIME_TO_KILL

TIME_TO_KILL is a parameter to configure the time to remove CAS in idle state among CAS added dynamically. You can set a unit as ms, s, min or h, which stands for milliseconds, seconds, minutes or hours respectively. If you omit the unit, s will be applied. The default value is 120 (seconds).

An idle state is one in which the server is not involved in any jobs. If this state continues exceeding the value specified in TIME_TO_KILL, CAS is removed.

The value configured in this parameter affects only CAS added dynamically, so it applies only when the AUTO_ADD_APPL_SERVER parameter is configured to ON. Note that times to add or remove CAS will be increased more if the TIME_TO_KILL value is so small.

Transaction & Query

CCI_DEFAULT_AUTOCOMMIT

CCI_DEFAULT_AUTOCOMMIT is a parameter to configure whether to make application implemented in CCI interface or CCI-based interface such as PHP, OLE DB, Perl, Python, and Ruby commit automatically. The default value is ON. This parameter does not affect applications implemented in JDBC.

If the CCI_DEFAULT_AUTOCOMMIT parameter value is OFF, the broker application server (CAS) process is occupied until the transaction is terminated. Therefore, it is recommended to execute commit after completing fetch when executing the SELECT statement.

Note

The CCI_DEFAULT_AUTOCOMMIT parameter has been supported from 2008 R4.0, and the default value is OFF for the version. Therefore, if you use CUBRID 2008 R4.1 or later versions and want to keep the configuration OFF, you should manually change it to OFF to avoid auto-commit of unexpected transaction.

Warning

In ODBC driver, the setting of CCI_DEFAULT_AUTOCOMMIT is ignored and worked as ON; therefore, you should set the autocommit on or off in the program directly.

LONG_QUERY_TIME

LONG_QUERY_TIME is a parameter to configure execution time of query which is evaluated as long-duration query. You can set a unit as ms, s, min or h, which stands for milliseconds, seconds, minutes or hours respectively. If you omit the unit, milliseconds(ms) will be applied. The default value is 60 (seconds) and the maximum value is 86,400(1 day). When you run a query and this query's running time takes more than the specified time, a value of LONG-Q, which is printed out from "cubrid broker status" command, is increased 1; this SQL is written to SLOW log file ($CUBRID/log/broker/sql_log/*.slow.log) of CAS. See SLOW_LOG.

This value can be valued in milliseconds with a decimal separator. For example, the value can be configured into 0.5 to configure 500 msec.

Note that if a parameter value is configured to 0, a long-duration query is not evaluated.

LONG_TRANSACTION_TIME

LONG_TRANSACTION_TIME is a parameter to configure execution time of query which is evaluated as long-duration transaction. The default value is 60 (seconds) and the maximum value is 86,400(1 day).

This value can be valued in milliseconds with a decimal separator. For example, the value can be configured into 0.5 to configure 500 msec.

Note that if a parameter value is configured to 0, a long-duration transaction is not evaluated.

MAX_PREPARED_STMT_COUNT

MAX_PREPARED_STMT_COUNT is a parameter used to limit the number of prepared statements by user (application) access. The default value is 2,000 and the minimum value is 1. The problem in which prepared statement exceeding allowed memory is mistakenly generated by system can be prohibited by making users specify the parameter value.

Note

When you want to change the value of MAX_PREPARED_STMT_COUNT dynamically by broker_changer command, this can be changed only when this is bigger than the existing value; this cannot be changed when this is smaller than the existing value.

MAX_QUERY_TIMEOUT

MAX_ QUERY_TIMEOUT is a parameter to configure timeout value of query execution. When time exceeds a value specified in this parameter after starting query execution, the query being executed stops and rolls back. You can set a unit as ms, s, min or h, which stands for milliseconds, seconds, minutes or hours respectively. If you omit the unit, milliseconds(ms) will be applied. The default value is 0 (seconds) and it means infinite waiting. The value range is available from 0 to 86,400 seconds(one day).

The smallest value (except 0) between the MAX_QUERY_TIMEOUT value and query timeout value of an application is applied if query timeout is configured in an application.

Note

See the cci_connect_with_url() and cci_set_query_timeout() functions to configure query timeout of CCI applications. For configuring query timeout of JDBC applications, see the setQueryTimeout method.

SESSION_TIMEOUT

SESSION_TIMEOUT is a parameter to configure timeout value for the session of the broker. You can set a unit as ms, s, min or h, which stands for milliseconds, seconds, minutes or hours respectively. If you omit the unit, milliseconds(ms) will be applied. The default value is 300 (seconds).

If there is no response to the job request for the specified time period, session will be terminated. If a value exceeds the value specified in this parameter without any action taken after starting transaction, the connections are terminated.

STATEMENT_POOLING

STATEMENT_POOLING is a parameter to configure whether to use statement pool feature. The default value is ON.

CUBRID closes all handles of prepared statement in the corresponding client sessions when transaction commit or rollback is made. If the value of STATEMENT_POOLING is set to ON, the handles are reusable because they are maintained in the pool. Therefore, in an environment where libraries, such as general applications reusing prepared statement or DBCP where statement pooling is implemented is applied, the default configuration (ON) should be maintained.

If the prepared statement is executed after transaction commit or termination while STATEMENT_POOLING is set to OFF, the following message will be displayed.

Caused by: cubrid.jdbc.driver.CUBRIDException: Attempt to access a closed Statement.

TRIGGER_ACTION

Turn on or off of the trigger's action about the broker which specified this parameter. Specify ON or OFF as a value; The default is ON.
Logging

ACCESS_LOG

ACCESS_LOG is a parameter to configure whether to store the access log of the broker. The default value is OFF. The name of the access log file for the broker is broker_name.access and the file is stored under $CUBRID/log/broker directory.

ACCESS_LOG_DIR

ACCESS_LOG_DIR specifies the directory for broker access logging files(ACCESS_LOB) to be created. The default is log/broker.

ACCESS_LOG_MAX_SIZE

ACCESS_LOG_MAX_SIZE specifies the maximum size of broker access logging files(ACCESS_LOG); if a broker access logging file is bigger than a specified size, this file is backed up into the name of broker_name.access.YYYYMMDDHHMISS, then logging messages are written to the new file(broker_name.access). The default is 10M and the maximum is 2G. It can be dynamically changed during operating a broker.

ERROR_LOG_DIR

ERROR_LOG_DIR is a parameter to configure default directory in which error logs about broker is stored. The default value is log/broker/error_log. The log file name for the broker error is broker_ name_id.err.

LOG_DIR

LOG_DIR is a parameter to configure the directory where SQL logs are stored. The default value is log/broker/sql_log. The file name of the SQL logs is broker_name_id.sql.log.

SLOW_LOG

SLOW_LOG is a parameter to configure whether to log. The default value is ON. If the value is ON, long transaction query which exceeds the time specified in LONG_QUERY_TIME or query where an error occurred is stored in the SLOW SQL log file. The name of file created is broker_name_id.slow.log and it is located under SLOW_LOG_DIR.

SLOW_LOG_DIR

SLOW_LOG_DIR is a parameter to configure the location of directory where the log file is generated. The default value is log/broker/sql_log.

SQL_LOG

SQL_LOG is a parameter to configure whether to leave logs for SQL statements processed by CAS when CAS handles requests from a client. The default value is ON. When this parameter is configured to ON, all logs are stored. The log file name becomes broker_name_id.sql.log. The file is created in the log/broker/sql_log directory under the installation directory. The parameter values are as follows:

  • OFF : Does not leave any logs.
  • ERROR : Stores logs for queries which occur an error. only queries where an error occurs.
  • NOTICE : Stores logs for the long-duration execution queries which exceeds the configured time/transaction, or leaves logs for queries which occur an error.
  • TIMEOUT : Stores logs for the long-duration execution queries which exceeds the configured time/transaction.
  • ON / ALL : Stores all logs.

SQL_LOG_MAX_SIZE

SQL_LOG_MAX_SIZE is a parameter to configure the maximum size of the SQL log file. You can set a unit as B, K, M or G, which stands for bytes, kilobytes(KB) or megabytes(MB) or gigabytes(GB) respectively. If you omit the unit, M will be applied. The default value is 10,000* (KB).

  • If the size of the SQL log file, which is created when the SQL_LOG parameter is configured to ON, reaches to the size configured by the parameter, broker_name_id.sql.log.bak is created.
  • If the size of the SLOW SQL log file, which is created when the SLOW_LOG parameter is configured to ON, reaches to the size configured by the parameter, broker_name_id.slow.log.bak is created.
Etc

MAX_STRING_LENGTH

MAX_STRING_LENGTH is a parameter to configure the maximum string length for BIT, VARBIT, CHAR and VARCHAR data types. If the value is -1, which is the default value, the length defined in the database is used. If the value is 100, the value acts like 100 being applied even when a certain attribute is defined as VARCHAR(1000).

SERVICE

SERVICE is a parameter to configure whether to run the broker. It can be either ON or OFF. The default value is ON. The broker can run only when this value is configured to ON.

SOURCE_ENV

SOURCE_ENV is a parameter used to determine the file where the operating system variable for each broker is configured. The extension of the file must be env. All parameters specified in cubrid.conf can also be configured by environment variables. For example, the lock_timeout parameter in cubrid.conf can also be configured by the CUBRID_LOCK_TIMEOUT environment variable. As another example, to block execution of DDL statements on broker1, you can configure CUBRID_BLOCK_DDL_STATEMENT to 1 in the file specified by SOURCE_ENV.

An environment variable, if exists, has priority over cubrid.conf. The default value is cubrid.env.

HA Configuration

Regarding HA configuration, see Environment Configuration.

SystemTap

Overview

SystemTap is a tool that can be used to dynamically monitor and track the process of running. CUBRID supports SystemTap; therefore, it is possible to find the cause of a performance bottleneck.

The basic idea of ​​SystemTap script is that you can specify the name of the event and grant a handler there. Handler is script statements that specify the action to be performed each time an event occurs.

To monitor the performance of CUBRID using SystemTap, you need to install SystemTap. After installing SystemTap, you can write and run a SystemTap script which is like a C language. With this script, you can monitor the performance of the System.

SystemTap supports only on Linux.

See http://sourceware.org/systemtap/index.html for further information and installation.

Installing SystemTap
Checking Installation
  1. Check if you have group accounts, stapusr and stapdev in /etc/group file. If they don't exist, SystemTap may not be installed.

  2. Add CUBRID user account when you install CUBRID into stapusr and stapdev group accounts. Here let's assume the CUBRID user account as "cubrid".

    $ vi /etc/group
    
    stapusr:x:156:cubrid
    stapdev:x:158:cubrid
    
  3. To check if SystemTap is runable, simply run the below command.

    $ stap -ve 'probe begin { log("hello world") exit() }'
    
Version

To execute SystemTap scripts in CUBRID, you should use SystemTap 2.2 or higher.

The below is an example to install SystemTap in CentOS 6.3. Checking version and installing SystemTap can be different among Linux distributors.

  1. Check the current version of the installed SystemTap.

    $ sudo yum list|grep  systemtap
    systemtap.x86_64                       1.7-5.el6_3.1                 @update
    systemtap-client.x86_64                1.7-5.el6_3.1                 @update
    systemtap-devel.x86_64                 1.7-5.el6_3.1                 @update
    systemtap-runtime.x86_64               1.7-5.el6_3.1                 @update
    systemtap-grapher.x86_64               1.7-5.el6_3.1                 update
    systemtap-initscript.x86_64            1.7-5.el6_3.1                 update
    systemtap-sdt-devel.i686               1.7-5.el6_3.1                 update
    systemtap-sdt-devel.x86_64             1.7-5.el6_3.1                 update
    systemtap-server.x86_64                1.7-5.el6_3.1                 update
    systemtap-testsuite.x86_64             1.7-5.el6_3.1                 update
    
  2. If the lower version of SystemTap than 2.2 version is installed, remove it.

    $ sudo yum remove systemtap-runtime
    $ sudo yum remove systemtap-devel
    $ sudo yum remove systemtap
    
  3. Installl the RPM distributed package of SystemTap 2.2 or higher. You can find the RPM distributed package in http://rpmfind.net/linux/rpm2html/.

    $ sudo rpm -ivh systemtap-devel-2.3-3.el6.x86_64.rpm
    $ sudo rpm -ivh systemtap-runtime-2.3-3.el6.x86_64.rpm
    $ sudo rpm -ivh systemtap-client-2.3-3.el6.x86_64.rpm
    $ sudo rpm -ivh systemtap-2.3-3.el6.x86_64.rpm
    
Using SystemTap in CUBRID
Building CUBRID source

SystemTap can be used only on Linux.

To use SystemTap by building CUBRID source, "--enable-systemtap" option should be specified when executing "./configure".

This option is already included in the release build, a user not building the CUBRID source but installing CUBRID with the installation package can also use SystemTap script.

The below is an example of building the CUBRID source.

./autogen.sh
./configure -prefix=$CUBRID --enable-systemtap --enable-64bit
make
make install
Running SystemTap script

Examples of SystemTap scripts in CUBRID are located in $CUBRID/share/systemtap directory.

The below is an example of running buffer_access.stp file.

cd $CUBRID/share/systemtap/scripts
stap -k buffer_access.stp -o result.txt
Printing Results

When you run a certain script, it displays the requested result to the console by the script code. With "-o filename" option, it writes the requested result to the filename.

The below is the result of the above example.

Page buffer hit count: 172
Page buffer miss count: 172
Miss ratio: 50
CUBRID markers

A very useful feature of SystemTap is the possibility of placing markers in the user source code (CUBRID code) and writing probes that triggers when these markers are reached. Below is the list of CUBRID markers and their meaning.

Connection markers

We might be interested in gathering information helpful for an analysis related to connection activity (number of connections, duration of individual connections, average duration of a connection, maximum number of connections achieved etc.) during a period of time. In order for such monitoring scripts to be written, we must provide at least two helpful markers: connection-start and connection-end.

conn_start(connection_id, user)
This marker is triggered after the query execution has begun.
Parameters:
  • query_string -- string representing the query to be executed.
  • query_id -- Query identifier.
  • connection_id -- an integer containing the connection ID.
  • user -- The username used by this connection.
conn_end(connection_id, user)

This marker is triggered when the query execution process on the server has ended.

Parameters:
  • connection_id -- an integer containing the connection ID.
  • user -- The username used by this connection.
Query markers

Markers for query execution related events can prove very useful in monitor tasks, although they do not contain global information related to the entire system. At least two markers are essential: those corresponding to the start of the execution of a query and the end of the execution.

query_exec_start(query_string, query_id, connection_id, user)

This marker is triggered after the query execution has begun on the server.

Parameters:
  • query_string -- string representing the query to be executed
  • query_id -- Query identifier
  • connection_id -- Connection ID
  • user -- The username used by this connection
query_exec_end(query_string, query_id, connection_id, user, status)

This marker is triggered when the query execution process on the server has ended.

Parameters:
  • query_string -- string representing the query to be executed
  • query_id -- Query identifier
  • connection_id -- Connection ID
  • user -- The username used by this connection
  • status -- The status returned by the query execution (Success, Error)
Object operation markers

Operations involving the storage engine are critical and probing updates in a table at object level can greatly help monitor database activity. Markers will be triggered for each object inserted/updated/deleted, which may bring performance drawbacks on both the monitoring scripts and the server.

obj_insert_start(table)

This marker is triggered before an object is inserted.

Parameters:table -- Target table of the operation
obj_insert_end(table, status)

This marker is triggered after an object has been inserted.

Parameters:
  • table -- Target table of the operation
  • status -- Value showing whether the operation ended with success or not
obj_update_start(table)

This marker is triggered before an object is updated.

Parameters:table -- Target table of the operation
obj_update_end(table, status)

This marker is triggered after an object has been updated

Parameters:
  • table -- Target table of the operation
  • status -- Value showing whether the operation ended with success or not
obj_deleted_start(table)

This marker is triggered before an object is deleted.

Parameters:table -- Target table of the operation
obj_delete_end(table, status)

This marker is triggered after an object has been deleted.

Parameters:
  • table -- Target table of the operation
  • status -- Value showing whether the operation ended with success or not
obj_read_start(table)

This marker is triggered before an object is read.

Parameters:table -- Target table of the operation
obj_read_end(table, status)

This marker is triggered after an object has been read.

Parameters:
  • table -- Target table of the operation
  • status -- Value showing whether the operation ended with success or not
Index operation markers

The object operation markers presented above are table-related, but below are index-related markers.

Indexes and their misuse can be the cause of many problems in a system and the possibility of monitoring them can be very helpful. The proposed markers are similar to those used for tables, since indexes support the same operations.

idx_insert_start(classname, index_name)

This marker is triggered before an insertion in the B-Tree.

Parameters:
  • classname -- Name of the class having the target index
  • index_name -- Target index of the operation
idx_insert_end(classname, index_name, status)

This marker is triggered after an insertion in the B-Tree.

Parameters:
  • classname -- Name of the class having the target index
  • index_name -- Target index_name of the operation
  • status -- Value showing whether the operation ended with success or not
idx_update_start(classname, index_name)

This marker is triggered before an update in the B-Tree.

Parameters:
  • classname -- Name of the class having the target index
  • index_name -- Target index_name of the operation
idx_update_end(classname, index_name, status)

This marker is triggered after an update in the B-Tree.

Parameters:
  • classname -- Name of the class having the target index
  • index_name -- Target index_name of the operation
  • status -- Value showing whether the operation ended with success or not
idx_delete_start(classname, index_name)

This marker is triggered before a deletion in the B-Tree.

Parameters:
  • classname -- Name of the class having the target index
  • index_name -- Target index_name of the operation
idx_delete_end(classname, index_name, status)

This marker is triggered after a deletion in the B-Tree.

Parameters:
  • classname -- Name of the class having the target index
  • index_name -- Target index_name of the operation
  • status -- Value showing whether the operation ended with success or not
idx_read_start(classname, index_name)

This marker is triggered before an indexed object is read.

Parameters:
  • classname -- Name of the class having the target index
  • index_name -- Target index_name of the operation
idx_read_end(classname, index_name, status)

This marker is triggered after an indexed object is read.

Parameters:
  • classname -- Name of the class having the target index
  • index_name -- Target index_name of the operation
  • status -- Value showing whether the operation ended with success or not
Locking markers

Markers that involve locking events are perhaps the most important for global monitoring tasks. The locking system has a deep impact on the server performance and a comprehensive analysis on lock waiting times and count, number of deadlocks and aborted transactions is very useful in finding problems.

lock_acquire_start(OID, table, type)

This marker is triggered before a lock is requested.

Parameters:
  • OID -- Target object of the lock request.
  • table -- Table holding the object
  • type -- Lock type (X_LOCK, S_LOCK etc.)
lock_acquire_end(OID, table, type, status)

This marker is triggered after a lock request has been completed.

Parameters:
  • OID -- Target object of the lock request.
  • table -- Table holding the object
  • type -- Lock type (X_LOCK, S_LOCK etc.)
  • status -- Value showing whether the request has been granted or not.
lock_release_start(OID, table, type)

This marker is triggered before a lock is released.

Parameters:
  • OID -- Target object of the lock request.
  • table -- Table holding the object
  • type -- Lock type (X_LOCK, S_LOCK etc.)
lock_release_end(OID, table, type, status)

This marker is triggered after a lock release operation has been completed.

Parameters:
  • OID -- Target object of the lock request
  • table -- Table holding the object
  • type -- Lock type(X_LOCK, S_LOCK etc)
  • status -- Value showing whether the operation ended with success or not
Transaction markers

Another interesting measure in server monitoring is transaction activity. A simple example: the number of transactions aborted is closely related to the number of deadlocks occurred, a very important performance indicator. Another straightforward use of such markers is the availability of a simple method of gathering system performance statistics such as TPS by using a simple SystemTap script.

tran_commit(tran_id)

This marker is triggered after a transaction completes successfully.

Parameters:tran_id -- Transaction identifier.
tran_abort(tran_id, status)

This marker is triggered after a transaction has been aborted.

Parameters:
  • tran_id -- Transaction identifier.
  • status -- Exit status.
tran_start(tran_id)

This marker is triggered after a transaction is started.

Parameters:tran_id -- Transaction identifier.
tran_deadlock()

This marker is triggered when a deadlock has been detected.

I/O markers

I/O access is the main bottleneck of a RDBMS and we should provide markers that allow the monitoring of I/O performance. The markers should be placed in a manner that will make it possible for user scripts to measure I/O page access time and aggregate various and complex statistics based on this measure.

pgbuf_hit()

This marker is triggered when a requested page was found in the page buffer and there is no need to retrieve it from disk.

pgbuf_miss()

This marker is triggered when a requested page was not found in the page buffer and it must be retrieved from disk.

io_write_start(query_id)

This marker is triggered when a the process of writing a page onto disk has begun.

Parameters:query_id -- Query identifier
io_write_end(query_id, size, status)

This marker is triggered when a the process of writing a page onto disk has ended.

Parameters:
  • query_id -- Query identifier
  • size -- number of bytes written
  • status -- Value showing whether the operation ended successfully or not
io_read_start(query_id)

This marker is triggered when a the process of reading a page from disk has begun.

Parameters:query_id -- Query identifier
io_read_end(query_id, size, status)

This marker is triggered when a the process of reading a page from disk has ended.

Parameters:
  • query_id -- Query identifier
  • size -- number of bytes read
  • status -- Value showing whether the operation ended successfully or not
Other markers
sort_start()

This marker is triggered when a sort operation is started.

sort_end(nr_rows, status)

This marker is triggered when a sort operation has been completed.

Parameters:
  • nr_rows -- number of rows sorted
  • status -- Value showing whether the operation ended successfully or not

Troubleshooting

Checking SQL Log
SQL log of CAS

When a specific error occurs, generally you can check SQL logs of broker application server(CAS)

One SQL log file is generated per each CAS; it is hard to find an SQL log in which an error occurred because SQL log files are many when CAS processes are many. However, SQL log file name includes CAS ID in the end part, you can find easily if you know the CAS ID in which an error occurred.

Note

SQL log file name in a CAS is <broker_name>_<app_server_num>.sql.log(see Broker Logs); <app_server_num> is CAS ID.

Function getting CAS information

cci_get_cas_info() function or cubrid.jdbc.driver.CUBRIDConnection.toString() method in JDBC) prints out the information including the broker host and CAS ID in which the query is executed when the query is run; with this information, you can find an SQL log file of that CAS easily.

<host>:<port>,<cas id>,<cas process id>
e.g. 127.0.0.1:33000,1,12916
Application log

If you specify the connection URL for printing out the log in the application, you can check the CAS ID which brought an error when an error occurs in the specific query. The following are examples that an application log is written when an error occurs.

JDBC application log

Syntax: syntax error, unexpected IdName [CAS INFO - localhost:33000,1,30560],[SESSION-16],[URL-jdbc:cubrid:localhost:33000:demodb::********:?logFile=driver_1.log&logSlowQueries=true&slowQueryThresholdMillis=5].

CCI application log

Syntax: syntax error, unexpected IdName [CAS INFO - 127.0.0.1:33000, 1, 30560].
Slow query

When a slow query occurs, you should find the reason of a slow query by an application log and an SQL log of CAS.

To find where the cause exists when slow query occurs(in the application-broker section? or in the broker-DB section?), you should check application log or SQL log of CAS because CUBRID is composed of 3-tiers; application-broker-DB server.

There is a slow query in the application log but that is not printed as slow query in the SQL log of CAS; then there will be a cause to make the speed low in the application-broker section.

Some examples are as below.

  • Check if there is a low speed of the network between application and broker.
  • Check if there is a case that CAS was restarted by watching the broker log(exists in $CUBRID/log/broker directory). If it is revealed as CASes are not enough, you should enlarge the number of CASes; to do so, the value of MAX_NUM_APPL_SERVER should be enlarged properly. Also the value of max_clients should be enlarged if needed.

If application log and CAS SQL log show the slow query log together and there is almost no gab between the slow query times of application log and the CAS SQL log, the cause which the query was slow will exist between the broker and DB server. For example, the query execution in the DB server was slow.

There are examples of each application log when a slow query occurs.

JDBC application log

2013-05-09 16:25:08.831|INFO|SLOW QUERY
[CAS INFO]
localhost:33000, 1, 12916
[TIME]
START: 2013-05-09 16:25:08.775, ELAPSED: 52
[SQL]
SELECT * from db_class a, db_class b

CCI application log

2013-05-10 18:11:23.023 [TID:14346] [DEBUG][CONHANDLE - 0002][CAS INFO - 127.0.0.1:33000, 1, 12916] [SLOW QUERY - ELAPSED : 45] [SQL - select * from db_class a, db_class b]

Slow query information in an application and in a broker is stored in each file when the setting is as following.

  • The slow query information in application is stored in application log file when the value of logSlowQueries property in the connection URL is set to yes and the value of slowQueryThresholdMillis is set; it is stored to the application logfile specified with the logFile property (see cci_connect_with_url() and Configuration Connection).
  • The slow query information in broker is stored in the $CUBRID/log/broker/sql_log directory when SLOW_LOG of Broker Configuration is set to ON and LONG_QUERY_TIME is set.
Server Error Log

You can get various information from the server error log by setting error_log_level parameter in cubrid.conf. The default of error_log_level is ERROR. If you want to get NOTIFICATION messages, set the value of error_log_level as NOTIFICATION. For how to set this parameter, see Error Message-Related Parameters.

Detecting Overflow Keys or Overflow Pages

When overflow keys or overflow pages occur, NOTIFICATION messages are written to the server error log. Through this message, users can detect DB performance became slow because of overflow keys or overflow pages. If possible, overflow keys or overflow pages should not appear. That is, it is better not to use the index on the big size column, and not to define the record size largely.

Time: 06/14/13 19:23:40.485 - NOTIFICATION *** file ../../src/storage/btree.c, line 10617 CODE = -1125 Tran = 1, CLIENT = testhost:csql(24670), EID = 6
Created the overflow key file. INDEX idx(B+tree: 0|131|540) ON CLASS hoo(CLASS_OID: 0|522|2). key: 'z ..... '(OID: 0|530|1).
...........

Time: 06/14/13 19:23:41.614 - NOTIFICATION *** file ../../src/storage/btree.c, line 8785 CODE = -1126 Tran = 1, CLIENT = testhost:csql(24670), EID = 9
Created a new overflow page. INDEX i_foo(B+tree: 0|149|580) ON CLASS foo(CLASS_OID: 0|522|3). key: 1(OID: 0|572|578).
...........

Time: 06/14/13 19:23:48.636 - NOTIFICATION *** file ../../src/storage/btree.c, line 5562 CODE = -1127 Tran = 1, CLIENT = testhost:csql(24670), EID = 42
Deleted an empty overflow page. INDEX i_foo(B+tree: 0|149|580) ON CLASS foo(CLASS_OID: 0|522|3). key: 1(OID: 0|572|192).
Detecting log recovery time

When DB sever is started or backuped volume is restored, you can check the duration of the log recovery by printing out the NOTIFICATION messages, the starting time and the ending time of the log recovery, to the server error log or an error log file of restoredb. In these messages, the number of logs and the number of log pages to redo are written together.

Time: 06/14/13 21:29:04.059 - NOTIFICATION *** file ../../src/transaction/log_recovery.c, line 748 CODE = -1128 Tran = -1, EID = 1
Log recovery is started. The number of log records to be applied: 96916. Log page: 343 ~ 5104.
.....
Time: 06/14/13 21:29:05.170 - NOTIFICATION *** file ../../src/transaction/log_recovery.c, line 843 CODE = -1129 Tran = -1, EID = 4
Log recovery is finished.
Detecting a Deadlock

If a deadlock occurs when error_log_level in cubrid.conf is NOTIFICATION, locks related information is written to the server error log.

demodb_20160202_1811.err

      ...

Your transaction (index 1, public@testhost|csql(21541)) timed out waiting on    X_LOCK lock on instance 0|650|3 of class t because of deadlock. You are waiting for user(s) public@testhost|csql(21529) to finish.

      ...
Detecting the change of HA status

Detecting the change of HA status can be checked in the cub_master process log. This log file is stored in the $CUBRID/log directory as named in <host_name>.cub_master.err.

Detecting HA split-brain

When there is an abnormal status that two or more nodes are in charge of master role in HA environment, we call it "split-brain".

To resolve the split-brain status, one of two is dead for itself; cub_master log file of this node includes the following information.

Time: 05/31/13 17:38:29.138 - ERROR *** file ../../src/executables/master_heartbeat.c, line 714 ERROR CODE = -988 Tran = -1, EID = 19
Node event: More than one master detected and local processes and cub_master will be terminated.

Time: 05/31/13 17:38:32.337 - ERROR *** file ../../src/executables/master_heartbeat.c, line 4493 ERROR CODE = -988 Tran = -1, EID = 20
Node event:HA Node Information
================================================================================
 * group_id : hagrp host_name : testhost02 state : unknown
--------------------------------------------------------------------------------
name priority state score missed heartbeat
--------------------------------------------------------------------------------
testhost03 3 slave 3 0
testhost02 2 master 2 0
testhost01 1 master -32767 0
================================================================================

Above example is the information to print out into the cub_master log when testhost02 server detects split-brain status and it is dead for itself.

Detecting Fail-over, Fail-back

If fail-over or fail-back occurs, a node changes its role.

The following is the log file of the cub_master that is changed as slave node after fail-back or master node after fail-over; it includes the following node information.

Time: 06/04/13 15:23:28.056 - ERROR *** file ../../src/executables/master_heartbeat.c, line 957 ERROR CODE = -988 Tran = -1, EID = 25
Node event: Failover completed.

Time: 06/04/13 15:23:28.056 - ERROR *** file ../../src/executables/master_heartbeat.c, line 4484 ERROR CODE = -988 Tran = -1, EID = 26
Node event: HA Node Information
================================================================================
 * group_id : hagrp host_name : testhost02 state : master
--------------------------------------------------------------------------------
name priority state score missed heartbeat
--------------------------------------------------------------------------------
testhost03 3 slave 3 0
testhost02 2 to-be-master -4094 0
testhost01 1 unknown 32767 0
================================================================================

Above example is an information which is printed out to the cub_master log; it is the process that the 'testhost02' host changes the role from slave to master because of the fail-over.

Failure on HA Start

The following is examples that replicated DB volumes' restoration is impossible without user intervention.

  • When logs to copy in copylogdb process are deleted from a source node.
  • When archive logs to apply from active server are already deleted.
  • When a restoration of server is failed.

When replicated DB volumes' restoration is impossible like above cases, "cubrid heartbeat start" command is failed; for each case, you should fix it properly.

Typical Unrestorable Failure

If server process is the cause of the cases that automatic restoration of DB volumes without user intervention is impossible, that cases will be very various, so descriptions for those are omitted. The following describes the error messages when copylogdb or applylogdb process is the cause.

  • When copylogdb process is the cause
Cause Error message
A log not copied yet is already deleted from the target node. log writer: failed to get log page(s) starting from page id 80.
Detected as the other DB's log. Log "/home1/cubrid/DB/tdb01_cdbs037.cub/tdb01_lgat" does not belong to the given database.
  • When applylogdb process is the cause
Cause Error message
Archive logs including logs to apply in replication are already deleted.

Internal error: unable to find log page 81 in log archives.

Internal error: logical log page 81 may be corrupted.

Different between db_ha_apply_info catalog time and DB creation time in the current replication logs. That is, it's not the previous log to be being applied. HA generic: Failed to initialize db_ha_apply_info.
Diffent database locale. Locale initialization: Active log file(/home1/cubrid/DB/tdb01_cdbs037.cub/tdb01_lgat) charset is not valid (iso88591), expecting utf8.
How to fix when a Failure on HA start
Status How to fix
When the source node, the cause of failure, is in master status. Rebuild replication.
When the source node, the cause of failure, is in slave status. Initialize replicated logs and db_ha_apply_info catalog then restart.

CUBRID HA

High Availability (HA) refers to a feature to provide uninterrupted service in the event of hardware, software, or network failure. This ability is a critical element in the network computing area where services should be provided 24/7. An HA system consists of more than two server systems, each of which provides uninterrupted services, even when a failure occurs in one of them.

CUBRID HA is an implementation of High Availability. CUBRID HA ensures database synchronization among multiple servers when providing service. When an unexpected failure occurs in the system which is operating services, this feature minimizes the service down time by allowing the other system to carry out the service automatically.

CUBRID HA is in a shared-nothing structure. To synchronize data from an active server to a standby server, CUBRID HA executes the following two steps.

  1. Transaction log multiplexing: Replicates the transaction logs created by an active server to another node in real time.
  2. Transaction log reflection: Analyzes replicated transaction logs in real time and reflects the data to a standby server.

CUBRID HA executes the steps described above in order to always maintain data synchronization between an active server and a standby server. For this reason, if an active server is not working properly because of a failure occurring in the master node that had been providing service, the standby server of the slave node provides service instead of the failed server. CUBRID HA monitors the status of the system and CUBRID in real time. It uses heartbeat messages to execute an automatic failover when a failure occurs.

_images/image13.png

CUBRID HA Concept

Nodes and Groups

A node is a logical unit that makes up CUBRID HA. It can become one of the following nodes according to its status: master node, slave node, or replica node.

  • Master node : A node to be replicated. It provides all services which are read, write, etc. using an active server.
  • Slave node : A node that has the same information as a master node. Changes made in the master node are automatically reflected to the slave node. It provides the read service using a standby server, and a failover will occur when the master node fails.
  • Replica node : A node that has the same information as a master node. Changes made in the master node are automatically reflected to the replica node. It provides the read service using a standby server, and no failover will occur when the master node fails.

The CUBRID HA group consists of the nodes described above. You can configure the members of this group by using the ha_node_list and ha_replica_list in the cubrid_ha.conf file. Nodes in a group have the same information. They exchange status checking messages periodically and a failover will occurs when the master node fails.

A node includes the master process (cub_master), the database server process (cub_server), the replication log copy process (copylogdb), the replication log reflection process (applylogdb), etc.

_images/image14.png
Processes

A CUBRID HA node consists of one master process (cub_master), one or more database server processes (cub_server), one or more replication log copy processes (copylogdb), and one or more replication log reflection processes (applylogdb). When a database is configured, database server processes, replication log copy processes, and replication log reflection processes will start. Because copy and reflection of a replication log are executed by different processes, the delay in replicating reflections does not affect the transaction that is being executed.

  • Master process (cub_master) : Exchanges heartbeat messages to control the internal management processes of CUBRID HA.
  • Database server process (cub_server) : Provides services such as read or write to the user. For details, see Servers.
  • Replication log copy process (copylogdb) : Copies all transaction logs in a group. When the replication log copy process requests a transaction log from the database server process of the target node, the database server process returns the corresponding log. The location of copied transaction logs can be configured in the ha_copy_log_base of cubrid_ha.conf. Use applyinfo utility to verify the information of copied replication logs. The replication log copy process has following two modes: SYNC and ASYNC. You can configure it with the ha_copy_sync_mode of cubrid_ha.conf. For details on these modes, see Log Multiplexing.
_images/image15.png
  • Replication log reflection process (applylogdb) : Reflects the log that has been copied by the replication log copy process to a node. The information of reflected replications is stored in the internal catalog (db_ha_apply_info). You can use the applyinfo utility to verify this information.
_images/image16.png
Servers

Here, the word "server" is a logical representation of database server processes. Depending on its status, a server can be either an active server or a standby server.

  • Active server : A server that belongs to a master node; the status is active. An active server provides all services, including read, write, etc. to the user.
  • Standby server : A standby server that belongs to a non-master node; the status is standby. A standby server provides only the read service to the user.

The server status changes based on the status of the node. You can use the cubrid changemode utility to verify server status. The maintenance mode exists for operational convenience and you can change it by using the cubrid changemode utility.

_images/image17.png
  • active : The status of servers that run on a master node is usually active. In this status, all services including read, write, etc. are provided.
  • standby : The status of servers that run on a slave node or a replica node is standby. In this status, only the read service is provided.
  • maintenance : The status of servers can be manually changed for operational convenience is maintenance. In this status, only a csql can access and no service is provided to the user.
  • to-be-active : The status in which a standby server will become active for reasons such as failover, etc. is to-be-active. In this status, servers prepare to become active by reflecting transaction logs from the existing master node to its own server. The node in this status can accept only SELECT query.
  • Other : This status is internally used.

When the node status is changed, on cub_master process log and cub_server process log, following error messages are saved. But, they are saved only when the value of error_log_level in cubrid.conf is error or less.

  • The following log information of cub_master process is saved on $CUBRID/log/<hostname>_master.err file.

    HA generic: Send changemode request to the server. (state:1[active], args:[cub_server demodb ], pid:25728).
    HA generic: Receive changemode response from the server. (state:1[active], args:[cub_server demodb ], pid:25728).
    
  • The following log information of cub_server is saved on $CUBRID/log/server/<db_name>_<date>_<time>.err file.

    Server HA mode is changed from 'to-be-active' to 'active'.
    
heartbeat Message

As a core element to provide HA, it is a message exchanged among master, slave, and replica nodes to monitor the status of other nodes. A master process periodically exchanges heartbeat messages with all other master processes in the group. A heartbeat message is exchanged through the UDP port configured in the ha_port_id parameter of cubrid_ha.conf. The exchange interval of heartbeat messages is determined by an internally configured value.

When the master node fails, a failover occurs to a slave node.

_images/image18.png
failover and failback

A failover means that the highest priority slave node automatically becomes a new master node when the original master node fails to provide services due to a failure. A master process calculates scores for all nodes in the CUBRID HA group based on the collected information, promotes slave nodes to master modes when it is necessary, and then notifies the management process of the changes it has made.

A failback means that the previously failed master node automatically becomes a master node back after the failure node is restored. The CUBRID HA does not currently support this functionality.

_images/image19.png

If a heartbeat message fails to deliver, a failover will occur. For this reason, servers with unstable connection may experience failover even though no actual failures occur. To prevent a failover from occurring in the situation described above, configure ha_ping_ports. Configuring ha_ping_ports will send a ping message to a node specified in ha_ping_ports in order to verify whether the network is stable or not when a heartbeat message fails to deliver. For details on configuring ha_ping_ports, see cubrid_ha.conf.

Broker Mode

A broker can access a server with one of the following modes: Read Write, Read Only or Standby Only. This configuration value is determined by a user.

A broker finds and connects to a suitable DB server by trying to establish a connection in the order of DB server connections; this is, if it fails to establish a connection, it tries another connection to the next DB server defined until it reaches the last DB server. If no connection is made even after trying all servers, the broker fails to connect to a DB server.

For details on how to configure broker mode, see cubrid_broker.conf.

DB connection is affected by PREFERRED_HOSTS, CONNECT_ORDER and MAX_NUM_DELAYED_HOSTS_LOOKUP parameters in cubrid_broker.conf. See Connecting a Broker to DB for further information.

The below is the description if the above parameters are not specified.

Read Write

"ACCESS_MODE=RW"

A broker that provides read and write services. This broker is usually connected to an active server. If there is no active server, this broker will be connected to a standby server temporarily. Therefore, a Read Write broker can be temporarily connected to a standby server.

When the broker temporarily establishes a connection to a standby server, it will disconnect itself from the standby server at the end of every transaction so that it can attempt to find an active server at the beginning of the next transaction. When it is connected to the standby server, only read service is available. Any write requests will result in a server error.

The following picture shows how a broker connects to the host through the db-host configuration.

_images/image20.png

The broker tries to connect as the order of B, C, A because db-host in databases.txt is "node B:node C:node A". At this time, "node B:node C:node A" specified in db-host is the real host names defined in the /etc/hosts file.

  • Example 1. node B is crashed, node C is in standby status, and node A is in active status. Therefore, at last, the broker connects to node A.
  • Example 2. node B is crashed, and node C is in active status. Therefore, at last, the broker connects to node C.

Read Only

"ACCESS_MODE=RO"

A broker that provides the read service. This broker is connected to a standby server if possible. Therefore, the Read Only broker can be connected to an active server temporarily.

Once it establishes a connection with an active server, it will maintain that connection until the time specified by RECONNECT_TIME. After RECONNECT_TIME, the broker tries to reconnect as disconnecting the old connection. Or you can reconnect to the standby server by running cubrid broker reset. If a write request is delivered to the Read Only broker, an error occurs in the broker; therefore, only the read service will be available even if it is connected to an active server.

The following picture shows how a broker connects to the host through the db-host configuration.

_images/image21.png

The broker tries to connect as the order of A, B, C because db-host in databases.txt is "node A:node B:node C". At this time, "node A:node B:node C" specified in db-host is the real host names defined in the /etc/hosts file.

  • Example 1. node A is in active status, node B is in standby status. Therefore, at last, the broker connects to node B.
  • Example 2. node A is in active status, node B is crashed, and node C is in standby status. Therefore, at last, the broker connects to node C.
  • Example 3. node A is in active status, node B and node C are crashed. Therefore, at last, the broker connects to node A.

Standby Only

"ACCESS_MODE=SO"

A broker that provides the read service. This broker can only be connected to a standby server. If no standby server exists, no service will be provided.

The following picture shows how a broker connects to the host through the db-host configuration.

_images/image22.png

The broker tries to connect as the order of A, B, C because db-host in databases.txt is "node A:node B:node C". At this time, "node A:node B:node C" specified in db-host is the real host names defined in the /etc/hosts file.

  • Example 1. node A is in active status, node B is in standby status. Therefore, at last, the broker connects to node B.
  • Example 2. node A is in active status, node B is crashed, and node C is in standby status. Therefore, at last, the broker connects to node C.
  • Example 3. node A is in active status, node B and node C are crashed. Therefore, at last, the broker does not connect to any node. This is the difference with Read Only broker.

CUBRID HA Features

Duplexing Servers

Duplexing servers is building a system by configuring duplicate hardware equipment to provide CUBRID HA. This method will prevent any interruptions in a server in case of occurring a hardware failure.

Server failover

A broker defines server connection order and connects to a server according to the defined order. If the connected server fails, the broker connects to the server with the next highest priority. This requires no processing in the application side. The actions taken when the broker connects to another server may differ according to the current mode of the broker. For details on the server connection order and configuring broker mode, see cubrid_broker.conf.

_images/image24.png

Server failback

CUBRID HA does not automatically support server failback. Therefore, to manually apply failback, restore the master node that has been abnormally terminated and run it as a slave node, terminate the node that has become the master from the slave due to failover, and finally, change the role of each node again.

For example, when nodeA is the master and nodeB is the slave, nodeB becomes the master and nodeA becomes the slave after a failover. After terminating nodeB (cubrid heartbeat stop) check (cubrid heartbeat status) whether the status of nodeA has become active. Start (cubrid heartbeat start) nodeB and it will become the slave.

Duplexing Brokers

As a 3-tier DBMS, CUBRID has middleware called the broker which relays applications and database servers. To provide HA, the broker also requires duplicate hardware equipment. This method will prevent any interruptions in a broker in case of occurring a hardware failure.

The configuration of broker redundancy is not determined by the configuration of server redundancy; it can be user-defined. In addition, it can be separated by piece of individual equipment.

To use the failover and failback functionalities of a broker, the altHosts attribute must be added to the connection URL of the JDBC, CCI, or PHP. For a description of this, see JDBC Configuration, CCI Configuration and PHP Configuration.

To set a broker, configure the cubrid_broker.conf file. To set the order of failovers of a database server, configure the databases.txt file. For more information, see Configuring and Starting Broker, and Verifying the Broker Status.

The following is an example in which two Read Write (RW) brokers are configured. When the first connection broker of the application URL is set to broker B1 and the second connection broker to broker B2, the application connects to broker B2 when it cannot connect to broker B1. When broker B1 becomes available again, the application reconnects to broker B1.

_images/image25.png

The following is an example in which the Read Write (RW) broker and the Read Only (RO) broker are configured in each piece of equipment of the master node and the slave node. First, the app1 and the app2 URL connect to broker A1 (RW) and broker B2 (RO), respectively. The second connection (altHosts) is made to broker A2 (RO) and broker B1 (RW). When equipment that includes nodeA fails, app1 and the app2 connect to the broker that includes nodeB.

_images/image26.png

The following is an example of a configuration in which broker equipment includes one Read Write broker (master node) and two Preferred Host Read Only brokers (slave nodes). The Preferred Host Read Only brokers are connected to nodeB and nodeC to distribute the reading load.

_images/image27.png

Broker failover

The broker failover is not automatically failed over by the settings of system parameters. It is available in the JDBC, CCI, and PHP applications only when broker hosts are configured in the altHosts of the connection URL. Applications connect to the broker with the highest priority. When the connected broker fails, the application connects to the broker with the next highest priority. Configuring the altHosts of the connection URL is the only necessary action, and it is processed in the JDBC, CCI, and PHP drivers.

Broker failback

If the failed broker is recovered after a failover, the connection to the existing broker is terminated and a new connection is established with the recovered broker which has the highest priority. This requires no processing in the application side as it is processed within the JDBC, CCI, and PHP drivers. Execution time of failback depends on the value configured in JDBC connection URL. For details, see JDBC Configuration.

Log Multiplexing

CUBRID HA keeps every node in the CUBRID HA group with the identical structure by copying and reflecting transaction logs to all nodes included in the CUBRID HA group. As the log copy structure of CUBRID HA is a mutual copy between the master and the slave nodes, it has a disadvantage of increasing the size of a log volume. However, it has an advantage of flexibility in terms of configuration and failure handling, comparing to the chain-type copy structure.

_images/image28.png

The transaction log copy modes include SYNC and ASYNC. This value can be configured by the user in cubrid_ha.conf file.

SYNC Mode

When transactions are committed, the created transaction logs are copied to the slave node and stored as a file. The transaction commit is complete after receiving a notice on its success. Although the time to execute commit in this mode may take longer than that in ASYNC mode, this is the safest method because the copied transaction logs are always guaranteed to be reflected to the standby server even if a failover occurs.

ASYNC Mode

When transactions are committed, commit is complete without verifying the transfer of transaction logs to a slave node. Therefore, it is not guaranteed that committed transactions are reflected to a slave node in a master node side.

Although ASYNC mode provides a better performance as it has almost no delay when executing commit, there may be data inconsistency in its nodes.

Note

SEMISYNC mode is deprecated, and this operates in the same way as SYNC mode.

Quick Start

This chapter simply explains how to build a master node and a slave node as 1:1 from DB creation. For details of various replication building methods, see Building Replication.

Preparation

Structure Diagram

The diagram below aims to help users who are new to CUBRID HA, by explaining a simple procedure of the CUBRID HA configuration.

_images/image29.png

Specifications

Linux and CUBRID version 2008 R2.2 or later must be installed on the equipment to be used as the master and the slave nodes. CUBRID HA does not support Windows operating system.

Specifications of Configuring the CUBRID HA Equipment

  CUBRID Version OS
For master nodes CUBRID 2008 R2.2 or later Linux
For slave nodes CUBRID 2008 R2.2 or later Linux

Note

This document describes the HA configuration in CUBRID 9.2 or later versions. Note that the previous versions have different settings. For example, cubrid_ha.conf is only available in CUBRID 2008 R4.0 or later. ha_make_slavedb.sh is introduced from CUBRID 2008 R4.1 Patch 2 or later.

Creating Databases and Configuring Servers

Creating Databases

Create databases to be included in CUBRID HA at each node of the CUBRID HA in the same manner. Modify the options for database creation as needed.

[nodeA]$ cd $CUBRID_DATABASES
[nodeA]$ mkdir testdb
[nodeA]$ cd testdb
[nodeA]$ mkdir log
[nodeA]$ cubrid createdb -L ./log testdb en_US
Creating database with 512.0M size. The total amount of disk space needed is 1.5G.

CUBRID 10.0

[nodeA]$

cubrid.conf

Ensure ha_mode of $CUBRID/conf/cubrid.conf in every CUBRID HA node has the same value. Especially, take caution when configuring the log_max_archives and force_remove_log_archives parameters (logging parameters) and the ha_mode parameter (HA parameter).

# Service parameters
[service]
service=server,broker,manager

# Common section
[common]
service=server,broker,manager

# Server parameters
server=testdb
data_buffer_size=512M
log_buffer_size=4M
sort_buffer_size=2M
max_clients=100
cubrid_port_id=1523
db_volume_size=512M
log_volume_size=512M

# Adds when configuring HA (Logging parameters)
log_max_archives=100
force_remove_log_archives=no

# Adds when configuring HA (HA mode)
ha_mode=on

cubrid_ha.conf

Ensure ha_port_id, ha_node_list, ha_db_list of $CUBRID/conf/cubrid_ha.conf in every CUBRID HA node has the same value. In the example below, we assume that the host name of a master node is nodeA and that of a slave node is nodeB.

[common]
ha_port_id=59901
ha_node_list=cubrid@nodeA:nodeB
ha_db_list=testdb
ha_copy_sync_mode=sync:sync
ha_apply_max_mem_size=500

databases.txt

Ensure that you must configure the host names (nodeA:nodeB) of master and slave nodes in db-host of $CUBRID_DATABASES/databases.txt; if $CUBRID_DATABASES is not configured, do it in $CUBRID/databases/databases.txt).

#db-name vol-path db-host log-path lob-base-path
testdb /home/cubrid/DB/testdb nodeA:nodeB /home/cubrid/DB/testdb/log file:/home/cubrid/DB/testdb/lob
Starting and Verifying CUBRID HA

Starting CUBRID HA

Execute the cubrid heartbeat start at each node in the CUBRID HA group. Note that the node executing cubrid heartbeat start first will become a master node. In the example below, we assume that the host name of a master node is nodeA and that of a slave node is nodeB.

  • Master node

    [nodeA]$ cubrid heartbeat start
    
  • Slave node

    [nodeB]$ cubrid heartbeat start
    

Verifying CUBRID HA Status

Execute cubrid heartbeat status at each node in the CUBRID HA group to verify its configuration status.

[nodeA]$ cubrid heartbeat status
@ cubrid heartbeat list
 HA-Node Info (current nodeA-node-name, state master)
   Node nodeB-node-name (priority 2, state slave)
   Node nodeA-node-name (priority 1, state master)
 HA-Process Info (nodeA 9289, state nodeA)
   Applylogdb testdb@localhost:/home1/cubrid1/DB/testdb_nodeB.cub (pid 9423, state registered)
   Copylogdb testdb@nodeB-node-name:/home1/cubrid1/DB/testdb_nodeB.cub (pid 9418, state registered)
   Server testdb (pid 9306, state registered_and_active)

[nodeA]$

Use the cubrid changemode utility at each node in the CUBRID HA group to verify the status of the server.

  • Master node

    [nodeA]$ cubrid changemode testdb@localhost
    The server 'testdb@localhost''s current HA running mode is active.
    
  • Slave node

    [nodeB]$ cubrid changemode testdb@localhost
    The server 'testdb@localhost''s current HA running mode is standby.
    

Verifying the CUBRID HA Operation

Verify that action is properly applied to standby server of the slave node after performing write in an active server of the master node. To make a success connection via the CSQL Interpreter in HA environment, you must specify the host name to be connected after the database name like "@<host_name>"). If you specify a host name as localhost, it is connected to local node.

Warning

Ensure that primary key must exist when creating a table to have replication successfully processed.

  • Master node

    [nodeA]$ csql -u dba testdb@localhost -c "create table abc(a int, b int, c int, primary key(a));"
    [nodeA]$ csql -u dba testdb@localhost -c "insert into abc values (1,1,1);"
    [nodeA]$
    
  • Slave node

    [nodeB]$ csql -u dba testdb@localhost -l -c "select * from abc;"
    === <Result of SELECT Command in Line 1> ===
    <00001> a: 1
            b: 1
            c: 1
    [nodeB]$
    
Configuring and Starting Broker, and Verifying the Broker Status

Configuring the Broker

To provide normal service during a database failover, it is necessary to configure an available database node in the db-host of databases.txt. And ACCESS_MODE in the cubrid_broker.conf file must be specified; if it is omitted, the default value is configured to Read Write mode. If you want to divide into a separate device, you must configure cubrid_broker.conf and databases.txt in the broker device.

  • databases.txt

    #db-name        vol-path                db-host         log-path        lob-base-path
    testdb          /home1/cubrid1/CUBRID/testdb  nodeA:nodeB        /home1/cubrid1/CUBRID/testdb/log file:/home1/cubrid1/CUBRID/testdb/lob
    
  • cubrid_broker.conf

    [%testdb_RWbroker]
    SERVICE                 =ON
    BROKER_PORT             =33000
    MIN_NUM_APPL_SERVER     =5
    MAX_NUM_APPL_SERVER     =40
    APPL_SERVER_SHM_ID      =33000
    LOG_DIR                 =log/broker/sql_log
    ERROR_LOG_DIR           =log/broker/error_log
    SQL_LOG                 =ON
    TIME_TO_KILL            =120
    SESSION_TIMEOUT         =300
    KEEP_CONNECTION         =AUTO
    CCI_DEFAULT_AUTOCOMMIT  =ON
    
    # broker mode parameter
    ACCESS_MODE             =RW
    

Starting Broker and Verifying its Status

A broker is used to access applications such as JDBC, CCI or PHP. Therefore, to simply test server redundancy, execute the CSQL interpreter that is directly connected to the server processes, without having to start a broker. To start a broker, execute cubrid broker start. To stop it, execute cubrid broker stop.

The following example shows how to execute a broker from the master node.

[nodeA]$ cubrid broker start
@ cubrid broker start
++ cubrid broker start: success
[nodeA]$ cubrid broker status
@ cubrid broker status
% testdb_RWbroker
---------------------------------------------------------
ID   PID   QPS   LQS PSIZE STATUS
---------------------------------------------------------
 1  9532     0     0  48120  IDLE

Configuring Applications

Specifies the host name (nodeA_broker, nodeB_broker) and port for an application to connect in the connection URL. The altHosts attribute defines the broker where the next connection will be made when the connection to a broker fails. The following is an example of a JDBC program. For more information on CCI and PHP, see CCI Configuration and PHP Configuration.

Connection connection = DriverManager.getConnection("jdbc:CUBRID:nodeA_broker:33000:testdb:::?charSet=utf-8&altHosts=nodeB_broker:33000", "dba", "");

Environment Configuration

The below is the description for setting the HA environment. See Connecting a Broker to DB for further information regarding the process connecting between a broker and a DB server.

cubrid.conf

The cubrid.conf file that has general information on configuring CUBRID is located in the $CUBRID/conf directory. This page provides information about cubrid.conf parameters used by CUBRID HA.

HA or Not

ha_mode

ha_mode is a parameter used to configure whether to use CUBRID HA. The default value is off. CUBRID HA does not support Windows; it supports Linux only.

  • off : CUBRID HA is not used.
  • on : CUBRID HA is used. Failover is supported for its node.
  • replica : CUBRID HA is used. Failover is not supported for its node.

The ha_mode parameter can be re-configured in the [@<database>] section; however, only off can be entered in the case. An error is returned if a value other than off is entered in the [@<database>] section.

If ha_mode is on, the CUBRID HA values are configured by reading cubrid_ha.conf.

This parameter cannot be modified dynamically. To modify the value of this parameter, you must restart it.

Logging

log_max_archives

log_max_archives is a parameter used to configure the minimum number of archive log files to be archived. The minimum value is 0 and the default is INT_MAX (2147483647). When CUBRID has installed for the first time, this value is set to 0 in the cubrid.conf file. The behavior of the parameter is affected by force_remove_log_archives.

If the value of force_remove_log_archives is set to no, the existing archive log files to which the activated transaction refers or the archive log files of the master node not reflected to the slave node in HA environment will not be deleted. For details, see the following force_remove_log_archives.

For details about log_max_archives, see Logging-Related Parameters.

force_remove_log_archives

It is recommended to configure force_remove_log_archives to no so that archive logs to be used by HA-related processes always can be maintained to set up HA environment by configuring ha_mode to on.

If you configure the value for force_remove_log_archives to yes, the archive log files which will be used in the HA-related process can be deleted, and this may lead to an inconsistency between replicated databases. If you want to maintain free disk space even though doing this could lead to risk, you can configure the value to yes.

For details about force_remove_log_archives, see Logging-Related Parameters.

Note

From 2008 R4.3 in replica mode, it will be always deleted except for archive logs as many as specified in the log_max_archives parameter, regardless the force_remove_log_archives value specified.

Access

max_clients

max_clients is a parameter used to configure the maximum number of clients to be connected to a database server simultaneously. The default is 100.

Because the replication log copy and the replication log reflection processes start by default if CUBRID HA is used, you must configure the value to twice the number of all nodes in the CUBRID HA group, except the corresponding node. Furthermore, you must consider the case in which a client that is connected to another node at the time of failover attempts to connect to that node.

For details about max_clients, see Connection-Related Parameters.

The Parameters That Must Have the Same Value for All Nodes

  • log_buffer_size : The size of a log buffer. This must be same for all nodes, as it affects the protocol between copylogdb that duplicate the server and logs.
  • log_volume_size : The size of a log volume. In CUBRID HA, the format and contents of a transaction log are the same as that of the replica log. Therefore, the parameter must be same for all nodes. If each node creates its own DB, the cubrid createdb options (--db-volume-size, --db-page-size, --log-volume-size, --log-page-size, etc.) must be the same.
  • cubrid_port_id : The TCP port number for creating a server connection. It must be same for all nodes in order to connect copylogdb that duplicate the server and logs.
  • HA-related parameters : HA parameters included in cubrid_ha.conf must be identical by default. However, the following parameters can be set differently according to the node.

The Parameters That Can be Different Among Nodes

  • The ha_mode parameter in replica node
  • The ha_copy_sync_mode parameter
  • The ha_ping_hosts parameter

Example

The following example shows how to configure cubrid.conf. Please take caution when configuring log_max_archives and force_remove_log_archives (logging-related parameters), and ha_mode (an HA-related parameter).

# Service Parameters
[service]
service=server,broker,manager

# Server Parameters
server=testdb
data_buffer_size=512M
log_buffer_size=4M
sort_buffer_size=2M
max_clients=200
cubrid_port_id=1523
db_volume_size=512M
log_volume_size=512M

# Adds when configuring HA (Logging parameters)
log_max_archives=100
force_remove_log_archives=no

# Adds when configuring HA (HA mode)
ha_mode=on
log_max_archives=100
cubrid_ha.conf

The cubrid_ha.conf file that has generation information on CUBRID HA is located in the $CUBRID/conf directory. CUBRID HA does not support Windows; it supports Linux only.

See Connecting a Broker to DB for further information regarding the process connecting between a broker and a DB server.

Node

ha_node_list

ha_node_list is a parameter used to configure the group name to be used in the CUBRID HA group and the host name of member nodes in which failover is supported. The group name is separated by @. The name before @ is for the group, and the names after @ are for host names of member nodes. A comma(,) or colon(:) is used to separate individual host names. The default is localhost@localhost.

Note

The host name of the member nodes specified in this parameter cannot be replaced with the IP. You should use the host names which are registered in /etc/hosts.

If the host name is not specified properly, the below message is written into the server.err error log file.

Time: 04/10/12 17:49:45.030 - ERROR *** file ../../src/connection/tcp.c, line 121 ERROR CODE = -353 Tran = 0, CLIENT = (unknown):(unknown)(-1), EID = 1 Cannot make connection to master server on host "Wrong_HOST_NAME".... Connection timed out

A node in which the ha_mode value is set to on must be specified in ha_node_list. The value of the ha_node_list of all nodes in the CUBRID HA group must be identical. When a failover occurs, a node becomes a master node in the order specified in the parameter.

This parameter can be modified dynamically. If you modify the value of this parameter, you must execute cubrid heartbeat reload to apply the changes.

ha_replica_list

ha_replica_list is a parameter used to configure the group name, which is used in the CUBRID HA group, and the replica nodes, which are host names of member nodes in which failover is not supported. There is no need to specify this if you do not construct replica nodes. The group name is separated by @. The name before @ is for the group, and the names after @ are for host names of member nodes. A comma(,) or colon(:) is used to separate individual host names. The default is NULL.

The group name must be identical to the name specified in ha_replica_list. The host names of member nodes and the host names of nodes specified in this parameter must be registered in /etc/hosts. A node in which the ha_mode value is set to replica must be specified in ha_replica_list. The ha_replica_list values of all nodes in the CUBRID HA group must be identical.

This parameter can be modified dynamically. If you modify the value of this parameter, you must execute cubrid heartbeat reload to apply the changes.

Note

The host name of the member nodes specified in this parameter cannot be replaced with the IP. You should use the host names which are registered in /etc/hosts.

ha_db_list

ha_db_list is a parameter used to configure the name of the database that will run in CUBRID HA mode. The default is NULL. You can specify multiple databases by using a comma (,).

Note

The host name of the member nodes specified in this parameter cannot be replaced with the IP. You should use the host names which are registered in /etc/hosts.

Access

ha_port_id

ha_port_id is a parameter used to configure the UDP port number; the UDP port is used to detect failure when exchanging heartbeat messages. The default is 59,901.

If a firewall exists in the service environment, the firewall must be configured to allow the configured port to pass through it.

ha_ping_hosts

ha_ping_hosts is a parameter used to configure the host which verifies whether or not a failover occurs due to unstable network when a failover has started in a slave node. The default is NULL. A comma(,) or colon(:) is used to separate individual host names.

The host name of the member nodes specified in this parameter can be replaced with the IP. When a host name is used, the name must be registered in /etc/hosts.

CUBRID checks hosts specified in ha_ping_hosts every hour; if there is a problem on a host, "ping check" is paused temporarily and checks every 5 minutes if the host is normalized or not.

Configuring this parameter can prevent split-brain, a phenomenon in which two master nodes simultaneously exist as a result of the slave node erroneously detecting an abnormal termination of the master node due to unstable network status and then promoting itself as the new master.

Replication

ha_copy_sync_mode

ha_copy_sync_mode is a parameter used to configure the mode of storing the replication log, which is a copy of transaction log. The default is SYNC.

The value can be one of the following: SYNC and ASYNC. The number of values must be the same as the number of nodes specified in ha_node_list. They must be ordered by the specified value. You can specify multiple modes by using a comma(,) or colon(:). The replica node is always working in ASNYC mode regardless of this value.

For details, see Log Multiplexing.

ha_copy_log_base

ha_copy_log_base is a parameter used to configure the location of storing the transaction log copy. The default is $CUBRID_DATABASES/<db_name>_<host_name>.

For details, see Log Multiplexing.

ha_copy_log_max_archives

ha_copy_log_max_archives is a parameter used to configure the maximum number of keeping replication log files. The default is 1. However, even if the number of replication log files exceeds the specified number of replication log files, they are not deleted if they are not applied to the database.

To prevent wasting needless disk space, it is recommended to keep this value as 1, the default.

ha_apply_max_mem_size

ha_apply_max_mem_size is a parameter used to configure the value of maximum memory that the replication log reflection process of CUBRID HA can use. The default and maximum values are 500 (unit: MB). When the value is larger than the size allowed by the system, memory allocation fails and the HA replication reflection process may malfunction. For this reason, you must check whether or not the memory resource can handle the specified value before setting it.

ha_applylogdb_ignore_error_list

ha_applylogdb_ignore_error_list is a parameter used to configure for proceeding replication in CUBRID HA process by ignoring an error occurrence. The error codes to be ignored are separated by a comma (,). This value has a high priority. Therefore, when this value is the same as the value of the ha_applylogdb_retry_error_list parameter or the error code of "List of Retry Errors," the values of the ha_applylogdb_retry_error_list parameter or the error code of "List of Retry Errors" are ignored and the tasks that cause the error are not retried. For "List of Retry Errors," see the description of ha_applylogdb_retry_error_list below.

ha_applylogdb_retry_error_list

ha_applylogdb_retry_error_list is a parameter used to configure for retrying tasks that caused an error in the replication log reflection process of CUBRID HA until the task succeeds. When specifying errors to be retried, separate each error with a comma (,). The following table shows the default "List of Retry Errors." If these values exist in ha_applylogdb_ignore_error_list, the error will be overridden.

List of Retry Errors

Error Code Name Error Code
ER_LK_UNILATERALLY_ABORTED -72
ER_LK_OBJECT_TIMEOUT_SIMPLE_MSG -73
ER_LK_OBJECT_TIMEOUT_CLASS_MSG -74
ER_LK_OBJECT_TIMEOUT_CLASSOF_MSG -75
ER_LK_PAGE_TIMEOUT -76
ER_PAGE_LATCH_TIMEDOUT -836
ER_PAGE_LATCH_ABORTED -859
ER_LK_OBJECT_DL_TIMEOUT_SIMPLE_MSG -966
ER_LK_OBJECT_DL_TIMEOUT_CLASS_MSG -967
ER_LK_OBJECT_DL_TIMEOUT_CLASSOF_MSG -968
ER_LK_DEADLOCK_CYCLE_DETECTED -1021

ha_replica_delay

This parameter specifies the term of applying the replicated data between a master node and a replica node. CUBRID intentionally delays replicating by the specified time. You can set a unit as ms, s, min or h, which stands for milliseconds, seconds, minutes or hours respectively. If you omit the unit, milliseconds(ms) will be applied. The default value is 0.

ha_replica_time_bound

In a master node, only the transactions which have been run on the specified time with this parameter are applied to the replica node. The format of this value is "YYYY-MM-DD hh:mi:ss". There is no default value.

Note

The following example shows how to configure cubrid_ha.conf.

[common]
ha_node_list=cubrid@nodeA:nodeB
ha_db_list=testdb
ha_copy_sync_mode=sync:sync
ha_apply_max_mem_size=500

Note

The following example shows how to configure the value of /etc/hosts (a host name of a member node: nodeA, IP: 192.168.0.1).

127.0.0.1 localhost.localdomain localhost
192.168.0.1 nodeA

ha_delay_limit

ha_delay_limit is a standard time for CUBRID itself to measure replication delay status, and ha_delay_limit_delta is a value to subtract a time which replication delay is released from a replication delay time. Once a server is measured as a replication delay, it keeps this status until the replication delay time is equal or lower than (ha_delay_limit - ha_delay_limit_delta). A slave node or a replica node corresponds to a standby DB server, that is a target server to judge whether replication is delayed or not.

For example, if you want set replication delay time as 10 minutes and replication-delay-releasing time as 8 minutes, the value of ha_delay_limit will be 600s(or 10min) and the value of ha_delay_limit_delta will be 120s(or 2min).

If it is measured as replication delay, CAS judges that there is a problem for standby DB to process jobs, and attempts to reconnect the other standby DBs.

CAS, which is connected to the DB which has the lower priority because of the replication delay, expects that the replication delay is released when the time by RECONNECT_TIME in cubrid_broker.conf is elapsed, then attempts to reconnect to the standby DB which has higher priority.

ha_delay_limit_delta

See the above description of ha_delay_limit.

ha_copy_log_timeout

This is the maximum value of the time in which a node's database server process (cub_server) waits a response from another node's replication-log-copy process (copylogdb). The default is 5(seconds). If this value is -1, this means to be infinite wait. It only works with SYNC log copy mode(ha_copy_sync_mode) parameter.

ha_monitor_disk_failure_interval

CUBRID judges the disk failure for each time which is set to the value of this parameter. The default is 30, and the unit is second.

  • If the value of ha_copy_log_timeout parameter is -1, the value of ha_monitor_disk_failure_interval parameter is ignored and the disk failure is not judged.
  • If the value of ha_monitor_disk_failure_interval parameter is smaller than the value of ha_copy_log_timeout parameter, the disk failure is judged for each ha_copy_log_timeout + 20 seconds.

ha_unacceptable_proc_restart_timediff

When the abnormal status of a server process is kept, the server can be restarted infinitely; it is better to remove this kind of node from the HA components. Because the server is restarted within a short time when the abnormal status is continued, specify this term with this parameter to detect this situation. If the server is restarted within the specified term, CUBRID assumes that this server is abnormal and remove(demote) this node from the HA components. The default is 2min. If the unit is omitted, it is specified as milliseconds(msec).

SQL Logging

ha_enable_sql_logging

If the value of this parameter is yes, CUBRID generates the log file of SQL which aplylogdb process applies to the DB volume. The log file is located under the sql_log of the replication log directory(ha_copy_log_base). The default is no.

The format of this log file name is <db name>_<master hostname>.sql.log.<id>, and <id> starts from 0. If this size is over ha_sql_log_max_size_in_mbytes, a new file with "<id> + 1" is created. For example, if "ha_sql_log_max_size_in_mbytes=100", demodb_nodeA.sql.log.1 is newly created as the size of demodb_nodeA.sql.log.0 file becomes 100MB.

SQL log files are piled up when this parameter is on; therefore, a user should remove log files manually for retaining the free space.

The SQL log format is as follows.

  • INSERT/DELETE/UPDATE

    -- date | SQL id | SELECT query's length for sampling | the length of a transformed query
    -- SELECT query for sampling
    transformed query
    
    -- 2013-01-25 15:16:41 | 40083 | 33 | 114
    -- SELECT * FROM [t1] WHERE "c1"=79186;
    INSERT INTO [t1]("c1", "c2", "c3") VALUES (79186,'b3beb3decd2a6be974',0);
    
  • DDL

    -- date | SQL id | 0 | the length of a transformed query
    DDL query
    (GRANT query will follow when CREATE TABLE, to grant the authority to the table created with DBA authority.)
    
    -- 2013-01-25 14:22:59 | 1 | 0 | 50
    create class t1 ( id integer, primary key (id)  );
    -- 2013-01-25 14:22:59 | 2 | 0 | 38
    GRANT ALL PRIVILEGES ON [t1] TO public;
    

Warning

When you apply this SQL log from a specific point as creating other DB, triggers should be turned off because the jobs performed by triggers from master node are written to the SQL log file.

ha_sql_log_max_size_in_mbytes

The value of this parameter is the maximum size of the file which is created when SQL applied to DB by applylogdb process is logged. The new file is created when the size of a log file is over this value.

cubrid_broker.conf

The cubrid_broker.conf file that has general information on configuring CUBRID broker is located in the $CUBRID/conf directory. This section explains the parameters of cubrid_broker.conf that are used by CUBRID HA.

See Connecting a Broker to DB for further information regarding the process connecting between a broker and a DB server.

Access Target

ACCESS_MODE

ACCESS_MODE is a parameter used to configure the mode of a broker. The default is RW.

Its value can be one of the following: RW (Read Write), RO (Read Only), SO (Standby Only), or PHRO (Preferred Host Read Only). For details, see Broker Mode.

REPLICA_ONLY

CAS is only accessed to the replica DB if the value of REPLICA_ONLY is ON. The default is OFF. If the value of REPLICA_ONLY is ON and the value of ACCESS_MODE is RW, writing job is possible to even replica DB.

Access Order

CONNECT_ORDER

This parameter specifies whether the host-connecting order from a CAS is sequential or random. The host is configured from db-host of $CUBRID_DATABASES/databases.txt.

The default is SEQ; CAS tries to connect in the order. When it is RANDOM, CAS tries to randomly connect. If PREFERRED_HOSTS parameter is given, CAS tries to connect to the hosts configured in PREFERRED_HOSTS with the order, then uses the value of db-host only when the connection by PREFERRED_HOSTS fails; and CONNECT_ORDER does not affects on the order of PREFERRED_HOSTS.

If you concern that the connections are centralized into one DB, set this value as RANDOM.

PREFERRED_HOSTS

Specify the order to connect by listing host names. The default value is NULL.

You can specify multiple nodes by using a colon (:). First, it tries to connect to host in the following order: host specified in the PREFERRED_HOSTS parameter first and then host specified in $CUBRID_DATABASES/databases.txt.

The following example shows how to configure cubrid_broker.conf. To access localhost in a first priority, set PREFERRED_HOSTS as localhost.

[%PHRO_broker]
SERVICE                 =ON
BROKER_PORT             =33000
MIN_NUM_APPL_SERVER     =5
MAX_NUM_APPL_SERVER     =40
APPL_SERVER_SHM_ID      =33000
LOG_DIR                 =log/broker/sql_log
ERROR_LOG_DIR           =log/broker/error_log
SQL_LOG                 =ON
TIME_TO_KILL            =120
SESSION_TIMEOUT         =300
KEEP_CONNECTION         =AUTO
CCI_DEFAULT_AUTOCOMMIT  =ON

# Broker mode setting parameter
ACCESS_MODE             =RO
PREFERRED_HOSTS         =localhost
Access Limitation

MAX_NUM_DELAYED_HOSTS_LOOKUP

When replication is delayed on all DB servers in the HA environment which specified multiple DB servers to db-host of databases.txt, CUBRID checks the replication-delayed servers until only the specified numbers in the MAX_NUM_DELAYED_HOSTS_LOOKUP parameter and decides the connection(checking the delay of replication is judged for the standby hosts; the delayed time is decided by the ha_delay_limit parameter). Also, MAX_NUM_DELAYED_HOSTS_LOOKUP is not applied to PREFERRED_HOSTS.

For example, when db-host is specified as "host1:host2:host3:host4:host5" and "MAX_NUM_DELAYED_HOSTS_LOOKUP=2", if the status of them as follows:

  • host1: active status
  • host2: standby status, replication is delayed
  • host3: unable to access
  • host4: standby status, replication is delayed
  • host5: standby status, replication is not delayed

then the broker tries to access the two hosts, host2 and host4 which their replications are delayed, then decides to access host4.

The reason to behave like the above is that CUBRID assumes that the replication will be delayed to the other hosts if the replication of the number(specified by MAX_NUM_DELAYED_HOSTS_LOOKUP) of hosts are delayed; therefore, CUBRID decides to connect to the last hosts which CUBRID have tried to access, as CUBRID does not try to access for the left hosts. However, if PREFERRED_HOSTS is specified together, CUBRID tries to access to them first and then tries to access to the hosts of db-host list from the first.

The step which the broker accesses CUBRID is divided into the primary connection and the secondary connection.

  • The primary connection: the step which the broker tries to access DB at first.

    It checks the DB status(active/standby) and whether the replication is delayed or not. At this time, the broker checks DB's status if it's active or standby based on the ACCESS_MODE then decides the connection.

  • The secondary connection: After the failure of the primary connection, the broker tries to connect from the failed position. At this time, the broker ignores the DB status(active/standby) and the delay of replication. However, SO broker always accepts a connection only to a standby DB.

    At this time, the connection is decided if the DB is accessible, by ignoring the delay of replication and DB status(active/standby). However, the error can occur during the query execution. For example, If ACCESS_MODE of the broker is RW but the broker accesses standby DB, it occurs an error during INSERT operation. Regardless of the error, after it is connected to a standby DB and the transaction is executed, the broker retries the primary connection. However, SO broker can never connect to the active DB.

Depending on the value of MAX_NUM_DELAYED_HOSTS_LOOKUP, how the number of hosts, attempting to connect is limited as follows:

  • MAX_NUM_DELAYED_HOSTS_LOOKUP=-1

    The same as you do not specify this parameter, which is the default value. In this case, at the primary step, the delay of replication and the DB status are checked to the end, then the connection is decided. At the second step, even if there is a replication, or even if that is not the expected DB status(active/standby), the broker connects to the last host which was accessible.

  • MAX_NUM_DELAYED_HOSTS_LOOKUP=0

    The secondary connection is processed after the connection is tried only to PREFERRED_HOSTS at the primary step; and at the secondary step, the broker tries to connect to a host even it is delayed in replication or it is not an expected DB status(active/standby). That is, because it is the secondary connection, RW broker can connect to a standby host and RO broker can connect to an active host. However, SO broker can never connect to the active DB.

  • MAX_NUM_DELAYED_HOSTS_LOOKUP=n(>0)

    The broker tries to connect until the specified number of replication-delayed hosts. At the primary connection, the broker inspects until the specified number of replication-delayed hosts; at the secondary connection, the broker connects to a host that there is a delay of replication.

Reconnection

RECONNECT_TIME

When a broker tries to connect a DB server which are not in PREFERRED_HOSTS, RO broker tries to connect to active DB server, or a broker tries to connect to the replication-delayed DB server, if connecting time is over RECONNECT_TIME(default: 10min), the broker tries to reconnect.

See RECONNECT_TIME for further information.

databases.txt

The databases.txt file has information on the order of servers for the CAS of a broker to connect. It is located in the $CUBRID_DATABASES (if not specified, $CUBRID/databases) directory; the information can be configured by using db_hosts. You can specify multiple nodes by using a colon (:). If "CONNECT_ORDER=RANDOM", the connection order is decided as randomly. But if PREFERRED_HOSTS is specified, the specified hosts have the first priority of the connection order.

The following example shows how to configure databases.txt.

#db-name    vol-path        db-host     log-path     lob-base-path
testdb       /home/cubrid/DB/testdb nodeA:nodeB   /home/cubrid/DB/testdb/log  file:/home/cubrid/DB/testdb/lob
JDBC Configuration

To use CUBRID HA in JDBC, you must specify the connection information of another broker (nodeB_broker) to be connected when a failure occurs in broker (nodeA_broker). The attribute configured for CUBRID HA is altHosts which represents information of one or more broker nodes to be connected. For details, see Configuration Connection.

The following example shows how to configure JDBC:

Connection connection = DriverManager.getConnection("jdbc:CUBRID:nodeA_broker:33000:testdb:::?charSet=utf-8&altHosts=nodeB_broker:33000", "dba", "");
CCI Configuration

To use CUBRID HA in CCI, you must use the cci_connect_with_url() function which additionally allows specifying connection information in connection URL; the connection information is used when a failure occurs in broker. The attribute configured for CUBRID HA is altHosts which represents information of one or more broker nodes to be connected.

The following example shows how to configure CCI.

con = cci_connect_with_url ("cci:CUBRID:nodeA_broker:33000:testdb:::?altHosts=nodeB_broker:33000", "dba", NULL);
if (con < 0)
{
      printf ("cannot connect to database\n");
      return 1;
}
PHP Configuration

To use the functions of CUBRID HA in PHP, connect to the broker by using cubrid_connect_with_url, which is used to specify the connection information of the failover broker in the connection URL. The attribute specified for CUBRID HA is altHosts, the information on one or more broker nodes to be connected when a failover occurs.

The following example shows how to configure PHP.

<?php
$con = cubrid_connect_with_url ("cci:CUBRID:nodeA_broker:33000:testdb:::?altHosts=nodeB_broker:33000", "dba", NULL);
if ($con < 0)
{
      printf ("cannot connect to database\n");
      return 1;
}
?>

Note

If you want to run smoothly the broker's failover in the environment which the broker's failover is enabled by setting altHosts, you should set the value of disconnectOnQueryTimeout in URL as true.

If this value is true, an application program releases the existing connection from a broker and reconnects to the other broker which is specified on altHosts.

Connecting a Broker to DB

A broker in HA environment should decide the one DB server to connect among multiple DB servers. At this time, it is different depending on the setting of the DB server and broker; how to connect to the DB server and what DB server should be chosen. In this chapter, we will look over how a broker choose DB server by the setting of HA environment. See Environment Configuration for the description about each parameters used in the environment setting.

Here are the main parameters used in the DB connection with the broker.

Location Configuration file Parameter name Description
DB server cubrid.conf ha_mode HA mode(on/off/replica) of DB server. Default: off
cubrid_ha.conf ha_delay_limit A period to determine whether the replication-delay
ha_delay_limit_delta Time subtracting the resolution time of replication-delay from the time of replication-delay
Broker cubrid_broker.conf ACCESS_MODE Broker mode(RW/RO/SO). Default: RW
REPLICA_ONLY Connectible to REPLICA server or not(ON/OFF). Default: OFF
PREFERRED_HOSTS Connecting to the host that is specified here in priority to the host that you set in the db-host of databases.txt
MAX_NUM_DELAYED_HOSTS_LOOKUP

The number of hosts to determine the delay of replication in databases.txt. If up to the specified number of hosts was determined as the delay of replication, the broker is connected to the host checked at last.

  • -1: check all hosts specified in databases.txt whether replication

    is delayed or not

  • 0: do not check whether replication-delay or not, and process

    the secondary connection immediately

  • n(>0): check up to n hosts whether replication is delayed or not

RECONNECT_TIME Time to try reconnecting after the broker is connected to the improper DB server. Default: 600s. If this value is 0, no try for reconnection.
CONNECT_ORDER A parameter specifying the connecting order whether to connect as or the random order(SEQ/RANDOM). Default: SEQ
Connection Process

When a broker accesses DB server, it tries the primary connection; if it fails, it tries the secondary connection.

  • The primary connection: Check the DB status(active/standby) and the delay of replication.
    1. A broker tries to connect as the order specified by PREFERRED_HOSTS. The broker rejects connecting to the improper DB of which the status does not match with ACCESS_MODE or in which the replication is delayed.
    2. By the CONNECT_ORDER, a broker tries to connect to the host in the order specified in databases.txt or the random order. The broker checks the DB status followed by the ACCESS_MODE and checks the replication-delayed host up to the number specified in MAX_NUM_DELAYED_HOSTS_LOOKUP.
  • The secondary connection: Ignore the DB status(active/standby) and the delay of replication. However, SO broker always accepts to connect only to standby DB.
    1. A broker tries to connect as the order specified by PREFERRED_HOSTS. The broker accepts connecting to the improper DB of which status does not match with ACCESS_MODE or in which the replication is delayed. However, SO broker can never connect to active DB.
    2. By the CONNECT_ORDER, a broker tries to connect to the host in the order specified in databases.txt or the random order. The broker ignores the DB status(active/standby) and the delay of replication; it is connected if possible.
Examples on Behaviours by Configuration

The following shows the example of configuration.

Host DB status

  • host1: active
  • host2: standby, replication is delayed.
  • host3: standby, replica, unable to access.
  • host4: standby, replica, replication is delayed.
  • host5: standby, replica, replication is delayed.

When the status of host DBs are as the above, the below shows samples of behaviours by the configuration.

Behaviours by configuration

  • 2-1, 2-2, 2-3: From 2, (+) is addition and (#) is modification.
  • 3-1, 3-2, 3-3: From 3, (+) is addition and (#) is modification.
No. Configuration Behavior
1
  • ACCESS_MODE=RW
  • PREFERRED_HOSTS=host2:host3
  • db-host=host1:host2:host3:host4:host5
  • MAX_NUM_DELAYED_HOSTS_LOOKUP=-1
  • CONNECT_ORDER=SEQ

At the primary connection try, a broker checks if DB status is active.

  • host2 of PREFERRED_HOSTS is replication-delay and host3 is unable to access; therefore, it tries to connect to db-host
  • connection is established because host1 is on active status.

The broker tries to reconnect after the RECONNECT_TIME because it did not connect to PREFERRED_HOSTS.

2
  • ACCESS_MODE=RO
  • db-host=host1:host2:host3:host4:host5
  • MAX_NUM_DELAYED_HOSTS_LOOKUP=-1
  • CONNECT_ORDER=SEQ

At the primary connection try, a broker checks if DB status is standby.

  • All hosts of which DB status is standby are all replication-delayed or unable to access; therefore, it will be failed at the primary connection.

At the secondary connection try, a broker ignores DB status and replication-delay.

  • The last accessed host, host5 is successful to connect to a broker.

Because the broker accessed the replication-delayed server, it tries to reconnect after RECONNECT_TIME.

2-1
  • (+)PREFERRED_HOSTS=host1:host3

At the primary connection try, a broker checks if DB status is standby.

  • In PREFERRED_HOSTS, host1 is active and host3 is unable to access; therefore, the broker tries to connect to db-host.
  • Because hosts of which DB status is standby are all replication-delayed or unable to access; therefore, it will be failed at the primary connection.

At the secondary connection try, a broker ignores DB status and replication-delay.

  • host1 in PREFERRED_HOSTS is active, but it is possible to access; therefore, it is successful to connect to a broker.

Because the broker accessed the active server, it tries to reconnect after RECONNECT_TIME.

2-2
  • (+)PREFERRED_HOSTS=host1:host3
  • (#)MAX_NUM_DELAYED_HOSTS_LOOKUP=0

At the primary connection try, a broker checks if DB status is standby.

  • In PREFERRED_HOSTS, host1 is active and host3 is unable to access.
  • no tries to connect to db-host.

At the secondary connection try, a broker ignores DB status and replication-delay.

  • In PREFERRED_HOSTS, host1 is active, but it is possible to access; therefore, it is successful to connect to a broker.

Because the broker accessed the active server, it tries to reconnect after RECONNECT_TIME.

2-3
  • (#)MAX_NUM_DELAYED_HOSTS_LOOKUP=2

At the primary connection try, a broker checks if DB status is standby.

  • It fails at the primary connection after checking that host2, host4 are replication-delayed where DB status is standby.

At the secondary connection try, a broker ignores DB status and replication-delay.

  • The lastly accessed host4 is successful to connect to a broker.

Because the broker accessed the replication-delayed server, it tries to reconnect after RECONNECT_TIME.

3
  • ACCESS_MODE=SO
  • db-host=host1:host2:host3:host4:host5
  • MAX_NUM_DELAYED_HOSTS_LOOKUP=-1
  • CONNECT_ORDER=SEQ

At the primary connection try, a broker checks if DB status is standby.

  • It fails at the primary connection because hosts of which status is standby are all replication-delayed or unable to access.

At the secondary connection try, a broker checks if DB status is standby but ignores replication-delay.

  • The lastly accessed host4 is successful to connect to a broker.

Because the broker accessed the replication-delayed server, it tries to reconnect after RECONNECT_TIME.

3-1
  • (+)PREFERRED_HOSTS=host1:host3

At the primary connection try, a broker checks if DB status is standby.

  • In PREFERRED_HOSTS, host1 is active and host3 is unable to access; therefore, it tries to connect to db-host.
  • It fails at the primary connection because hosts of which status is standby are all replication-delayed or unable to access.

At the secondary connection try, a broker checks if DB status is standby but ignores replication-delay.

  • In PREFERRED_HOSTS, host1 is active and host3 is unable to access; therefore, it tries to connect to db-host.
  • The first host of which DB status is standby is host2; therefore, it connects to host2.

Because the broker accessed the replication-delayed server, it tries to reconnect after RECONNECT_TIME.

3-2
  • PREFERRED_HOSTS=host1:host3
  • (#)MAX_NUM_DELAYED_HOSTS_LOOKUP=0

At the primary connection try, a broker checks if DB status is standby.

  • In PREFERRED_HOSTS, host1 is active and host3 is unable to access.
  • It does not try to connect to db-host.

At the secondary connection try, a broker checks if DB status is standby but ignores replication-delay.

  • In PREFERRED_HOSTS, host1 is active and host3 is unable to access; therefore, it tries to connect to db-host.
  • The first host of which DB status is standby is host2; therefore, it connects to host2.

Because the broker accessed the replication-delayed server, it tries to reconnect after RECONNECT_TIME.

3-3
  • (#)MAX_NUM_DELAYED_HOSTS_LOOKUP=2

At the primary connection try, a broker checks if DB status is standby.

  • It fails at the primary connection after checking that host2, host4 are replication-delayed where DB status is standby.

At the secondary connection try, a broker checks if DB status is standby but ignores replication-delay.

  • The lastly accessed host4 is successful to connect to a broker.

Because the broker accessed the replication-delayed server, it tries to reconnect after RECONNECT_TIME.

Running and Monitoring

cubrid heartbeat Utility

cubrid heartbeat command can be run as cubrid hb, the abbreviated command.

start

This utility is used to activate CUBRID HA feature and start all processes of CUBRID HA in the node(database server process, replication log copy process, and replication log reflection process). Note that a master node or a slave node is determined based on the execution order of cubrid heartbeat start.

How to execute the command is as shown below.

$ cubrid heartbeat start

The database server process configured in HA mode cannot be started with the cubrid server start command.

Specify the database name at the end of the command to run only the HA configuration processes (database server process, replication log copy process, and replication log reflection process) of a specific database in the node. For example, use the following command to run the database testdb only:

$ cubrid heartbeat start testdb
stop

This utility is used to disable and stop all components of CUBRID. The node that executes this command stops and a failover occurs to the next slave node according to the CUBRID HA configuration.

How to use this utility is as shown below.

$ cubrid heartbeat stop

The database server process cannot be stopped with the cubrid server stop command.

Specify the database name at the end of the command to stop only the HA configuration processes (database server process, replication log copy process, and replication log reflection process) of a specific database in the node. For example, use the following command to run the database testdb only:

$ cubrid heartbeat stop testdb

If you want to deactivate CUBRID HA feature immediately, add -i option into the "cubrid heartbeat stop" command. This option is used when the speedy quitting is required because the DB server process is working improperly.

$ cubrid heartbeat stop -i
or
$cubrid heartbeat stop --immediately
copylogdb

This utility is used to start or stop the copylogdb process that copies the transaction logs for the db_name of a specific peer_node in the CUBRID HA configuration. You can pause log copy for rebuilding replications in the middle of operation and then rerun it whenever you want.

Even though only the cubrid heartbeat copylogdb start command has succeeded, the functions of detecting and recovering the failure between the nodes are executed. Since the node is the target of failover, the slave node can be changed to the master node.

How to use this utility is as shown below.

$ cubrid heartbeat copylogdb <start|stop> [ -h <host-name> ] db_name peer_node
<host-name>: the name of the remote host where copylogdb command will be executed

When nodeB is a node to run a command and nodeA is peer_node, you can run the command as follows.

[nodeB]$ cubrid heartbeat copylogdb stop testdb nodeA
[nodeB]$ cubrid heartbeat copylogdb start testdb nodeA

When the copylogdb process is started/stopped, the configuration information of the cubrid_ha.conf is used. We recommend that you do not change the configuration as possible after you have set the configuration once. If you need to change it, it is recommended to restart the whole nodes.

applylogdb

This utility is used to start or stop the copylogdb process that reflects the transaction logs for the db_name of a specific peer_node in the CUBRID HA configuration. You can pause log copy for rebuilding replications in the middle of operation and then rerun it whenever you want.

Even though only the cubrid heartbeat copylogdb start command has succeeded, the functions of detecting and recovering the failure between the nodes are executed. Since the node is the target of failover, the slave node can be changed to the master node.

How to use this utility is as shown below.

$ cubrid heartbeat applylogdb <start|stop> [ -h <host-name> ] db_name peer_node
<host-name>: the name of the remote host where appplylogdb command will be executed

When nodeB is a node to run a command and nodeA is peer_node, you can run the command as follows.

[nodeB]$ cubrid heartbeat applylogdb stop testdb nodeA
[nodeB]$ cubrid heartbeat applylogdb start testdb nodeA

When the applylogdb process is started/stopped, the configuration information of the cubrid_ha.conf is used. We recommend that you do not change the configuration as possible after you have set the configuration once. If you need to change it, it is recommended to restart the whole nodes.

reload

This utility is used to retrieve the CUBRID HA information again. To start/stop HA replication processes of the added/removed nodes at once, you can use "cubrid heartbeat replication start/stop" command.

How to use this utility is as shown below.

$ cubrid heartbeat reload

Reconfigurable parameters are ha_node_list and ha_replica_list. Even if an error occurs on a special node during running this command, the left jobs are continued. After reload command is finished, check if the reconfiguration of nodes is applied well or not. If it fails, find the reason and resolve it.

replication(or repl) start

This utility is used to run in batch HA processes(copylogdb/applylogdb) related to a specific node; in general, it is used to run in batch HA replication processes of added nodes after running cubrid heartbeat reload.

replication command can be abbreviated by repl.

cubrid heartbeat repl start <node_name>
  • node_name: one of nodes specified in ha_node_list of cubrid_ha.conf.
replication(or repl) stop

This utility is used to stop in batch HA processes(copylogdb/applylogdb) related to a specific node; in general, it is used to stop in batch HA replication processes of removed nodes after running cubrid heartbeat reload.

replication command can be abbreviated by repl.

cubrid heartbeat repl stop <node_name>
  • node_name: one of nodes specified in ha_node_list of cubrid_ha.conf.
status
$ cubrid heartbeat status [-v] [ -h <host-name> ]
<host-name>: the name of the remote host where status command will be executed

This utility is used to output the information of CUBRID HA group and CUBRID HA components. How to use this utility is as shown below.

$ cubrid heartbeat status
@ cubrid heartbeat status

 HA-Node Info (current nodeB, state slave)
   Node nodeB (priority 2, state slave)
   Node nodeA (priority 1, state master)


 HA-Process Info (master 2143, state slave)
   Applylogdb testdb@localhost:/home/cubrid/DB/testdb_nodeB (pid 2510, state registered)
   Copylogdb testdb@nodeA:/home/cubrid/DB/testdb_nodeA (pid 2505, state registered)
   Server testdb (pid 2393, state registered_and_standby)

Note

act, deact, and deregister commands which were used in versions lower than CUBRID 9.0 are no longer used.

Registering HA to cubrid service

If you register heartbeat to CUBRID service, you can use the utilities of cubrid service to start, stop or check all the related processes at once. The processes specified by service parameter in [service] section in cubrid.conf file are registered to CUBRID service. If this parameter includes heartbeat, you can start/stop all the service processes and the HA-related processes by using cubrid service start / stop command.

How to configure cubrid.conf file is shown below.

# cubrid.conf

...

[service]

...

service=broker,heartbeat

...

[common]

...

ha_mode=on
applyinfo

This utility is used to check the copied and applied status of replication logs by CUBRID HA.

cubrid applyinfo [option] <database-name>
  • database-name : Specifies the name of a server to monitor. A node name is not included.

The following shows the [options] used on cubrid applyinfo.

-r, --remote-host-name=HOSTNAME

Configures the name of a target node in which transaction logs are copied. Using this option will output the information of active logs (Active Info.) of a target node.

-a, --applied-info

Outputs the information of replication reflection of a node executing cubrid applyinfo. The -L option is required to use this option.

-L, --copied-log-path=PATH

Configures the location of transaction logs copied from the other node. Using this option will output the information of transaction logs copied (Copied Active Info.) from the other node.

-p, --pageid=ID

Outputs the information of a specific page in the copied logs. This is available only when the -L option is enabled. The default is 0, it means the active page.

-v

Outputs detailed information.

-i, --interval=SECOND

Outputs the copied status and applied status of transaction logs per specified seconds. To see the delayed status of the replicated log, this option is mandatory.

Example

The following example shows how to check log information (Active Info.) of the master node, the status information of log copy (Copied Active Info.) of the slave node, and the applylogdb info (Applied Info.) of the slave node by executing applyinfo in the slave node.

  • Applied Info.: Shows the status information after the slave node applies the replication log.
  • Copied Active Info.: Shows the status information after the slave node copies the replication log.
  • Active Info.: Shows the status information after the master node records the transaction log.
  • Delay in Copying Active Log: Shows the status information which the transaction logs' copy is delayed.
  • Delay in Applying Copied Log: Shows the status information which the transaction logs' application is delayed.
[nodeB] $ cubrid applyinfo -L /home/cubrid/DB/testdb_nodeA -r nodeA -a -i 3 testdb

 *** Applied Info. ***
Insert count                   : 289492
Update count                   : 71192
Delete count                   : 280312
Schema count                   : 20
Commit count                   : 124917
Fail count                     : 0

 *** Copied Active Info. ***
DB name                        : testdb
DB creation time               : 04:29:00.000 PM 11/04/2012 (1352014140)
EOF LSA                        : 27722 | 10088
Append LSA                     : 27722 | 10088
HA server state                : active

 *** Active Info. ***
DB name                        : testdb
DB creation time               : 04:29:00.000 PM 11/04/2012 (1352014140)
EOF LSA                        : 27726 | 2512
Append LSA                     : 27726 | 2512
HA server state                : active

 *** Delay in Copying Active Log ***
Delayed log page count         : 4
Estimated Delay                : 0 second(s)

 *** Delay in Applying Copied Log ***
Delayed log page count         : 1459
Estimated Delay                : 22 second(s)

The items shown by each status are as follows:

  • Applied Info.
    • Committed page: The information of committed pageid and offset of a transaction reflected last through replication log reflection process. The difference between this value and the EOF LSA of "Copied Active Info. represents the amount of replication delay.
    • Insert Count: The number of Insert queries reflected through replication log reflection process.
    • Update Count: The number of Update queries reflected through replication log reflection process.
    • Delete Count: The number of Delete queries reflected through replication log reflection process.
    • Schema Count: The number of DDL statements reflected through replication log reflection process.
    • Commit Count: The number of transactions reflected through replication log reflection process.
    • Fail Count: The number of DML and DDL statements in which log reflection through replication log reflection process fails.
  • Copied Active Info.
    • DB name: Name of a target database in which the replication log copy process copies logs
    • DB creation time: The creation time of a database copied through replication log copy process
    • EOF LSA: Information of pageid and offset copied at the last time on the target node by the replication log copy process. There will be a delay in copying logs as much as difference with the EOF LSA value of "Active Info." and with the Append LSA value of "Copied Active Info."
    • Append LSA: Information of pageid and offset written at the last time on the disk by the replication log copy process. This value can be less than or equal to EOF LSA. There will be a delay in copying logs as much as difference between the EOF LSA value of "Copied Active Info." and this value.
    • HA server state: Status of a database server process which replication log copy process receives logs from. For details on status, see Servers.
  • Active Info.
    • DB name: Name of a database whose node was configured in the -r option.
    • DB creation time: Database creation time of a node that is configured in the -r option.
    • EOF LSA: The last information of pageid and offset of a database transaction log of a node that is configured in the -r option. There will be a delay in copying logs as much as difference between the EOF LSA value of "Copied Active Info." and this value.
    • Append LSA: Information of pageid and offset written at the last time on the disk by the database whose node was configured in the -r option.
    • HA server state: The server status of a database server whose node was configured in the -r option.
  • Delay in Copying Active Log
    • Delayed log page count: the count of transaction log pages which the copy is delayed.
    • Estimated Delay: the expected time which the logs copying is completed.
  • Delay in Applying Copied Log
    • Delayed log page count: the count of transaction log pages which the application is delayed.
    • Estimated Delay: the expected time which the logs applying is completed.

When you run this command in replica node, if "ha_replica_delay=30s" is specified in cubrid.conf, the following information is printed out additionally.

 *** Replica-specific Info. ***
Deliberate lag                 : 30 second(s)
Last applied log record time   : 2013-06-20 11:20:10

Each item of the status information is as below.

  • Replica-specific Info.
    • Deliberate lag: delayed time a user defined by ha_replica_delay parameter
    • Last applied log record time: the time where the replication log of being applied in the replica node recently was actually applied in the master node.

When you run this command in replica node, if "ha_replica_delay=30s" and "ha_replica_time_bound=2013-06-20 11:31:00" are specified in cubrid.conf, "ha_replica_delay=30s" is ignored and the following information is printed out additionally.

 *** Replica-specific Info. ***
Last applied log record time   : 2013-06-20 11:25:17
Will apply log records up to   : 2013-06-20 11:31:00

Each item of the status information is as below.

  • Replica-specific Info.
    • Last applied log record time: the time where the replication log of being applied in the replica node recently was actually applied in the master node.
    • Will apply log records up to: the replica node will apply the master node's logs replicated up to this time.

When applylogdb stops the replication after the time of being specified by ha_replica_time_bound, the error message which is printed out in the file, $CUBRID/log/db-name@local-node-name_applylogdb_db-name_remote-node-name.err is as below.

Time: 06/20/13 11:51:05.549 - ERROR *** file ../../src/transaction/log_applier.c, line 7913 ERROR CODE = -1040 Tran = 1, EID = 3
HA generic: applylogdb paused since it reached a log record committed on master at 2013-06-20 11:31:00 or later.
Adjust or remove ha_replica_time_bound and restart applylogdb to resume.
cubrid changemode

This utility is used to check and change the server status of CUBRID HA.

cubrid changemode [options] <database-name@node-name>
  • database-name@node-name: Specifies the name of a server to be checked or changed and separates each node name by using @. If [options] is omitted, server status is displayed.

The following shows [options] used in cubrid changemode.

-m, --mode=MODE

Changes the server status. You can enter one of the following:

standby, maintenance or active.

  • You can change a mode as maintenance if a server's status is standby.
  • You can change a mode as standby if a server's status is maintenance.
  • You can change a mode as active if a server's status is to-be-active. However, this should be used together with --force option. See the below descrioption regarding --force option.
-f, --force

Configures whether or not to forcibly change the server status. This option must be configured if you want to change the server status from to-be-active to active. |

If it is not configured, the status will not be changed to active. Forcibly change may cause data inconsistency among replication nodes; so it is not recommended. |

-t, --timeout=SECOND

The default is 5(seconds). Configures the waiting time for the normal completion of the transaction that is being processed when the node status switches from standby to maintenance.

If the transaction is still in progress beyond the configured time, it will be forced to terminate and switch to maintenance status; if all transactions have completed normally within the configured time, it will switch to maintenance status immediately.

Status Changeable

This table shows changeable modes depending on current status.

  Changeable
active standby maintenance
Current Status standby X O O
to-be-standby X X X
active O X X
to-be-active O* X X
maintenance X O O

* When the server status is to-be-active, forcibly change may cause data inconsistency among replication nodes. It is not recommended if you are not skilled enough.

Example

The following example shows how to switch the testdb server status in the localhost node to maintenance. The waiting time for all transactions in progress to complete normally is 5 seconds, which is the default value for the -t option. If all transactions are complete within this time limit, the status will be switched immediately. However, if there are transactions still being processed after this time limit, they will be rolled back before changing the status.

$ cubrid changemode -m maintenance testdb@localhost
The server 'testdb@localhost''s current HA running mode is maintenance.

The following example shows how to retrieve status of the testdb server in the localhost node.

$ cubrid changemode testdb@localhost
The server 'testdb@localhost''s current HA running mode is active.
Monitoring CUBRID Manager HA

CUBRID Manager is a dedicated CUBRID database management tool that provides the CUBRID database management and query features in a GUI environment. CUBRID Manager provides the HA dashboard, which shows the relationship diagram for the CUBRID HA group and server status. For details, see CUBRID Manager manual.

Structures of HA

There are four possible structures for CUBRID HA: The default structure, multiple-slave node structure, load balancing structure, and multiple-standby server structure. In the table below, M stands for a master node, S for a slave node, and R for a replica node.

Structure Node structure (M:S:R) Characteristic
Default Structure 1:1:0 The most basic structure of CUBRID HA consists of one master node and one slave node and provides availability which is a unique feature of CUBRID HA.
Multiple-Slave Node Structure 1:N:0 This is a structure in which availability is increased by several slave nodes. However, note that there may be a situation in which data is inconsistent in the CUBRID HA group when multiple failures occur.
Load Balancing Structure 1:1:N Several replica nodes are added in the basic structure. Read service load can be distributed, and the HA load is reduced, comparing to a multiple-slave node structure. Note that replica nodes do not failover.
Multiple-Standby Server Structure 1:1:0 Basically, this structure is the same as the basic structure. However, several slave nodes are installed on a single physical server.

In the following description, it is assumed that there is no data in the testdb database on each node. To build HA feature as replicating database, see Building Replication or Rebuilding Replication Script.

Basic Structure of HA

The most basic structure of CUBRID HA consists of one master node and one slave node.

The default configuration is one master node and one slave node. To distribute the write load, a multi-slave node or load-distributed configuration is recommended. In addition, to access a specific node such as a slave node or replica node in read-only mode, configure the Read Only broker or the Preferred Host Read Only broker. For details about broker configuration, see Duplexing Brokers.

An Example of Node Configuration

_images/image30.png

You can configure each node in the basic structure of HA as shown below:

  • node A (master node)

    • Configure the ha_mode of the cubrid.conf file to on.

      ha_mode=on
      
    • The following example shows how to configure cubrid_ha.conf:

      ha_port_id=59901
      ha_node_list=cubrid@nodeA:nodeB
      ha_db_list=testdb
      
  • node B (slave node): Configure this node in the same manner as node A.

For the databases.txt file of a broker node, it is necessary to configure the list of hosts configured as HA in db-host according to their priority. The following example shows the databases.txt file.

#db-name    vol-path                  db-host       log-path                   lob-base-path
testdb     /home/cubrid/DB/testdb     nodeA:nodeB   /home/cubrid/DB/testdb/log file:/home/cubrid/DB/testdb/lob

The cubrid_broker.conf file can be set in a variety of ways according to configuration of the broker. It can also be configured as separate equipment with the databases.txt file.

The example below shows that the RW broker is set in each node, and node A and node B have the same value.

[%RW_broker]
...

# Broker mode setting parameter
    ACCESS_MODE             =RW

Connection Configuration of Applications

See JDBC Configuration, CCI Configuration, and PHP Configuration in Environment Configuration.

Remark

The moving path of a transaction log in these configurations is as follows:

_images/image31.png
Multiple-Slave Node Structure

In multiple-slave node structure, there is one master node and several slave nodes to improve the service availability of CUBRID.

Because replication log copy process and replication log reflection process are running at all nodes in the CUBRID HA group, a load of copying replication log occurs. Therefore, all nodes in the CUBRID HA group have high network and disk usage.

Because there are many nodes with HA enabled, read and write services never fail as long as a single node is alive.

In the multiple-slave node structure, the node becoming a master node when failover occurs is determined by the order specified in ha_node_list. If the value of ha_node_list is node1:node2:node3 and the master node is node A, node B will become a new master node when the master node fails.

An Example of Node Configuration

_images/image32.png

You can configure each node in the basic structure of HA as shown below:

  • node A (master node)

    • Configure the ha_mode of the cubrid.conf file to on.

      ha_mode=on
      
    • The following example shows how to configure cubrid_ha.conf:

      ha_port_id=59901
      ha_node_list=cubrid@nodeA:nodeB:nodeC
      ha_db_list=testdb
      ha_copy_sync_mode=sync:sync:sync
      
  • node B, node C (slave node): Configure this node in the same manner as node A.

You must enter the list of hosts configured in HA in order of priority in the databases.txt file of a broker node. The following is an example of the databases.txt file.

#db-name   vol-path                   db-host             log-path                   lob-base-path
testdb     /home/cubrid/DB/testdb     nodeA:nodeB:nodeC   /home/cubrid/DB/testdb/log file:/home/cubrid/DB/testdb/lob

The cubrid_broker.conf file can be set in a variety of ways according to configuration of the broker. It can also be configured as separate equipment with the databases.txt file. In this example, the RW broker is configured in node A, node B, and node C.

The following is an example of the databases.txt file in node A, node B, and node C.

[%RW_broker]
...

# Broker mode setting parameter
ACCESS_MODE             =RW

Connection Configuration of Applications

Connect the application to access to the broker of node A, node B, or node C.

Connection connection = DriverManager.getConnection(
    "jdbc:CUBRID:nodeA:33000:testdb:::?charSet=utf-8&altHosts=nodeB:33000,nodeC:33000", "dba", "");

For details, see JDBC Configuration, CCI Configuration, and PHP Configuration in Environment Configuration.

Note

The data in the CUBRID HA group may lose integrity when there are multiple failures in this structure and the example is shown below.

  • n a situation where a failover occurs in the first slave node while replication in the second slave node is being delayed due to restart
  • In a situation where a failover re-occurs before replication reflection of a new master node is not complete due to frequent failover

In addition, if the mode of replication log copy process is ASYNC, the data in the CUBRID HA group may lose integrity.

If the data in the CUBRID HA group loses integrity for any of the reasons above, all data in the CUBRID HA group should be fixed as the same by using Building Replication or Rebuilding Replication Script.

Remark

The moving path of a transaction log in these configurations is as follows:

_images/image33.png
Load Balancing Structure

The load balancing structure increases the availability of the CUBRID service by placing several nodes in the HA configuration (one master node and one slave node) and distributes read-load.

Because the replica nodes receive replication logs from the nodes in the HA configuration and maintain the same data, and because the nodes in the HA configuration do not receive replication logs from the replica nodes, its network and disk usage rate is lower than that of the multiple-slave structure.

Because replica nodes are not included in the HA structure, they provide read service without failover, even when all other nodes in the HA structure fail.

An Example of Node Configuration

_images/image34.png

You can configure each node in load balancing structure as shown below:

  • node A (master node)

    • Configure the ha_mode of the cubrid.conf file to on.

      ha_mode=on
      
    • The following example shows how to configure cubrid_ha.conf:

      ha_port_id=59901
      ha_node_list=cubrid@nodeA:nodeB
      ha_replica_list=cubrid@nodeC:nodeD:nodeE
      ha_db_list=testdb
      ha_copy_sync_mode=sync:sync
      
  • node B (slave node): Configure this node in the same manner as node A.

  • node C, node D, node E (replica node)

    • Configure the ha_mode of the cubrid.conf file to replica.

      ha_mode=replica
      
    • You can configure the cubrid_ha.conf file in the same manner as node A.

The cubrid_broker.conf can be set in a variety of ways according to configuration of the broker. It can also be configured as separate equipment with the databases.txt file.

In this example, broker and DB server exist on the same machine; the RW broker is configured in node A and node B; the SO broker with "CONNECT_ORDER=RANDOM" and "PREFERRED_HOSTS=localhost" is configured in node C, node D and node E. each of node C, node D or node E tries to connect to local DB server first because they are set as "PREFERRED_HOSTS=localhost". When it is failed to connect to localhost, it tries to connect to one of db-hosts in databases.txt randomly because they are set as "CONNECT_ORDER=RANDOM".

The following is an example of cubrid_broker.conf in node A and node B.

[%RW_broker]
...

# Broker mode setting parameter
ACCESS_MODE             =RW

The following is an example cubrid_broker.conf in node C, node D and node E.

[%PHRO_broker]
...

# Broker mode setting parameter
ACCESS_MODE             =SO
PREFERRED_HOSTS         =localhost

You must enter the list of DB server hosts in the order so that each broker can be connected appropriate HA or load balancing server in the databases.txt file of a broker node.

The following is an example of the databases.txt file in node A and node B.

#db-name    vol-path                  db-host       log-path             lob-base-path
testdb     /home/cubrid/DB/testdb   nodeA:nodeB   /home/cubrid/DB/testdb/log file:/home/cubrid/CUBRID/testdb/lob

The following is an example of the databases.txt file in node C, node D and node E.

#db-name    vol-path                db-host             log-path                    lob-base-path
testdb     /home/cubrid/DB/testdb   nodeC:nodeD:nodeE   /home/cubrid/DB/testdb/log  file:/home/cubrid/CUBRID/testdb/lob

Connection Configuration of Applications

Connect the application to access in read/write mode to the broker of node A or node B. The following is an example of a JDBC application.

Connection connection = DriverManager.getConnection(
    "jdbc:CUBRID:nodeA:33000:testdb:::?charSet=utf-8&altHosts=nodeB:33000", "dba", "");

Connect the application to access in read-only mode to the broker of node C, node D or node E. The following is an example of a JDBC application. Configure "loadBalance=true" on the URL to connect randomly to the main host and hosts which are specified by altHosts.

Connection connection = DriverManager.getConnection(
    "jdbc:CUBRID:nodeC:33000:testdb:::?charSet=utf-8&loadBalance=true&altHosts=nodeD:33000,nodeE:33000", "dba", "");

For details, see JDBC Configuration, CCI Configuration, and PHP Configuration in Environment Configuration.

Remark

The path of a transaction log in these configurations is as follows:

_images/image35.png
Multiple-Standby Server Structure

Although its node structure has a single master node and a single slave node, many slave nodes from different services are physically configured in a single server.

This structure is for very small services in which the reading load of slave nodes is light. It is strictly for the availability of the CUBRID service. For this reason, when a master node that failed after a failover has been restored, the load must be moved back to the original master node to minimize the load of the server with multiple-slave nodes.

_images/image36.png

An Example of Node Configuration

You can configure each node in the basic structure of HA as shown below:

  • node AM, node AS : Configure them in the same manner.

    • Configure the ha_mode of the cubrid.conf file to on.

      ha_mode=on
      
    • The following example shows how to configure cubrid_ha.conf.

      ha_port_id=10000
      ha_node_list=cubridA@Host1:Host5
      ha_db_list=testdbA1,testdbA2
      ha_copy_sync_mode=sync:sync
      
  • node BM, node BS : Configure them in the same manner.

    • Configure the ha_mode of the cubrid.conf file to on.

      ha_mode=on
      
    • The following example shows how to configure cubrid_ha.conf.

      ha_port_id=10001
      ha_node_list=cubridB@Host2:Host5
      ha_db_list=testdbB1,testdbB2
      ha_copy_sync_mode=sync:sync
      
  • node CM, node CS : Configure them in the same manner.

    • Configure the ha_mode of the cubrid.conf file to on.

      ha_mode=on
      
    • The following example shows how to configure cubrid_ha.conf.

      ha_port_id=10002
      ha_node_list=cubridC@Host3:Host5
      ha_db_list=testdbC1,testdbC2
      ha_copy_sync_mode=sync:sync
      
  • node DM, node DS : Configure them in the same manner.

    • Configure the ha_mode of the cubrid.conf file to on.

      ha_mode=on
      
    • The following is an example of the cubrid_ha.conf configuration.

      ha_port_id=10003
      ha_node_list=cubridD@Host4:Host5
      ha_db_list=testdbD1,testdbD2
      ha_copy_sync_mode=sync:sync
      

HA Constraints

Supported Platforms

Currently, CUBRID HA is supported by Linux only. All nodes within CUBRID HA groups must be configured on the same platforms.

Table Primary Key

CUBRID HA synchronizes data among nodes with the following method (as known as transaction log shipping): It replicates the primary key-based replication logs generated from the server of a master node to a slave node and then reflects the replication logs to the slave node.

If data of the specific table within CUBRID HA groups is not synchronized, you should check whether the appropriate primary key has specified for the table.

On the partitioned table, the table which has promoted some partitions by the PROMOTE statement replicates all data to the slave. However, since the table does not have the primary key, the data changes on the table made by the master are not applied to the slave.

Java Stored Procedure

Because using java stored procedures in CUBRID HA cannot be replicated, java stored procedures should be configured to all nodes. For more details, see Environment Configuration for Java Stored Function/Procedure.

Method

CUBRID HA synchronizes data among nodes within CUBRID HA groups based on replication logs, So using method that does not generate replication logs may cause data inconsistency among nodes within CUBRID HA groups.

Therefore, in CUBRID HA environment, it is not recommended to use method. (e.g. CALL login('dba', '') ON CLASS dbuser;)

Standalone Mode

The replication logs are not generated as for tasks performed in standalone mode. For this reason, data inconsistency among nodes within CUBRID HA groups may occur when performing tasks in standalone mode.

Serial Cache

To enhance performance, a serial cache does not access Heap and does not generate replication logs when retrieving or updating serial information. Therefore, if you use a serial cache, the current values of serial caches will be inconsistent among the nodes within CUBRID HA groups.

cubrid backupdb -r

This command is used to back up a specified database. If the -r option is used, logs that are not required for recovery will be deleted. This deletion may result in data inconsistency among nodes within CUBRID HA groups. Therefore, you must not use the -r option.

On-line backup

If you want to perform on-line backup in HA environment, add @hostnameafter the database name. hostnameis a name defined in $CUBRID_DATABASES/databases.txt. Specify "@localhost" because you generally perform on-line backup on the local database.

cubrid backupdb -C -D ./ -l 0 -z testdb@localhost

Backup during running database may occur disk I/O load. Therefore, it is recommended to run backup on slave DB than master DB.

INCR/DECR Functions

If you use INCR / DECR (click counter functions) in a slave node of HA configuration, an error is returned.

LOB (BLOB/CLOB) Type

In a CUBRID HA environment, the meta data (Locator) of a LOB column is replicated and LOB data is not replicated. Therefore, if storage of a LOB type is located on the local machine, no tasks corresponding to columns are allowed in slave nodes or master nodes after failover.

Note

On previous version of CUBRID 9.1, using triggers in CUBRID HA can cause duplicate executions. This may cause data inconsistency among nodes within CUBRID HA groups. Therefore, you should not use triggers on the previous version of 9.1.

Note

UPDATE STATISTICS

From 10.0, UPDATE STATISTICS statement is replicated.

In the previous version of 10.0, UPDATE STATISTICS statement is not replicated; therefore, as a separated operation, you should run this statement in the slave/replica node. When you want to apply UPDATE STATISTICS on the slave/replica node in the previous version of 10.0, you should run this in the CSQL with --sysadm and --write_on_slave options.

Operational Scenarios

Operation Scenario during Read/Write Service

The operation scenario written in this page is not affected by read/write services. Therefore, its impact on the services caused by CUBRID operation is very limited. There can be two types of operation scenarios in which failover occurs or it does not occur.

When Failover Does Not Occur

You can perform the following operations without stopping and restarting nodes in CUBRID HA groups.

General Operation Scenario Consideration
Online Backup Operation task is performed at each master node and slave node each during operation. Note that there may be a delay in the transaction of master node due to the operation task.
Schema change (excluding basic key change), index change, authorization change When an operation task occurs at a master node, it is automatically replication reflected to a slave node. Because replication log is copied and reflected to a slave node after an operation task is completed in a master node, operation task time is doubled. Changing schema must be processed without any failover. Index change and authority change other than the schema change can be performed by stopping each node and executing standalone mode (ex: the -S option of the csql utility) when the operation time is important.
Add volume Operation task is performed at each DB regardless of HA structure. Note that there may be a delay in the transaction of master node due to the operation task. If operation task time is an issue, operation task can be performed by stopping each node and executing standalone mode (ex: the -S of the cubrid addvoldb utility).
Failure node server replacement It can be replaced without restarting the CUBRID HA group when a failure occurs. The failure node must be registered in the ha_node_list of CUBRID HA group, and the node name must not be changed during replacement.
Failure broker server replacement It can be replaced without restarting the broker when a failure occurs. The connection to a broker replaced at a client can be made by rcTime which is configured in URL string.
DB server expansion You can execute cubrid heartbeat reload in each node after configuration change (ha_node_list, ha_replica_list) without restarting the previously configured CUBRID HA group. Starts or stops the copylogdb/applylogdb processes which were added or deleted by loading changed configuration information.
Broker server expansion Run additional brokers without restarting existing brokers. Modify the URL string to connect to a broker where a client is added.

When Failover Occurs

You must stop nodes in CUBRID HA group and complete operation before performing the following operations.

General Operation Scenario Consideration
DB server configuration change A node whose configuration is changed is restarted when the configuration in cubrid.conf is changed.  
Change broker configuration, add broker , and delete broker A broker whose configuration is changed is restarted when the configuration in cubrid_broker.conf is changed.  
DBMS version patch Restart nodes and brokers in HA group after version patch. Version patch means there is no change in the internal protocol, volume, and log of CUBRID.
Operation Scenario during Read Service

The operation scenario written in this page is only applied to read service. It is required to allow read service only or dynamically change mode configuration of broker to Read Only. There can be two types of operation scenarios in which failover occurs or it does not occur.

When Failover Does Not Occur

You can perform the following operations without stopping and restarting nodes in CUBRID HA groups.

General Operation Scenario Consideration
Schema change (primary key change) When an operation task is performed at the master node, it is automatically reflected to the slave node. In order to change the primary key, the existing key must be deleted and a new one added. For this reason, replication reflection may not occur due to the HA internal structure which reflects primary key-based replication logs. Therefore, operation tasks must be performed during the read service.
Schema change (excluding basic key change), index change, authorization change When an operation task is performed at the master node, it is automatically reflected to the slave node. Because replication log is copied and reflected to a slave node after an operation task is completed in a master node, operation task time is doubled. Changing schema must be processed without any failover. Index change and authority change other than the schema change can be performed by stopping each node and executing standalone mode(ex: the span class="nkeyword">-S option of csql) when the operation time is important.

When Failover Occurs

You must stop nodes in CUBRID HA group and complete operation before performing the following operations.

General Operation Scenario Consideration
DBMS version upgrade Restart each node and broker in the CUBRID HA group after they are upgraded. A version upgrade means that there have been changed in the internal protocol, volume, or log of CUBRID. Because there are two different versions of the protocols, volumes, and logs of a broker and server during an upgrade, an operation task must be performed to make sure that each client and broker (before/after upgrade) are connected to the corresponding counterpart in the same version.
Massive data processing (INSERT/UPDATE/DELETE) Stop the node that must be changed, perform an operation task, and then execute the node. This processes massive data that cannot be segmented.
Operation Scenario after Stopping a Service

You must stop all nodes in CUBRID HA group before performing the following operation.

General Operation Scenario Consideration
Changing the host name and IP of a DB server Stop all nodes in the CUBRID HA group, and restart them after the operation task. When a host name has been changed, change the databases.txt file of each broker and reset the broker connection with cubrid broker reset.
Setting Replica Replication Delay

This scenario delays the replication of the master node data in replica node, and stops the replication of the master node data at the specific time, to detect the case which someone deleted the data by mistake and stop the replication at the specified time.

General Operation Scenario Consideration
Setting the delay of replication in replica node Specify the term of replicated delay to replica node, and let the replication stop on the specified time specify ha_replica_delay and ha_replica_time_bound in cubrid.conf

Building Replication

restoreslave

cubrid restoreslave is the same as cubrid restoredb which restores a database from a backup but it includes several convenient features when rebuilding a slave or a replica. With cubrid restoreslave, user does not need to manually collect replication-related information from a backup output to create a replication catalog which is stored in db_ha_apply_info. It automatically reads any necessary information from a backup image and an active log and then it adds the relevant replication catalog into db_ha_apply_info. All you need to do is to provide two mandatory options: the state of the node where the backup image was created, and the hostname of the current master node. Please also refer restoredb for more details.

cubrid restoreslave [OPTION] database-name
-s, --source-state=STATE

You need to specify the state of the node where the backup image was created. STATE may be 'master', 'slave', or 'replica'

-m, --master-host-name=NAME

You need to specify the hostname of the current master node.

--list

This option displays information on backup files of a database; restoration procedure is not performed. For further information, see --list of restoredb

-B, --backup-file-path=PATH

You can specify the directory where backup files are to be located by using the -B option. For further information, see -B of restoredb

-o, --output-file=FILE

You can specify a filename to store output messages. For further information, see -o of restoredb

-u, --use-database-location-path

This option restores a database to the path specified in the database location file(databases.txt). For further information, see -u of restoredb

Example Scenarios of Building Replication

In this section, we will see various scenarios regarding adding a new node or removing a node during HA service.

Note

  • Please note that only tables which have a primary key can be replicated.
  • Please note that volume paths between a master node and a slave (or replica) node must be the same.
  • A node includes replication processing information for all other nodes. For example, let's consider HA architecture with a master nodeA, and two slaves nodeB and nodeC. nodeA has the replication process information for nodeB and nodeC; nodeB has information for nodeB and nodeC; nodeC has information for nodeA and nodeC.
  • Under the assumption of no failover, add a new node. If failover occurs during building replication, it is recommended to rebuild replication from the beginning.

Now let's see in detail about the above scenarios.

When you want to rebuild only the abnormal node in the HA environment, see Rebuilding Replication Script.

Note

  • During building a replication, please note that added or rebuilt node's replication information and replication logs should be updated or removed when you add, rebuild or remove a certain node. Replication information is saved on the db_ha_apply_info table, and it has other nodes' replication process information.

    However, because role change does not occur in a replica node, the other node is not required to have replication information and a replication logs about the replica node. On the other hand, the replica node has all information about a master and a slave.

  • When you run a scenario of Rebuild a Slave during Service, you should update db_ha_apply_info's information directly.

  • When you run a scenario of Add a Slave after Stopping a Service, a slave is newly built; therefore, you can use the automatically added information.

  • When you run a a scenario of Build Another Slave during HA Service or Add a Replica during Service, backed-up database from the existing slave is used; you can use as it exists because master's db_ha_apply_info information is included in the existing slave.

  • When you run a scenario of Remove a Slave during Service, you must remove replication information about a removed slave. However, this information does not make a problem even if this is left.

Add a Slave after Stopping a Service

Now let's see the case of building a new slave node with a single master node - making a 1:1 master-slave composition.

_images/build_slave.png
  • nodeA: a master node's host name
  • nodeB: a slave node's host name to be added newly

This scenario assumes that the database has been created by below commands. When you run createdb, a locale name and a charset should be the same between a master node and a slave node.

export CUBRID_DATABASES=/home/cubrid/DB
mkdir $CUBRID_DATABASES/testdb
mkdir $CUBRID_DATABASES/testdb/log
cd $CUBRID_DATABASES/testdb
cubrid createdb testdb -L $CUBRID_DATABASES/testdb/log en_US.utf8

The backup file is saved in the $CUBRID_DATABASES/testdb directory by default if the location is not specified.

URL's change in an application is not required if a broker node is composed of a separated machine and if adding a new broker is not considered.

Note

If a broker's machine is not separated from a database's, to prepare a fault of a master node's machine, broker's access on a slave machine should be possible, too. To do this, altHosts should be added on an application's access URL and databases.txt's configuration should be changed for broker duplexing.

For broker's configuration on HA environment, see cubrid_broker.conf.

In this scenario, we assume that broker's node is not installed on a separated machine.

With the above in mind, let's work as follows.

  1. Configure HA of master node and slave node.

    • Set the $CUBRID/conf/cubrid.conf identically on master and slave nodes.

      [service]
      service=server,broker,manager
      
      # Add the database name to run when starting the service
      server=testdb
      
      [common]
      ...
      
      # Add when configuring the HA (Logging parameters)
      force_remove_log_archives=no
      
      # Add when configuring the HA (HA mode)
      ha_mode=on
      
    • Set the $CUBRID/conf/cubrid_ha.conf identically on master and slave nodes.

      [common]
      ha_port_id=59901
      
      # cubrid is a group name of HA system, nodeA and nodeB are host names.
      ha_node_list=cubrid@nodeA:nodeB
      
      ha_db_list=testdb
      ha_copy_sync_mode=sync:sync
      ha_apply_max_mem_size=500
      
    • Set the $CUBRID_DATABASES/databases.txt identically on master and slave nodes.

      #db-name    vol-path                db-host         log-path                    lob-base-path
      testdb      /home/cubrid/DB/testdb  nodeA:nodeB     /home/cubrid/DB/testdb/log  file:/home/cubrid/DB/testdb/lob
      
    • Set brokers and applications in HA environment.

      For broker setting and adding altHosts into URL, see cubrid_broker.conf.

    • Set locale library identically on master and slave nodes.

      [nodeA]$ scp $CUBRID/conf/cubrid_locales.txt cubrid_usr@nodeB:$CUBRID/conf/.
      [nodeB]$ make_locale.sh -t64
      
    • Create a directory to a slave node.

      [nodeB]$ cd $CUBRID_DATABASES
      [nodeB]$ mkdir testdb
      
    • Create a log directory to a slave node. (create this on the same path with a master node.)

      [nodeB]$ cd $CUBRID_DATABASES/testdb
      [nodeB]$ mkdir log
      
  2. Stop a master node, backup a master database.

    [nodeA]$ cubrid service stop
    

    Back up the database of the master node and copy the backup file to the slave node.

    If the location where the backup file will be saved in the master node is not specified, the location is set as the log directory of testdb by default. Copy the backup file to the same location in the slave node. testdb_bk0v000 is the backup volume file and testdb_bkvinf is the backup volume information file.

    [nodeA]$ cubrid backupdb -z -S testdb
    Backup Volume Label: Level: 0, Unit: 0, Database testdb, Backup Time: Thu Apr 19 16:05:18 2012
    [nodeA]$ cd $CUBRID_DATABASES/testdb/log
    [nodeA]$ scp testdb_bk* cubrid_usr@nodeB:$CUBRID_DATABASES/testdb/log
    cubrid_usr@nodeB's password:
    testdb_bk0v000                            100% 6157KB   6.0MB/s   00:00
    testdb_bkvinf                             100%   66     0.1KB/s   00:00
    
  3. Restore a database from a slave node.

    Restore the database in the slave node. At this time, the volume path of the master node must be identical to that of the slave node.

    [nodeB]$ cubrid restoredb -B $CUBRID_DATABASES/testdb/log demodb
    
  4. Start a master node, start a slave node.

    [nodeA]$ cubrid heartbeat start
    

    After confirming that the master node has been started, start the slave node.

    If nodeA's state is changed from registered_and_to_be_active to registered_and_active, it means that the master node has been successfully started.

    [nodeA]$ cubrid heartbeat status
    @ cubrid heartbeat status
    
     HA-Node Info (current nodeA, state master)
       Node nodeB (priority 2, state unknown)
       Node nodeA (priority 1, state master)
    
     HA-Process Info (master 123, state master)
    
       Applylogdb testdb@localhost:/home1/cubrid/DB/tdb01_nodeB (pid 234, state registered)
       Copylogdb testdb@nodeB:/home1/cubrid/DB/tdb01_nodeB (pid 345, state registered)
       Server tdb01 (pid 456, state registered_and_to_be_active)
    
    [nodeB]$ cubrid heartbeat start
    

    Confirm that the HA configurations of the master node and the slave node are successfully running

    [nodeA]$ csql -u dba testdb@localhost -c"create table tbl(i int primary key);insert into tbl values (1),(2),(3)"
    
    [nodeB]$ csql -u dba testdb@localhost -c"select * from tbl"
    
                i
    =============
                1
                2
                3
    
Build Another Slave during HA Service

The following is a scenario to add a new slave from an existing slave during a HA service. "Master:Slave" will be from 1:1 to 1:2.

_images/build_another_slave.png
  • nodeA: a master node's host name
  • nodeB: a slave node's host name
  • nodeC: a slave node's host name to be added

You can use an existing master or slave if you want to add a new slave during HA service. In this scenario, let's add a new slave by using an existing slave because we assume that slave's disk I/O is less than master's.

Note

Why possible to use a slave instead of a master when adding a node

The reason to use a slave instead of a master is that master's transaction log (active log + archive log) is replicated to a slave as it is, and master node's transaction logs and slave node's replication logs (replicated transaction logs) are the same in format and content.

Note

Build an initial database

It assumes that the database is already created with the below command. a locale name and a charset should be the same between a master and a slave when you run "createdb".

export CUBRID_DATABASES=/home/cubrid/DB
mkdir $CUBRID_DATABASES/testdb
mkdir $CUBRID_DATABASES/testdb/log
cd $CUBRID_DATABASES/testdb
cubrid createdb testdb -L $CUBRID_DATABASES/testdb/log en_US.utf8

At this time, if you don't specify backup files' saving path as an option, backup files are saved on the log directory specified in databases.txt.

_images/build_another_slave_process.png
  1. HA configuration of nodeC

    • Set $CUBRID/conf/cubrid.conf of nodeC identically with nodeB's.

      "force_remove_log_archives=no" should be set not to let no-replicated logs be deleted during HA service.

      [service]
      service=server,broker,manager
      
      [common]
      ...
      
      # Add when configuring the HA (Logging parameters)
      force_remove_log_archives=no
      
      # Add when configuring the HA (HA mode)
      ha_mode=on
      
    • Set $CUBRID/conf/cubrid_ha.conf of nodeC identically with nodeB's.

      However, add nodeC into ha_node_list, and add one more "sync" into ha_copy_sync_mode.

      [common]
      ha_port_id=59901
      
      # cubrid is a group name of HA system, nodeA, nodeB, and nodeC are host names.
      ha_node_list=cubrid@nodeA:nodeB:nodeC
      
      ha_db_list=testdb
      ha_copy_sync_mode=sync:sync:sync
      ha_apply_max_mem_size=500
      
    • Set a locale library of nodeC identically with that of nodeA or nodeB.

      [nodeB]$ scp $CUBRID/conf/cubrid_locales.txt cubrid_usr@nodeC:$CUBRID/conf/.
      [nodeC]$ make_locale.sh -t64
      
    • Add nodeA, nodeB, and nodeC into db-host of $CUBRID_DATABASES/databases.txt in nodeC.

      #db-name     vol-path                   db-host             log-path                        lob-base-path
      testdb       /home/cubrid/DB/testdb     nodeA:nodeB:nodeC   /home/cubrid/DB/testdb/log      file:/home/cubrid/DB/testdb/lob
      

      db-host of databases.txt is related to the access order to the database server by a broker; therefore, you can change the value as you want. For example, you can write only nodeA:nodeB or localhost into db-host. However, by considering the local machine access, (e.g. csql -u dba testdb@localhost) you should add at least localhost or the name of localhost into db-host.

  2. Apply configuration for preventing from deleting replication logs of nodeB during restoring after backup

    Replication logs of nodeB can be added if service continues after restoring a database from the nodeB backup file to nodeC. By the way, slave's replication logs can be deleted before being copied to nodeC by configuration. To prevent this case, you can configure system parameters as follows.

    • Change the value of ha_copy_log_max_archives bigger without restarting nodeB's database.

      From backup of nodeB, transactions which have been executed after backup of nodeB should be kept; then transactions after backup can be applied to nodeC.

      Therefore, added replication logs of nodeB after backup should be kept.

      Here, let's assume the number of replication logs as 5, which can sufficiently save executed transactions during building nodeC.

      Edit $CUBRID/conf/cubrid_ha.conf

      ha_copy_log_max_archives=5
      

      Apply the change of the parameter ha_copy_log_max_archives to the applylogdb process of nodeB.

      [nodeB]$ cubrid heartbeat applylogdb stop testdb nodeA
      [nodeB]$ cubrid heartbeat applylogdb start testdb nodeA
      

      Note

      If you build nodeC with only nodeA, a master node, to change the value of ha_copy_log_max_archives from nodeB is needless because copying replication logs from nodeB is needless.

      Instead, you should apply the changed log_max_archives to nodeA.

      The value of log_max_archives parameter of cubrid.conf can be changed during service by using "SET SYSTEM PARAMETERS" syntax.

      [nodeA]$ csql -u dba -c "SET SYSTEM PARAMETERS 'log_max_archives=5'" testdb@localhost
      
  3. Backup from nodeB, restore into nodeC

    • Backup a database from nodeB.

      [nodeB]$ cd $CUBRID_DATABASES/testdb/log
      [nodeB]$ cubrid backupdb --sleep-msecs=10 -C -o output.txt testdb@localhost
      

      Note

      --sleep-msecs is an option to set the rest time in each cycle when 1MB is written in a backup file.The unit is millisecond. Consider setting this option if the disk I/O overhead of a machine to back up is severe; however, it is recommended to set this value as small as possible and do backup when backup overhead is small enough because if this value is bigger, backup time takes longer.

      If there is no I/O overhead on nodeB, you can omit this option.

      On the file specified in -o option, the backup result information is written.

    • Copy backup files to nodeC.

      [nodeB]$
      [nodeB]$ scp -l 131072 testdb_bk* cubrid_usr@nodeC:$CUBRID_DATABASES/testdb/log
      

      Note

      scp command's -l option is an option to control the amount of copying file; when you copy files between nodes, use this value properly as considering I/O overhead. The unit is Kbits. 131072 is 16MB.

    • Restore the database into nodeC.

      At this time, the volume path of the slave must be the same with the master.

      [nodeC]$ cubrid restoredb -B $CUBRID_DATABASES/testdb/log testdb
      
  4. Copy the active log of nodeA into nodeC

    In nodeA's active log, there exists a number information of the archive log which is recently created. This information is needed for archive logs, which has been created after the time in which the active log had been copied, to be automatically copied by copylogdb process after the start of HA service of nodeC; therefore, the user just needs to manually copy archive logs which has been created before copying an active log.

    • Start cub_master which manages HA connection in nodeC.

      [nodeC]$ cub_master
      
    • Start copylogdb process for nodeA.

      [nodeC]$ cubrid heartbeat copylogdb start testdb nodeA
      
    • Check if nodeA's active log was copied.

      To copy the current active log means to obtain the number information of the last archive log. Archive logs after this time are automatically copied after the process [5. Start HA server in nodeC].

      [nodeC]$ cd $CUBRID_DATABASES/testdb_nodeA
      [nodeC]$ ls
      testdb_lgar_t  testdb_lgat  testdb_lgat__lock
      
    • Stop copylogdb process for nodeA on nodeC.

      [nodeC]$ cubrid heartbeat copylogdb stop testdb nodeA
      
    • Stop cub_master of nodeC.

      [nodeC]$ cubrid service stop
      
  5. Copy required log files after restoring a database into nodeC

    • Copy all replicated archive logs of nodeB into nodeC.

      [nodeC]$ cd $CUBRID_DATABASES/testdb_nodeA
      [nodeC]$ scp -l 131072 cubrid@nodeB:$CUBRID_DATABASES/testdb_nodeA/testdb_lgar0* .
      

      In this process, please note that all replicated archive logs which are required for replication should exist.

      Note

      scp command's -l option is an option to control the amount of copying file; when you copy files between nodes, use this value properly as considering I/O overhead. The unit is Kbits. 131072 is 16MB.

      Note

      Copy files of which the names end with a number. Here, we copied with "testdb_lgar0*" because numbers of names of all replication log files are started with 0.

      Note

      Preparation plan when the required replication logs are already deleted

      Replication logs which are created between backup time and active log creation time can be deleted if the value of ha_copy_log_max_archives is not large enough; in this case, an error can occur when running the below process, [5. Start HA service on nodeC].

      When an error occurs, start HA service of nodeC by adding archive logs in master if the required logs exist in master node. For example, you can copy an archive log #1 from master if there are archive logs #1, #2, and #3 in master; and there are only replicated archive logs #2, and #3 in slave and #1 is required additionally. However, the case in which master's archive log files are left more can happen only when the value of log_max_archives of master is big enough.

      If there is no wanted number's archive log in master's archive logs, change the value of ha_copy_log_max_archives big enough and do backup-and-restore procedure from the beginning.

      Note

      Check if required replication logs are deleted

      You can check if requried replication logs are deleted or not by watching the testdb_lginf file.

      1. If this is the case of restoring a database from a slave backup file, you can check what pages are required, from the page of master by watching the value of required_lsa_pageid in the db_ha_apply_info catalog table.
      2. Watch the contents of the testdb_lginf file located in $CUBRID_DATABASES/testdb/log directory from bottom to top.
      Time: 03/16/15 17:44:23.767 - COMMENT: CUBRID/LogInfo for database /home/cubrid/DB/databases/testdb/testdb
      Time: 03/16/15 17:44:23.767 - ACTIVE: /home/cubrid/DB/databases/testdb/log/testdb_lgat 1280 pages
      Time: 03/16/15 17:54:40.892 - ARCHIVE: 0 /home/cubrid/DB/databases/testdb/log/testdb_lgar000 0 1277
      Time: 03/16/15 17:57:29.451 - COMMENT: Log archive /home/cubrid/DB/databases/testdb/log/testdb_lgar000 is not needed any longer unless a database media crash occurs.
      Time: 03/16/15 18:03:08.166 - ARCHIVE: 1 /home/cubrid/DB/databases/testdb/log/testdb_lgar001 1278 2555
      Time: 03/16/15 18:03:08.167 - COMMENT: Log archive /home/cubrid/DB/databases/testdb/log/testdb_lgar000, which contains log pages before 2556, is not needed any longer by any HA utilities.
      Time: 03/16/15 18:03:29.378 - COMMENT: Log archive /home/cubrid/DB/databases/testdb/log/testdb_lgar001 is not needed any longer unless a database media crash occurs.
      

      When the contents of testdb_lginf is written as the above, the last two numbers in "Time: 03/16/15 17:54:40.892 - ARCHIVE: 0 /home/cubrid/DB/databases/testdb/log/testdb_lgar000 0 1277" are the start and end IDs of pages which this file store.

      For example, if the page ID at backup is 2300, we can see this ID is between no. 1278 and no. 2555 by watching "testdb_lgar001 1278 2555"; therefore, we can know that the archive logs of master (or replicated archive logs of slave) are required from no. 1 when restoring a database.

  6. Start HA service on nodeC

    [nodeC]$ cubrid heartbeat start
    
  7. Change HA configuration of nodeA and nodeB

    • Turn back the value of ha_copy_log_max_archive of nodeB.

      [nodeB]$ vi cubrid_ha.conf
      
      ha_copy_log_max_archives=1
      
    • Apply the changed value of ha_copy_log_max_archives to the applylogdb process of nodeB.

      [nodeB]$ cubrid heartbeat applylogdb stop testdb nodeA
      [nodeB]$ cubrid heartbeat applylogdb start testdb nodeA
      
    • In cubrid_ha.conf, add nodeC into ha_node_list, and add one "sync" more to nodeA and nodeB.

      $ cd $CUBRID/conf
      $ vi cubrid_ha.conf
      
      ha_node_list=cubrid@nodeA:nodeB:nodeC
      ha_copy_sync_mode=sync:sync:sync
      
    • Apply changed ha_node_list.

      [nodeA]$ cubrid heartbeat reload
      [nodeB]$ cubrid heartbeat reload
      
    • Start coplylogdb and applylogdb for nodeC.

      [nodeA]$ cubrid heartbeat repl start nodeC
      [nodeB]$ cubrid heartbeat repl start nodeC
      
  8. Add a broker and add this broker's host name into altHosts of application URL

    Add a broker if needed, and add this broker's host name into altHosts, the property of application URL to access this broker.

    If you are not considering to add a broker, you do not need to do this job.

    • From all of nodeA and nodeB, add nodeC into db-host of $CUBRID_DATABASES/databases.txt.
    #db-name     vol-path                   db-host             log-path                        lob-base-path
    testdb       /home/cubrid/DB/testdb     nodeA:nodeB:nodeC   /home/cubrid/DB/testdb/log      file:/home/cubrid/DB/testdb/lob
    

    db-host of databases.txt is a configuration parameter related to the order of access from a broker to database servers; therefore, you can change as you want.For example, you can write only "nodeA:nodeB" or "localhost" into db-host. However, if you access database from a local machine (e.g. csql -u dba testdb@localhost), you should include "localhost" or the localhost name into db-host.

Remove a Slave during Service

Let's remove a slave when the HA environment is composed of "master:slave = 1:2".

_images/remove_slave.png
  • nodeA: a master node's host name
  • nodeB: a slave node's host name
  • nodeC: a slave node's host name to be removed
_images/remove_slave_process.png
  1. Stop the service of nodeC

    $ cubrid heartbeat stop     # Processes related to heartbeat (applylogdb, copylogdb, cub_server) are stopped.
    $ cubrid service stop       # Processes such as cub_master, cub_broker, and cub_manager are stopped.
    
  2. Remove nodeC from the configuration of nodeA, and nodeB

  • Remove nodeC in ha_node_list from cubrid_ha.conf of nodeA and nodeB; remove one "sync" in ha_copy_sync_mode.

    $ vi cubrid_ha.conf
    
    ha_node_list=cubrid@nodeA:nodeB
    ha_copy_sync_mode=sync:sync
    
  • Apply the changed ha_node_list.

    Run "reload" command at the master, nodeA.

    [nodeA]$ cubrid heartbeat reload
    

    Run "stop" and "start" commands at the slave, nodeB.

    [nodeB]$ cubrid heartbeat stop
    [nodeB]$ cubrid heartbeat start
    
  • Stop coplylogdb and applylogdb for nodeC.

    [nodeA]$ cubrid heartbeat repl stop nodeC
    [nodeB]$ cubrid heartbeat repl stop nodeC
    
  • Remove replication logs about nodeC from nodeA and nodeB.

    $ cd $CUBRID_DATABASES
    $ rm -rf testdb_nodeC
    
  • Remove replication information about nodeC from nodeA and nodeB.

    You can run DELELTE operation from a slave node only if you add --sysadm and --write-on-standby options on running csql.

    $ csql -u dba --sysadm --write-on-standby testdb@localhost
    
    sysadm> DELETE FROM db_ha_apply_info WHERE copied_log_path='/home/cubrid/DB/databases/testdb_nodeC';
    

    copied_log_path is the path in which replication log files are stored.

  1. Remove nodeC from broker's configuration

    • Remove nodeC if this exists in db-host of databases.txt from nodeA and nodeB.

      $ cd $CUBRID_DATABASES
      $ vi databases.txt
      
      #db-name     vol-path                   db-host             log-path                        lob-base-path
      testdb       /home/cubrid/DB/testdb     nodeA:nodeB         /home/cubrid/DB/testdb/log      file:/home/cubrid/DB/testdb/lob
      
    • Restart brokers of nodeA and nodeB.

      $ cubrid broker restart
      

      Note

      You don't need to hurry to restart these brokers because nodeC is already stopped and an application will not access the nodeC database. If you restart these brokers, you should consider that the applications connected to these brokers can be disconnected. Moreover, if multiple brokers with the same configuration exist, one broker can substitute others; therefore, restart a broker one by one.

      For example, on the above, nodeA and nodeB are the same configuration; therefore, you can restart nodeB first then restart nodeA.

Add a Replica during Service

Now let's add a replica when HA environment is set as "master:slave=1:1". The beginning database setting is the same as the setting in Build an initial database of Build Another Slave during HA Service.

_images/add_replica.png
  • nodeA: a master node's host name
  • nodeB: a slave node's host name
  • nodeC: a replica node's host name to be added newly
_images/add_replica_process.png
  1. Configure HA parameter of nodeC

    • Set nodeC's $CUBRID/conf/cubrid.conf as the same with nodeB except for ha_mode.

      Set "ha_mode=replica".

      [service]
      service=server,broker,manager
      
      [common]
      
      # Add this when doing HA configuration (HA mode)
      ha_mode=replica
      

      Note

      Replica node's transaction logs are not used to replication; therefore, whatever the value of force_remove_log_archives is set to, it works as yes.

    • Configure nodeC's $CUBRID/conf/cubrid_ha.conf

      Add nodeC into ha_replica_list.

      [common]
      ha_port_id=59901
      
      # cubrid is a group name of HA system, nodeA, nodeB, and nodeC are host names.
      ha_node_list=cubrid@nodeA:nodeB
      
      ha_replica_list=cubrid@nodeC
      
      ha_db_list=testdb
      ha_copy_sync_mode=sync:sync
      ha_apply_max_mem_size=500
      
    • Set a locale library of nodeC identically with that of nodeA or nodeB.

      [nodeB]$ scp $CUBRID/conf/cubrid_locales.txt cubrid_usr@nodeC:$CUBRID/conf/.
      [nodeC]$ make_locale.sh -t64
      
    • Add nodeC into db-host of $CUBRID_DATABASES/databases.txt in nodeC.

      #db-name     vol-path                   db-host             log-path                        lob-base-path
      testdb       /home/cubrid/DB/testdb     nodeC   /home/cubrid/DB/testdb/log      file:/home/cubrid/DB/testdb/lob
      

      db-host of databases.txt is related to the access order to the database server by a broker; therefore, you can change the value as you want. For example, you can write only nodeA:nodeB or localhost into db-host. However, by considering the local machine access, (e.g. csql -u dba testdb@localhost) you should add at least localhost or the name of localhost into db-host.

  2. Apply configuration for preventing from deleting replication logs of nodeB during restoring after backup

    nodeB's replication logs can be added after restoring if a service keeps going during restoring on nodeC after backup of nodeB; at this time, some replication logs which are needed for nodeC can be deleted by the configuration. To protect this, configure nodes as following.

    • Change the value of ha_copy_log_max_archives larger without restarting a database on nodeB.

      To apply transactions after backup time to nodeC, transactions should be kept until the nodeC's data which restore nodeB's backup data become the same with master(nodeA)'s.

      Therefore, nodeB's replication logs which are added after backup should be kept.

      Here, let's assume the number of replication log files which can sufficiently store transactions executed during nodeC's building as 5.

      Edit $CUBRID/conf/cubrid_ha.conf

      ha_copy_log_max_archives=5
      

      Apply the change of ha_copy_log_max_archives to nodeB's applylogdb process.

      [nodeB]$ cubrid heartbeat applylogdb stop testdb nodeA
      [nodeB]$ cubrid heartbeat applylogdb start testdb nodeA
      

      Note

      If you build nodeC with nodeA, a master node only, copying replication logs from nodeB is not needed; therefore, changing the value of ha_copy_log_max_archives from nodeB is also needless.

      Instead, it requires to apply a changed value of log_max_archives to nodeA.

      The value of log_max_archives parameter in cubrid.conf can be changed during service with the "SET SYSTEM PARAMETERS" syntax.

      [nodeA]$ csql -u dba -c "SET SYSTEM PARAMETERS 'log_max_archives=5'" testdb@localhost
      
  3. Backup nocdB and restore on nodeC

    • Backup a database from nodeB.

      [nodeB]$ cd $CUBRID_DATABASES/testdb/log
      [nodeB]$ cubrid backupdb --sleep-msecs=10 -C -o output.txt testdb@localhost
      

      Note

      Please refer to the explanation of --sleep-msecs within Build Another Slave during HA Service.

    • Copy backup files to nodeC.

      [nodeB]$
      [nodeB]$ scp -l 131072 testdb_bk* cubrid_usr@nodeC:$CUBRID_DATABASES/testdb/log
      

      Note

      scp command's -l option is an option to control the amount of copying file; when you copy files between nodes, use this value properly as considering I/O overhead. The unit is Kbits. 131072 is 16MB.

    • Restore the database into nodeC.

      At this time, volume paths between a master and a slave should be the same.

      [nodeC]$ cubrid restoredb -B $CUBRID_DATABASES/testdb/log testdb
      
  4. Copy nodeA's active log to nodeC

    In nodeA's active log, there exists a number information of the archive log which is recently created. This information is needed for archive logs, which has been created after the time in which the active log had been copied, to be automatically copied by copylogdb process after the start of HA service of nodeC; therefore, the user just needs to manually copy archive logs which has been created before copying an active log.

    • Start cub_master, which manages HA connections, on nodeC.

      [nodeC]$ cub_master
      
    • Start copylogdb process for nodeA.

      [nodeC]$ cubrid heartbeat copylogdb start testdb nodeA
      
    • Check if nodeA's active log was copied.

      To copy the current active log means to obtain the number information of the last archive log. Archive logs after this time are automatically copied after the process [5. Start HA server in nodeC].

      [nodeC]$ cd $CUBRID_DATABASES/testdb_nodeA
      [nodeC]$ ls
      testdb_lgar_t  testdb_lgat  testdb_lgat__lock
      
    • Stop copylogdb process for nodeA on nodeC.

      [nodeC]$ cubrid heartbeat copylogdb stop testdb nodeA
      
    • Stop cub_master of nodeC.

      [nodeC]$ cubrid service stop
      
  5. Copy required log files after restoring a database into nodeC

    • Copy all replicated archive logs of nodeB into nodeC.

      [nodeC]$ cd $CUBRID_DATABASES/testdb_nodeA
      [nodeC]$ scp -l 131072 cubrid@nodeB:$CUBRID_DATABASES/testdb_nodeA/testdb_lgar0* .
      

      In this process, please note that all replicated archive logs which are required for replication should exist.

      Note

      scp command's -l option is an option to control the amount of copying file; when you copy files between nodes, use this properly as considering I/O overhead. The unit is Kbits. 131072 is 16MB.

      Note

      Copy files of which the names end with a number. Here, we copied with "testdb_lgar0*" because numbers of the names of all replication log files are started with 0.

      Note

      Replication logs which are created between backup time and active log creation time can be deleted if the value of ha_copy_log_max_archives is not large enough; in this case, an error can occur when running the below process, [5. Start HA service on nodeC].

      When an error occurs, take actions by referring to Preparation plan when the required replication logs are already deleted described on the above.

  6. Start HA service on nodeC

    [nodeC]$ cubrid heartbeat start
    
  7. Change HA configuration of nodeA and nodeB

    • Turn back ha_copy_log_max_archive of nodeB.

      [nodeB]$ vi cubrid_ha.conf
      
      ha_copy_log_max_archives=1
      
    • Apply the changed value of ha_copy_log_max_archives to the applylogdb process of nodeB.

      [nodeB]$ cubrid heartbeat applylogdb stop testdb nodeA
      [nodeB]$ cubrid heartbeat applylogdb start testdb nodeA
      
    • In cubrid_ha.conf, add nodeC into ha_node_list, and add one "sync" more to nodeA and nodeB.

      $ cd $CUBRID/conf
      $ vi cubrid_ha.conf
      
      ha_replica_list=cubrid@nodeC
      
    • Apply changed ha_node_list.

      [nodeA]$ cubrid heartbeat reload
      [nodeB]$ cubrid heartbeat reload
      

      At this time, coplylogdb and applylogdb processes for nodeC on nodeA and nodeB are needless to start because nodeC is a replica node.

  8. Add a broker and add this broker's host name into altHosts of application URL

    Add a broker if needed, and add this broker's host name into altHosts, the property of application URL to access this broker.

    If you are not considering to add a broker, you do not need to do this job.

    • From all of nodeA and nodeB, add nodeC into db-host of $CUBRID_DATABASES/databases.txt.
    #db-name     vol-path                   db-host             log-path                        lob-base-path
    testdb       /home/cubrid/DB/testdb     nodeA:nodeB:nodeC   /home/cubrid/DB/testdb/log      file:/home/cubrid/DB/testdb/lob
    

    db-host of databases.txt is a configuration parameter related to the order of access from a broker to database servers; therefore, you can change as you want. For example, you can write only "nodeA:nodeB" or "localhost" into db-host. However, if you access database from a local machine (e.g. csql -u dba testdb@localhost), you should include "localhost" or the localhost name into db-host.

Rebuild a Slave during Service

Now let's see the case of rebuilding a existing slave node during a service in a composition of "master:slave:relica = 1:1:1". The beginning database setting is the same as the setting in Build an initial database of Build Another Slave during HA Service.

_images/rebuild_slave.png
  • nodeA: a host name of a master node
  • nodeB: a host name of a slave node to be rebuilt
  • nodeC: a host name of a replica node
_images/rebuild_slave_process.png
  1. Stop nodeB's service and remove this database

    After stopping nodeB's service, remove nodeB's database volumes and nodeB's replication logs located in nodeA and nodeC.

    • Stop nodeB's service.

      [nodeB]$ cubrid heartbeat stop
      [nodeB]$ cubrid service stop
      
    • Remove nodeB's database volumes and replication logs.

      [nodeB]$ cd $CUBRID_DATABASES
      [nodeB]$ rm testdb/*
      [nodeB]$ rm testdb/log/*
      
      [nodeB]$ rm -rf testdb_nodeA
      
    • Stop log replication processes of nodeB on nodeA and nodeC.

      [nodeA]$ cubrid heartbeat repl stop testdb nodeB
      [nodeC]$ cubrid heartbeat repl stop testdb nodeB
      
    • Remove replication logs for nodeB from nodeA and nodeC.

      [nodeA]$ rm -rf $CUBRID_DATABASES/testdb_nodeB
      [nodeC]$ rm -rf $CUBRID_DATABASES/testdb_nodeB
      
  2. Remove HA catalog table's data, restore nodeB's database from nodeA's backup, and add data to HA catalog table.

    • Delete the HA catalog table, db_ha_apply_info's records.

      Delete all records of db_ha_apply_info of nodeB to initialize.

      [nodeB]$ csql --sysadm --write-on-standby -u dba -S testdb
      csql> DELETE FROM db_ha_apply_info;
      

      Delete db_ha_apply_info data for nodeB from nodeA and nodeC.

      [nodeA]$ csql --sysadm -u dba testdb@localhost
      csql> DELETE FROM db_ha_apply_info WHERE copied_log_path-='/home/cubrid/DB/databases/testdb_nodeB'
      
      [nodeC]$ csql --sysadm --write-on-standby -u dba testdb@localhost
      csql> DELETE FROM db_ha_apply_info WHERE copied_log_path-='/home/cubrid/DB/databases/testdb_nodeB'
      
    • Backup a database from nodeA.

      [nodeA]$ cd $CUBRID_DATABASES/testdb/log
      [nodeA]$ cubrid backupdb --sleep-msecs=10 -C -o output.txt testdb@localhost
      
    • Copy backup files to nodeB.

      [nodeA]$
      [nodeA]$ scp testdb_bk* cubrid_usr@nodeB:$CUBRID_DATABASES/testdb/log
      

      Note

      scp command's -l option is an option to control the amount of copying file; when you copy files between nodes, use this properly as considering I/O overhead. The unit is Kbits. 131072 is 16MB.

    • Restore the database into nodeB.

      At this time, the volume path of the master node must be identical to that of the slave node.

      [nodeB]$ cubrid restoredb -B $CUBRID_DATABASES/testdb/log testdb
      
    • Add a replication information record for nodeA to nodeB's db_ha_apply_info.

      Get an update information of db_ha_apply_info from output.txt file, which has backup result messages in nodeA. output.txt is saved at the directory on which a user ran "cubrid backupdb" command.

      [nodeA]$ vi $CUBRID_DATABASES/testdb/log/output.txt
      
      [ Database(testdb) Full Backup start ]
      
      - num-threads: 2
      
      - compression method: NONE
      
      - sleep 10 millisecond per 1M read.
      
      - backup start time: Fri Mar 20 18:18:53 2015
      
      - number of permanent volumes: 2
      
      - HA apply info: testdb 1426495463 12922 16192
      
      - backup progress status
      
      ...
      

      Make the below script and run. At "HA apply info" on the above output, put the first number, 1426495463 into $db_creation, the second number, 12922 into $pageid, and the third number, 16192 into $offset; put testdb into db_name, the database name and nodeA into master_host, the master node's host name.

      [nodeB]$ vi update.sh
      
      #!/bin/sh
      
      db_creation=1426495463
      page_id=12922
      offset=16192
      db_name=testdb
      master_host=nodeA
      
      repl_log_home_abs=$CUBRID_DATABASES
      
      repl_log_path=$repl_log_home_abs/${db_name}_${master_host}
      
      local_db_creation=`awk 'BEGIN { print strftime("%m/%d/%Y %H:%M:%S", $db_creation) }'`
          csql_cmd="\
          INSERT INTO \
                  db_ha_apply_info \
          VALUES \
          ( \
                  '$db_name', \
                  datetime '$local_db_creation', \
                  '$repl_log_path', \
                  $page_id, $offset, \
                  $page_id, $offset, \
                  $page_id, $offset, \
                  $page_id, $offset, \
                  $page_id, $offset, \
                  $page_id, $offset, \
                  NULL, \
                  NULL, \
                  NULL, \
                  0, \
                  0, \
                  0, \
                  0, \
                  0, \
                  0, \
                  0, \
                  NULL \
          )"
      
      # Insert nodeA's HA info.
      csql --sysadm -u dba -c "$csql_cmd" -S testdb
      
      [nodeB]$ sh update.sh
      

      Check if the data is successfully inserted.

      [nodeB]$ csql -u dba -S testdb
      
      csql> ;line on
      csql> SELECT * FROM db_ha_apply_info;
      
  3. Copy nodeA's active log into nodeB

    In nodeA's active log, there exists a number information of the archive log which is recently created. This information is needed for archive logs, which has been created after the time in which the active log had been copied, to be automatically copied by copylogdb process after the start of HA service of nodeC; therefore, the user just needs to manually copy archive logs which has been created before copying an active log.

    • Start cub_master which manages HA connection in nodeB.

      [nodeB]$ cub_master
      
    • Start copylogdb process for nodeA on nodeB.

      [nodeB]$ cubrid heartbeat copylogdb start testdb nodeA
      
    • Check if an active log of nodeA is copied.

      To copy the current active log means to obtain the number information of the last archive log. Archive logs after this time are automatically copied after the process [5. Start HA server in nodeB].

      [nodeB]$ cd $CUBRID_DATABASES/testdb_nodeA
      [nodeB]$ ls
      testdb_lgar_t  testdb_lgat  testdb_lgat__lock
      
    • Stop copylogdb process for nodeA on nodeB.

      [nodeB]$ cubrid heartbeat copylogdb stop testdb nodeA
      
    • Stopo nodeB's cub_master.

      [nodeB]$ cubrid service stop
      
  4. Copy required log files after restoring a database into nodeB

    • Copy all archive logs of nodeA into nodeB.

      [nodeB]$ cd $CUBRID_DATABASES/testdb_nodeA
      [nodeB]$ scp -l 131072 cubrid@nodeA:$CUBRID_DATABASES/testdb/log/testdb_lgar0* .
      

      In this process, please note that all replicated archive logs which are required for replication should exist.

      Note

      scp command's -l option is an option to control the amount of copying file; when you copy files between nodes, use this properly as considering I/O overhead. The unit is Kbits. 131072 is 16MB.

      Note

      Copy files of which the names end with a number. Here, we copied with "testdb_lgar0*" because numbers of names of all replication log files are started with 0.

      Note

      When required logs are already deleted

      Archive logs which are created between backup time and active log creation time can be deleted if the value of log_max_archives is not large enough; in this case, an error can occur when running the below process, [5. Start HA service on nodeB ...].

      When an error occurs, enlarge the value of log_max_archives enough and proceed again backup-and-restore from the beginning.

  5. Start HA service on nodeB; restart copylogdb and applylogdb processes on nodeA and nodeC

    [nodeB]$ cubrid heartbeat start
    
    [nodeA]$ cubrid heartbeat applylogdb start testdb nodeB
    [nodeA]$ cubrid heartbeat copylogdb start testdb nodeB
    
    [nodeC]$ cubrid heartbeat applylogdb start testdb nodeB
    [nodeC]$ cubrid heartbeat copylogdb start testdb nodeB
    

Detection of Replication Mismatch

How to Detect Replication Mismatch

Replication mismatch between replication nodes, indicating that data of the master node and the slave node is not identical, can be detected to some degree by the following process. You can also use checksumdb utility to detect a replication inconsistency. However, please note that there is no more accurate way to detect a replication mismatch than by directly comparing the data of the master node to the data of the slave node. If it is determined that there has been a replication mismatch, you should rebuild the database of the master node to the slave node (see Rebuilding Replication Script.)

  • Execute cubrid statdump command and check Time_ha_replication_delay. When this value is bigger, replication latency can be larger; the bigger latency time shows the possibility of the larger replication mismatch.

  • On the slave node, execute cubrid applyinfo to check the "Fail count" value. If the "Fail count" is 0, it can be determined that no transaction has failed in replication (see applyinfo.)

    [nodeB]$ cubrid applyinfo -L /home/cubrid/DB/testdb_nodeA -r nodeA -a testdb
    
     *** Applied Info. ***
    Committed page                 : 1913 | 2904
    Insert count                   : 645
    Update count                   : 0
    Delete count                   : 0
    Schema count                   : 60
    Commit count                   : 15
    Fail count                     : 0
    ...
    
  • To check whether copying replication logs has been delayed or not on the slave node, execute cubrid applyinfo and compare the "Append LSA" value of "Copied Active Info." to the "Append LSA" value of "Active Info.". If there is a big difference between the two values, it means that delay has occurred while copying the replication logs to the slave node (see applyinfo.)

    [nodeB]$ cubrid applyinfo -L /home/cubrid/DB/testdb_nodeA -r nodeA -a testdb
    
    ...
    
     *** Copied Active Info. ***
    DB name                        : testdb
    DB creation time               : 11:28:00.000 AM 12/17/2010  (1292552880)
    EOF LSA                        : 1913 | 2976
    Append LSA                     : 1913 | 2976
    HA server state                : active
    
     ***  Active Info. ***
    DB name                        : testdb
    DB creation time               : 11:28:00.000 AM 12/17/2010  (1292552880)
    EOF LSA                        : 1913 | 2976
    Append LSA                     : 1913 | 2976
    HA server state                : active
    
  • If a delay seems to occur when copying the replication logs, check whether the network line speed is slow, whether there is sufficient free disk space, disk I/O is normal, etc.

  • To check the delay in applying the replication log in the slave node, execute cubrid applyinfo and compare the "Committed page" value of "Applied Info." to the "EOF LSA" value of "Copied Active Info.". If there is a big difference between the two values, it means that a delay has occurred while applying the replication logs to the slave database (see applyinfo.)

    [nodeB]$ cubrid applyinfo -L /home/cubrid/DB/testdb_nodeA -r nodeA -a testdb
    
     *** Applied Info. ***
    Committed page                 : 1913 | 2904
    Insert count                   : 645
    Update count                   : 0
    Delete count                   : 0
    Schema count                   : 60
    Commit count                   : 15
    Fail count                     : 0
    
     *** Copied Active Info. ***
    DB name                        : testdb
    DB creation time               : 11:28:00.000 AM 12/17/2010  (1292552880)
    EOF LSA                        : 1913 | 2976
    Append LSA                     : 1913 | 2976
    HA server state                : active
    ...
    
  • If the delay in applying the replication logs is too long, it may be due to a transaction with a long execution time. If the transaction is performed normally, a delay in applying the replication logs may normally occur. To determine whether it is normal or abnormal, continuously execute cubrid applyinfo and check whether applylogdb continuously applies replication logs to the slave node or not.

  • Check the error log message created by the copylogdb process and the applylogdb process (see the error message).

  • Compare the number of records on the master database table to that on the slave database table.

checksumdb

checksumdb provides a simple way to check replication integrity. Basically, it divides each table from a master node into fixed-size chunks and then calculates CRC32 values. The calculation itself, not the calculated value, is then replicated through CUBRID HA. Consequently, by comparing CRC32 values calculated on master and slave nodes, checksumdb can report the replication integrity. Note that checksumdb might affect master's performance even though it is designed to minimize the performance degradation.

cubrid checksumdb [options] <database-name>@<hostname>
  • <hostname> : When you initiates checksum calculation, you need to specify the hostname of a master node. When you need to get the result after the calculation is completed, specify the hostname of a node you want to check.
-c, --chunk-size=NUMBER

You can specify the number of rows to select for each CRC32 calculation. (default: 500 rows, minimum: 100 rows)

-s, --sleep=NUMBER

checksumdb sleeps the specified amount of time after calculating each chunk (default: 100 ms)

-i, --include-class-file=FILE

You can specify tables to check the replication mismatch by specifying the -i FILE option. If it is not specified, entire tables will be checked. Empty string, tab, carriage return and comma are separators among table names in the file.

-e, --exclude-class-file=FILE

You can specify tables to exclude from checking the replication mismatch by specifying the -e FILE option. Note that either -i or -e can be used, not both.

-t, --timeout=NUMBER

You can specify a calculation timeout with this option. (default: 1000 ms) If the timeout is reached, the calculation will be cancelled and will be resumed after a short period of time.

-n, --table-name=STRING

You can specify a table name to save checksum results. (default: db_ha_checksum)

-r, --report-only

After checksum calculation is completed, you can get a report with this option.

--resume

When checksum calculation is aborted, you can resume the calculation using this option.

--schema-only

When this option is given, checksumdb does not calculate CRC32 but only check schema of each table

--cont-on-error

Without this option, checksumdb halts on errors.

The following example shows how to start checksumdb

cubrid checksumdb -c 100 -s 10 testdb@master

When no replication mismatch found,

$ cubrid checksumdb -r testdb@slave
================================================================
 target DB: testdb@slave (state: standby)
 report time: 2016-01-14 16:33:30
 checksum table name: db_ha_checksum, db_ha_checksum_schema
================================================================

------------------------
 different table schema
------------------------
NONE

----------------------------------------------------------------
table name  diff chunk id   chunk lower bound
----------------------------------------------------------------
NONE

--------------------------------------------------------------------------------------
table name  total # of chunks       # of diff chunks        total/avg/min/max time
--------------------------------------------------------------------------------------
t1              7                       0                       88 / 12 / 5 / 14 (ms)
t2              7                       0                       96 / 13 / 11 / 15 (ms)

When there is a replication mismatch in table t1,

$ cubrid checksumdb -r testdb@slave
================================================================
 target DB: testdb@slave (state: standby)
 report time: 2016-01-14 16:35:57
 checksum table name: db_ha_checksum, db_ha_checksum_schema
================================================================

------------------------
 different table schema
------------------------
NONE

----------------------------------------------------------------
table name  diff chunk id   chunk lower bound
----------------------------------------------------------------
t1              0               (id>=1)
t1              1               (id>=100)
t1              4               (id>=397)

--------------------------------------------------------------------------------------
table name  total # of chunks       # of diff chunks        total/avg/min/max time
--------------------------------------------------------------------------------------
t1              7                       3                       86 / 12 / 5 / 14 (ms)
t2              7                       0                       93 / 13 / 11 / 15 (ms)

When there is a schema mismatch in table t1,

$ cubrid checksumdb -r testdb@slave
================================================================
 target DB: testdb@slave (state: standby)
 report time: 2016-01-14 16:40:56
 checksum table name: db_ha_checksum, db_ha_checksum_schema
================================================================

------------------------
 different table schema
------------------------
<table name>
t1
<current schema - collected at 04:40:53.947 PM 01/14/2016>
CREATE TABLE [t1] ([id] INTEGER NOT NULL, [col1] CHARACTER VARYING(20), [col2] INTEGER, [col3] DATETIME, [col4] INTEGER,  CONSTRAINT [pk_t1_id] PRIMARY KEY  ([id])) COLLATE iso88591_bin
<schema from master>
CREATE TABLE [t1] ([id] INTEGER NOT NULL, [col1] CHARACTER VARYING(20), [col2] INTEGER, [col3] DATETIME,  CONSTRAINT [pk_t1_id] PRIMARY KEY  ([id])) COLLATE iso88591_bin

* Due to schema inconsistency, the checksum difference of the above table(s) may not be reported.
----------------------------------------------------------------
table name  diff chunk id   chunk lower bound
----------------------------------------------------------------
NONE

--------------------------------------------------------------------------------------
table name  total # of chunks       # of diff chunks        total/avg/min/max time
--------------------------------------------------------------------------------------
t1              7                       0                       95 / 13 / 11 / 16 (ms)
t2              7                       0                       94 / 13 / 11 / 15 (ms)
HA Error Messages

The following are error messages about the errors which can be reasons for the replication mismatch.

CAS process(cub_cas)

Error messages in CAS process are written to $CUBRID/log/broker/error_log/<broker_name>_<app_server_num>.err. The following table shows connection error messages in the HA environment.

Error messages for handshaking between a broker and a DB server

Error Code Error message Severity Description Solution
-1139 Handshake error (peer host ?): incompatible read/write mode. (client: ?, server: ?) error ACCESS_MODE of broker and the status of server (active/standby) is not the same (see Broker Mode).  
-1140 Handshake error (peer host ?): HA replication delayed. error Replication is delayed in the server which set ha_delay_limit.  
-1141 Handshake error (peer host ?): replica-only client to non-replica server. error A broker(CAS) which can access only a replica attempts to connect to the server which is not a replica(see Broker Mode).  
-1142 Handshake error (peer host ?): remote access to server not allowed. error It attempts to connect to a server with HA maintenance mode(see Servers).  
-1143 Handshake error (peer host ?): unidentified server version. error Server version is unidentified.  

Connection Error Messages

Error Code Error message Severity Description Solution
-353 Cannot make connection to master server on host ?. error cub_master process went down.  
-1144 Timed out attempting to connect to ?. (timeout: ? sec(s)) error The machine went down.  
Replication Log Copy Process(copylogdb)

The error messages from the replication log copy process are stored in $CUBRID/log/<db-name>@<remote-node-name>_copylogdb.err. The severity levels of error messages found in the replication log copy process are as follows: fatal, error, and notification. The default level is error. Therefore, to record notification error messages, it is necessary to change the value of error_log_level in the cubrid.conf file. For details, see Error Message-Related Parameters.

Initialization Error Messages

The error messages that can be found in initialization stage of replication log copy process are as follows:

Error Code Error Message Severity Description Solution
-10 Cannot mount the disk volume ?. error Fails to open a replication log file. Check if replication logs exist. For the location of replication logs, see Default Environment Configuration.
-78 Internal error: an I/O error occurred while reading logical log page ? (physical page ?) of ? fatal Fails to read a replication log. Check the replication log by using the cubrid applyinfo utility.
-81 Internal error: logical log page ? may be corrupted. fatal A replication log page error, in which the replication log copy process has been copied from the connected database server process. Check the error log of the database server process to which the replication log copy process is connected. This error log can be found in $CUBRID/log/server.
-1039 log writer: log writer has been started. mode: ? error The replication log copy process has been successfully initialized and started. No action is required because this error message is recorded to display the start information of the replication log copy process. Ignore any error messages which are displayed between the start of replication log copy process and output of this error message since there is a possibility that an error message is shown up even in normal situation.

Replication Log Request and Reception Error Messages

The replication log copy process requests a replication log from the connected database server and receives the corresponding replication log. Error messages that can be found in this stage are as follows:

Error Code Error Message Severity Description Solution
-89 Log ? is not included in the given database. error The previously replicated log and the log to be replication do not match. Check information of the database server/host to which the replication log copy process is connected. If you need to change the database server/host information, reinitialize it by deleting the existing replication log and then restarting.
-186 Data receiver error from the server error Incorrect information has been received from the database server to which the replication log copy process is connected. It will be internally recovered.
-199 The server is not responding. error The connection to the database server has been terminated. It will be internally recovered.

Replication Log Write Error Messages

The replication log copy process copies the replication log that was received from the connected database server process to the location (ha_copy_log_base) specified in the cubrid_ha.conf file. Error messages that can be found in this stage are as follows:

Error Code Error Message Severity Description Solution
-10 Cannot mount the disk volume ?. error Fails to open a replication log file. Check if replication logs exist.
-79 Internal error: an I/O error occurred while writing logical log page ? (physical page ?) of ?. fatal Fails to write a replication log. It will be internally recovered.
-80 An error occurred due to insufficient space in operating system device while writing logical log page ?(physical page ?) of ?. Up to ? bytes in size are allowed. fatal Fails to write a replication log due to insufficient file system space. Check if there is sufficient space left in the disk partition.

Replication Log Archive Error Messages

The replication log copy process periodically archives the replication logs that have been received from the connected database server process. Error messages that can be found in this stage are as follows:

Error Code Error Message Severity Description Solution
-78 Internal error: an I/O error occurred while reading logical log page ? (physical page ?) of ?. fatal Fails to read a replication log during archiving. Check the replication log by using the cubrid applyinfo utility.
-79 Internal error: an I/O error occurred while writing logical log page ? (physical page ?) of ?. fatal Fails to write an archive log. It will be internally recovered.
-81 Internal error: logical log page ? may be corrupted. fatal Found an error on the replication log during archiving. Check the replication log by using the cubrid applyinfo utility.
-98 Cannot create an archive log ? to archive pages from ? to ?. fatal Fails to create an archive log file. Check if there is sufficient space left in the disk partition.
-974 An archive log ? to archive pages from ? to ? has been created. notification Information on an archive log file No action is required because this error message is recorded to keep information on newly created archive.

Stop and Restart Error Messages

Error messages that can be found in this stage are as follows:

Error Code Error Message Severity Description Solution
-1037 log writer: log writer is terminated by signal. error The copylogdb process has been terminated by a specified signal. It will be internally recovered.
Replication Log Reflection Process(applylogdb)

The error messages from the replication log reflection process are stored in $CUBRID/log/db-name@local-node-name_applylogdb_db-name_remote-node-name.err. The severity levels of error message found in the replication log reflection process are as follow: fatal, error, and notification. The default level is error. Therefore, to record notification error messages, it is necessary to change the value of error_log_level in the cubrid.conf file. For details, see Error Message-Related Parameters.

Initialization Error Messages

The error messages that can be found in initialization stage of replication log reflection process are as follows:

Error Code Error Message Severity Description Solution
-10 Cannot mount the disk volume ?. error An applylogdb that is trying to reflect the same replication log is already running. Check if there is an applylogdb process that is trying to reflect the same replication log.
-1038 log applier: log applier has been started. required LSA: ?|?. last committed LSA: ?|?. last committed repl LSA: ?|? error It will be started normally after initialization of applylogdb succeeds. No action is required because this error is recorded to display the start information of the replication log reflection process.

Log Analysis Error Messages

The replication log reflection process reads, analyzes, and reflects the replications logs that have been copied by the replication log copy process. The error message that can be found in this stage are as follows:

Error Code Error Message Severity Description Solution
-13 An I/O error occurred while reading page ? in volume ?. error Fails to read a log page to be reflected. Check the replication log by using the cubrid applyinfo utility.
-17 Internal error: Trying to read page ? of the volume ? which has been already released. fatal Trying to read a log page that does not exist in the replication log. Check the replication log by using the cubrid applyinfo utility.
-81 Internal error: logical log page ? may be corrupted. fatal There is an inconsistency between an old log under replication reflection and the current log, or there is a replication log record error. Check the replication log by using the cubrid applyinfo utility.
-82 Cannot mount the disk volume/file ?. error No replication log file exists. Check if replication logs exist. Check the replication log by using the cubrid applyinfo utility.
-97 Internal error: unable to find log page ? in log archives. error No log page exists in the replication log. Check the replication log by using the cubrid applyinfo utility.
-897 Decompression failure error Fails to decompress the log record. Check the replication log by using the cubrid applyinfo utility.
-1028 log applier: Unexpected EOF log record exists in the Archive log. LSA: ?|?. error Incorrect log record exists in the archive log. Check the replication log by using the cubrid applyinfo utility.
-1029 log applier: Incorrect log page/offset. page HDR: ?|?, final: ?|?, append LSA: ?|?, EOF LSA: ?|?, ha file status: ?, is end-of-log: ?. error Incorrect log record exists. Check the replication log by using the cubrid applyinfo utility.
-1030 log applier: Incorrect log record. LSA: ?|?, forw LSA: ?|?, backw LSA: ?|?, Trid: ?, prev tran LSA: ?|?, type: ?. error Log record header error Check the replication log by using the cubrid applyinfo utility.

Replication Log Reflection Error Messages

The replication log reflection process reads, analyzes, and reflects the replication logs that have been copied by the replication log copy process. Error messages that can be found in this stage are as follows:

Error Code Error Message Severity Description Solution
-72 The transaction (index ?, ?@?|?) has been cancelled by system. error Fails to reflect replication due to deadlock, etc. It will be recovered internally.
-111 Your transaction has been cancelled due to server failure or a mode change. error Fails to reflect replication because the database server process in which replication is supposed to be reflected has been terminated or its mode has been changed. It will be recovered internally.
-191 Cannot connect to server ? on ?. error The connection to the database server process in which replication is supposed to be reflected has been terminated. It will be recovered internally.
-195 Server communication error: ?. error The connection to the database server process in which replication is supposed to be reflected has been terminated. It will be recovered internally.
-224 The database has not been resumed. error The connection to the database server process in which replication is supposed to be reflected has been terminated. It will be recovered internally.
-1027 log applier: Failed to change the reflection status from ? to ?. error Fails to change of replication reflection. It will be recovered internally.
-1031 log applier: Failed to reflect the Schema replication log. class: ?, schema: ?, internal error: ?. error Fails to reflect SCHEMA replication. Check the consistency of the replication. If it is inconsistent, reconfigure the HA replication.
-1032 log applier: Failed to reflect the Insert replication log. class: ?, key: ?, internal error: ?. error Fails to reflect INSERT replication. Check the consistency of the replication. If it is inconsistent, reconfigure the HA replication.
-1033 log applier: Failed to reflect the Update replication log. class: ?, key: ?, internal error: ?. error Fails to reflect UPDATE replication. Check the consistency of the replication. If it is inconsistent, reconfigure the HA replication.
-1034 log applier: Failed to reflect the Delete replication log. class: ?, key: ?, internal error: ?. error Fails to reflect DELETE replication. Check the consistency of the replication. If it is inconsistent, reconfigure the HA replication.
-1040 HA generic: ?. notification Changes the last record of the archive log or replication reflection status. No action is required because this error message is recorded to provide general information.

Stop and Restart Error Messages

The error messages that can be found in this stage are as follows:

Error Code Error Message Severity Description Solution
-1035 log applier: The memory size (? MB) of the log applier is larger than the maximum memory size (? MB), or is doubled the starting memory size (? MB) or more. required LSA: ?|?. last committed LSA: ?|?. error The replication log reflection process has been restarted due to reaching the maximum memory size limit. It will be recovered internally.
-1036 log applier: log applier is terminated by signal. error The replication log reflection process has been terminated by a specified signal. It will be recovered internally.

Rebuilding Replication Script

Replication rebuilding is required in CUBRID HA when data in the CUBRID HA group is inconsistent because of multiple failures in multiple-slave node structure, or because of a generic error. Rebuilding replications in CUBRID HA is perform done through a ha_make_slavedb.sh script. With the cubrid applyinfo utility, you can check the replication progress; however replication inconsistency is not detected. If you want to determine whether replication is inconsistent correctly, you must examine data of the master and slave nodes yourself.

When you rebuild only a slave because the slave is abnormal in the environment of master-slave composition, the process is as follows.

  1. Backup the master database.
  2. Restore the database from slave.
  3. Save backup time into the slave's HA meta table (db_ha_apply_info).
  4. Start HA service from slave. (cubrid hb start)

For rebuilding replications, the following environment must be the same in master, slave and replica nodes.

  • CUBRID version
  • Environmental variable ($CUBRID, $CUBRID_DATABASES, $LD_LIBRARY_PATH, $PATH)
  • The paths of database volume, log, and replication
  • Username and password of the Linux server
  • HA-related parameters except for ha_mode and ha_copy_sync_mode, ha_ping_hosts

You can rebuild replication by running ha_make_slavedb.sh script only in these cases.

  • from-master-to-slave
  • from-slave-to-replica
  • from-replica-to-replica
  • from-replica-to-slave

For the other cases, you should build manually. For the manual building scenarios, see Building Replication.

If the case is not for rebuilding but for newly building, configure cubrid.conf, cubrid_ha.conf, and databases.txt files as the same with master's.

In the below description, first, we will look over the cases to use ha_make_slavedb.sh script, which is used to rebuilding replication.

As a reference, you cannot use ha_make_slavedb.sh script when you want to build multiple slave nodes.

ha_make_slavedb.sh Script

To rebuild replications, use the ha_make_slavedb.sh script. This script is located in $CUBRID/share/scripts/ha. Before rebuilding replications, the following items must be configured for the environment of the user. This script is supported since the version 2008 R2.2 Patch 9 and its configuration is different from 2008 R4.1 Patch 2 or earlier. This document describes it in CUBRID 2008 R4.1 Patch 2 or later.

  • target_host : The host name of the source node (master node in general) for rebuilding replication. It should be registered in /etc/hosts. A slave node can rebuild replication by using the master node or the replica node as the source. A replica node can rebuild replication by using the slave node or another replica node as the source.
  • repl_log_home : Specifies the home directory of the replication log of the master node. It is usually the same as $CUBRID_DATABASES. You must enter an absolute path and should not use a symbolic link. You also cannot use a slash (/) after the path.

The following are optional items:

  • db_name : Specifies the name of the database to be replicated. If not specified, the first name that appears in ha_db_list in $CUBRID/conf/cubrid_ha.conf is used.
  • backup_dest_path : Specifies the path in which the backup volume is created when executing backupdb in source node for rebuilding replication.
  • backup_option : Specifies necessary options when executing backupdb in the source node in which replication will be rebuilt.
  • restore_option : Specifies necessary options when executing restoredb in the target node in which replication will be rebuilt.
  • scp_option : Specifies the scp option which enables backup of source node in which replication is rebuilt to copy into the target node. The default option is -l 131072, which does not impose an overload on network (limits the transfer rate to 16 MB).

Once the script has been configured, execute the ha_make_slavedb.sh script in the target node in which replication will be rebuilt. When the script is executed, rebuilding replication happens in a number of phases. To move to the next stage, the user must enter an appropriate value. The following are the descriptions of available values.

  • yes : Keeps going.
  • no : Does not move forward with any stages from now on.
  • skip: Skips to the next stage. This input value is used to ignore a stage that has not necessarily been executed when retrying the script after it has failed.

Warning

  • ha_make_slavedb.sh script executes the connection command into the remote node by expect and ssh; therefore, expect command should be installed('yum install expect' in root account) and ssh should be possible in remote connection.

Note

  • Backup volumes are required for rebuilding replication

    To replicate, you must copy the physical image of the database volume in the target node to the database of the node to be replicated. However, cubrid unloaddb backs up only logical images so replication using cubrid unloaddb and cubrid loaddb is unavailable. Because cubrid backupdb backs up physical images, replication is possible by using this utility. The ha_make_slavedb.sh script performs replication by using cubrid backupdb.

  • Online-backup of a source node and restoration of a rebuilding node during rebuilding replication.

    ha_make_slavedb.sh script executes online backup about a source node during DB operation, and restore to the being-rebuilt node. To apply added transactions after backup to the being-rebuilt node, ha_make_slavedb.sh script use the archive logs of "master" node by copying(in all cases, archive logs of "master" are used; all cases include how to build slave from master, how to build replica from slave and how to build replica from replica).

    Therefore, so as not to remove archive logs which have been added to the source node during the execution of the online backup, there is a need to properly set force_remove_log_max_archives and log_max_archives in cubrid.conf from the master node. For details, see the below building examples.

  • Error while executing the rebuilding replication script

    The rebuilding replication script is not automatically rolled back to its previous stage even when an error occurs during the execution. This is because the slave node cannot provide normal service before rebuilding replication script is executed. To return to the phase before rebuilding replication script is executed, you must back up the existing replication logs and db_ha_apply_info information which is internal catalog of the master and slave nodes before building replication is executed.

API Reference

This chapter covers the following API:

JDBC Driver

JDBC Overview

CUBRID JDBC driver (cubrid_jdbc.jar) implements an interface to enable access from applications in Java to CUBRID database server. CUBRID JDBC driver is installed in the <directory where CUBRID is installed>/jdbc directory. The driver has been developed based on the JDBC 2.0 specification and the default driver provided is complied with JDK 1.6.

To download JDBC driver or get the latest information, please visit http://www.cubrid.org/wiki_apis/entry/cubrid-jdbc-driver.

Verifying CUBRID JDBC Driver Version

You can verify the version of JDBC driver as follows:

% jar -tf cubrid_jdbc.jar
META-INF/
META-INF/MANIFEST.MF
cubrid/
cubrid/jdbc/
cubrid/jdbc/driver/
cubrid/jdbc/jci/
cubrid/sql/
cubrid/jdbc/driver/CUBRIDBlob.class
...
CUBRID-JDBC-8.3.1.1032

Registering CUBRID JDBC Driver

Use the Class.forName (driver-class-name) method to register CUBRID JDBC driver. The following example shows how to load the cubrid.jdbc.driver.CUBRIDDriver class to register CUBRID JDBC driver.

import java.sql.*;
import cubrid.jdbc.driver.*;

public class LoadDriver {
   public static void main(String[] Args) {
       try {
           Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
       } catch (Exception e) {
           System.err.println("Unable to load driver.");
           e.printStackTrace();
       }
       ...
Installing and Configuring JDBC

Requirements

  • JDK 1.6 or later
  • CUBRID 2008 R2.0 (8.2.0) or later
  • CUBRID JDBC driver 2008 R1.0 or later

Installing Java and Configuring Environment

You must already have Java installed and the JAVA_HOME environment variable configured in your system. You can download Java from the Developer Resources for Java Technology website ( http://java.sun.com ). For more information, please see Environment Configuration for Java Stored Function/Procedure.

Configuring the environment variables for Windows

After installing Java, right-click [My Computer] and click [System Properties]. In the [Advanced] tab, click [Environment Variables]. The [Environment Variables] dialog will appear.

In the [System Variables], click [New]. Enter JAVA_HOME and Java installation path such as C:Program FilesJavajdk1.6.0_13 and then click [OK].

_images/image51.png

Of system variables, select Path and then click [Edit]. Add %JAVA_HOME%\bin in the [Variable value] and then click [OK].

_images/image52.png

You can also configure JAVA_HOME and PATH values in the shell instead of using the way described above.

set JAVA_HOME= C:\Program Files\Java\jdk1.6.0_13
set PATH=%PATH%;%JAVA_HOME%\bin

Configuring the environment variables for Linux

Specify the directory path where Java is installed (example: /usr/java/jdk1.6.0_13) as a JAVA_HOME environment variable and add $JAVA_HOME/bin to the PATH environment variable.

export JAVA_HOME=/usr/java/jdk1.6.0_16     #bash
export PATH=$JAVA_HOME/bin:$PATH           #bash

setenv JAVA_HOME /usr/java/jdk1.6.0_16     #csh
set path = ($JAVA_HOME/bin $path)          #csh

Configuring JDBC Driver

To use JDBC, you should specify the path where the CUBRID JDBC driver is located in the CLASSPATH environment variable.

The CUBRID JDBC driver (cubrid_jdbc.jar) is located in the jdbc directory under the directory of CUBRID installation.

_images/image53.png

Configuring the CLASSPATH environment variable for Windows

set CLASSPATH=C:\CUBRID\jdbc\cubrid_jdbc.jar:.

Configuring the CLASSPATH environment variable for Linux

export CLASSPATH=$HOME/CUBRID/jdbc/cubrid_jdbc.jar:.

Warning

If a general CUBRID JDBC driver has been installed in the same library directory ($JAVA_HOME/jre/lib/ext) where the JRE is installed, it may be loaded ahead of the server-side JDBC driver used by the Java stored procedure, which causing it to malfunction. In a Java stored procedure environment, make sure not to install a general CUBRID JDBC driver in the directory where the JRE is installed ($JAVA_HOME/jre/lib/ext).

JDBC Programming
Configuration Connection

The DriverManager is an interface for managing the JDBC driver. It is used to select a driver and create new database connection. If CUBRID JDBC driver is registered, you can connect a database by calling the DriverManager.getConnection (db-url, user-id, password) method.

The getConnection method returns the Connection object and it is used to execute queries and commands, and commit and roll back transactions. The syntax below shows the db-url argument for configuring connection.

jdbc:cubrid:<host>:<port>:<db-name>:[user-id]:[password]:[?<property> [& <property>]]

<host> ::=
hostname | ip_address

<property> ::= altHosts=<alternative_hosts>
             | rcTime=<second>
             | loadBalance=<bool_type>
             | connectTimeout=<second>
             | queryTimeout=<second>
             | charSet=<character_set>
             | zeroDateTimeBehavior=<behavior_type>
             | logFile=<file_name>
             | logOnException=<bool_type>
             | logSlowQueries=<bool_type>&slowQueryThresholdMillis=<millisecond>
             | useLazyConnection=<bool_type>

    <alternative_hosts> ::=
    <standby_broker1_host>:<port> [,<standby_broker2_host>:<port>]
    <behavior_type> ::= exception | round | convertToNull
    <bool_type> ::= true | false
  • host: IP address or host name where the CUBRID broker is running

  • port: The CUBRID broker port number (default value: 33,000)

  • db-name: The name of the database to connect

  • user-id: The user ID which is connected to a database. There are two types of users in a database by default: dba and public. If this is NULL, it becomes <db_user> in db-url. If this is an empty string (""), it becomes a public user.

  • password: The password of a user who is to be connected to a database. If this is NULL, <db_password> in db-url is used. If this is an empty string (""), DB password becomes an empty string. You cannot include ':' in the password of the db-url string.

  • <property>

    • altHosts: The host IP addresses and connection ports of one or more stand by brokers which will perform failover in the HA environment.

      Note

      Even if there are RW and RO together in ACCESS_MODE* setting of brokers of main host and altHosts, application decides the target host to access without the relation for the setting of ACCESS_MODE. Therefore, you should define the main host and altHosts as considering ACCESS_MODE of target brokers.

    • rcTime: Interval time (in seconds) to try to connect active brokers during failover in the HA environment. See the below URL example.

    • loadBalance: If this value is true, the application tries to connect with main host and altHosts in random order(default value: false).

    • connectTimeout: Timeout value (in seconds) for database connection. The default value is 30 seconds. If this value is 0, it means infinite waiting. This value is also applied when internal reconnection occurs after the initial connection. The DriverManger.setLoginTimeout () method can be used to configure it; however, the value configured in this method will be ignored if a value is configured in the connection URL.

    • queryTimeout: Timeout value (in seconds) for query execution (default value: 0, infinite). The maximum value is 2,000,000. This value can be changed by the DriverManger.setQueryTimeout () method.

      Note

      When you run executeBatch() method, the query timeout is applied in one method call, not in one query.

    • charSet: The character set of a database to be connected

    • zeroDateTimeBehavior: The property used to determine the way to handle an output value; because JDBC does not allow a value having zero for both date and time regardless of date and time in the object with the java.sql.Date type. For information about the value having zero for both date and date, see Date/Time Types.

      The default operation is exception. The operation for each configuration is as follows:

      • exception: Default operation. It is handled as an SQLException exception.
      • round: Converts to the minimum value allowed for a type to be returned. Exceptionally, when the value's type is TIMESTAMP, this value is rounded as '1970-01-01 00:00:00'(GST). (yyyy-mm-dd hh24:mi:ss)
      • convertToNull: Converts to NULL.
    • logFile: The name of a log file for debugging (default value: cubrid_jdbc.log). If a path is not configured, it is stored the location where applications are running.

    • logOnException: Whether to log exception handling for debugging (default value: false)

    • logSlowQueries: Whether to log slow queries for debugging (default value: false)

      • slowQueryThresholdMillis: Timeout value (in milliseconds) of slow queries (default value: 60,000).
    • useLazyConnection: If this is true, it returns success without connecting to the broker when user requests the connection, and it connects to the broker after calling prepare or execute function(default: false). If this value is true, it can prevent from access delay or failure as many application clients restart simultaniously and create connection pools.

Example 1

--connection URL string when user name and password omitted

URL=jdbc:CUBRID:192.168.0.1:33000:demodb:public::

--connection URL string when zeroDateTimeBehavior property specified
URL=jdbc:CUBRID:127.0.0.1:33000:demodb:public::?zeroDateTimeBehavior=convertToNull

--connection URL string when charSet property specified

URL=jdbc:CUBRID:192.168.0.1:33000:demodb:public::?charSet=utf-8

--connection URL string when queryTimeout and charSet property specified

URL=jdbc:CUBRID:127.0.0.1:33000:demodb:public::?queryTimeout=1&charSet=utf-8

--connection URL string when a property(altHosts) specified for HA
URL=jdbc:CUBRID:192.168.0.1:33000:demodb:public::?altHosts=192.168.0.2:33000,192.168.0.3:33000

--connection URL string when properties(altHosts,rcTime, connectTimeout) specified for HA
URL=jdbc:CUBRID:192.168.0.1:33000:demodb:public::?altHosts=192.168.0.2:33000,192.168.0.3:33000&rcTime=600&connectTimeout=5

--connection URL string when properties(altHosts,rcTime, charSet) specified for HA
URL=jdbc:CUBRID:192.168.0.1:33000:demodb:public::?altHosts=192.168.0.2:33000,192.168.0.3:33000&rcTime=600&charSet=utf-8

Example 2

String url = "jdbc:cubrid:192.168.0.1:33000:demodb:public::";
String userid = "";
String password = "";

try {
   Connection conn =
           DriverManager.getConnection(url,userid,password);
   // Do something with the Connection

   ...

   } catch (SQLException e) {
       System.out.println("SQLException:" + e.getMessage());
       System.out.println("SQLState: " + e.getSQLState());
   }
   ...

Note

  • Because a colon (:) and a question mark are used as a separator in the URL string, it is not allowed to use them as parts of a password. To use them in a password, you must specify a user name (user-id) and a password (password) as a separate argument in the getConnection method.
  • The database connection in thread-based programming must be used independently each other.
  • The rollback method requesting transaction rollback will be ended after a server completes the rollback job.
  • In autocommit mode, the transaction is not committed if all results are not fetched after running the SELECT statement. Therefore, although in autocommit mode, you should end the transaction by executing COMMIT or ROLLBACK if some error occurs during fetching for the resultset.
Connecting with DataSource

DataSource is the concept to be introduced in JDBC 2.0 API extention; it supports connection pooling and distributed transaction. CUBRID supports only connection pooling and do not supports distributed transaction and JNDI.

CUBRIDDataSource is DataSource implemented in CUBRID.

Creating a DataSource Object

To create a DataSource object, call as follows.

CUBRIDDataSource ds = null;
ds = new CUBRIDDataSource();

Setting Connection Properties

Connection properties are used to configure connections between datasource and CUBRID DBMS. General properties are a DB name, a host name, a port number, a user name and a password.

To set or get the values of properties, use below methods which is implemented in cubrid.jdbc.driver.CUBRIDDataSource.

public PrintWriter getLogWriter();
public void setLogWriter(PrintWriter out);
public void setLoginTimeout(int seconds);
public int getLoginTimeout();
public String getDatabaseName();
public String getDatabaseName();
public String getDataSourceName();
public String getDescription();
public String getNetworkProtocol();
public String getPassword();
public int getPortNumber();
public int getPort();
public String getRoleName();
public String getServerName();
public String getUser();
public String getURL();
public String getUrl();
public void setDatabaseName(String dbName);
public void setDescription(String desc);
public void setNetworkProtocol(String netProtocol);
public void setPassword(String psswd);
public void setPortNumber(int p);
public void setPort(int p);
public void setRoleName(String rName);
public void setServerName(String svName);
public void setUser(String uName);
public void setUrl(String urlString);
public void setURL(String urlString);

Especially, use a setURL() method to set the property through a URL string. Regarding URL string, see Configuration Connection.

import cubrid.jdbc.driver.CUBRIDDataSource;
...
CUBRIDDataSource ds = null;
ds = new CUBRIDDataSource();
ds.setUrl("jdbc:cubrid:10.113.153.144:55300:demodb:::?charset=utf8&logSlowQueries=true&slowQueryThresholdMillis=1000&logTraceApi=true&logTraceNetwork=true");

Call getConnection method to get a connection object from DataSource.

Connection connection = null;
connection = ds.getConnection("dba", "");

CUBRIDConnectionPoolDataSource is an object which connection-pool datasource is implemented in CUBRID; it includes the methods of the same names with the methods of CUBRIDDataSource.

For detail examples, see Connecting to a DataSource Object in JDBC Sample Program.

Checking SQL LOG

The connection URL information can be printed out by calling cubrid.jdbc.driver.CUBRIDConnection.toString() method.

e.g.) cubrid.jdbc.driver.CUBRIDConnection(CAS ID : 1, PROCESS ID : 22922)

You can find SQL log of that CAS easily by CAS ID which is printed out.

For more details, see Checking SQL Log.

Checking Foreign Key Information

You can check foreign key information by using getImportedKeys, getExportedKeys, and getCrossReference methods of the DatabaseMetaData interface. The usage and example of each method are as follows:

getImportedKeys(String catalog, String schema, String table)

getExportedKeys(String catalog, String schema, String table)

getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable)
  • getImportedKeys method: Retrieves information of primary key columns which are referred by foreign key columns in a given table. The results are sorted by PKTABLE_NAME and KEY_SEQ.
  • getExportedKeys method: Retrieves information of all foreign key columns which refer to primary key columns in a given table. The results are sorted by FKTABLE_NAME and KEY_SEQ.
  • getCrossReference method: Retrieves information of primary key columns which are referred by foreign key columns in a given table. The results are sorted by PKTABLE_NAME and KEY_SEQ.

Return Value

When the methods above are called, the ResultSet consisting of 14 columns listed in the table below is returned.

Name Type Note
PKTABLE_CAT String null without exception
PKTABLE_SCHEM String null without exception
PKTABLE_NAME String The name of a primary key table
PKCOLUMN_NAME String The name of a primary key column
FKTABLE_CAT String null without exception
FKTABLE_SCHEM String null without exception
FKTABLE_NAME String The name of a foreign key table
FKCOLUMN_NAME String The name of a foreign key column
KEY_SEQ short Sequence of columns of foreign keys or primary keys (starting from 1)
UPDATE_RULE short The corresponding values to referring actions defined as to foreign keys when primary keys are updated. Cascade=0, Restrict=2, No action=3, Set null=4
DELETE_RULE short The corresponding value to referring actions defined as to foreign keys when primary keys are deleted. Cascade=0, Restrict=2, No action=3, Set null=4
FK_NAME String Foreign key name
PK_NAME String Primary key name
DEFERRABILITY short 6 without exception (DatabaseMetaData.importedKeyInitiallyImmediate)

Example

ResultSet rs = null;
DatabaseMetaData dbmd = conn.getMetaData();

System.out.println("\n===== Test getImportedKeys");
System.out.println("=====");
rs = dbmd.getImportedKeys(null, null, "pk_table");
Test.printFkInfo(rs);
rs.close();

System.out.println("\n===== Test getExportedKeys");
System.out.println("=====");
rs = dbmd.getExportedKeys(null, null, "fk_table");
Test.printFkInfo(rs);
rs.close();

System.out.println("\n===== Test getCrossReference");
System.out.println("=====");
rs = dbmd.getCrossReference(null, null, "pk_table", null, null, "fk_table");
Test.printFkInfo(rs);
rs.close();
Using Object Identifiers (OIDs) and Collections

In addition to the methods defined in the JDBC specification, CUBRID JDBC driver provides methods that handle OIDs and collections (set, multiset, and sequence).

To use these methods, you must import cubrid.sql.*; as well as the CUBRID JDBC driver classes which are imported by default. Furthermore, you should convert to not the ResultSet class, which is provided by the standard JDBC API) but the CUBRIDResultSet class to get result.

import cubrid.jdbc.driver.* ;
import cubrid.sql.* ;
...

CUBRIDResultSet urs = (CUBRIDResultSet) stmt.executeQuery(
    "SELECT city FROM location");

Warning

If extended API is used, transactions won't be automatically committed even though AUTOCOMMIT is set to TRUE. Therefore, you must explicitly commit transactions for open connections. The extended API of CUBRID is method that handle OIDs, collections, etc.

Using OIDs

You must follow the rules below when using OIDs.

  • To use CUBRIDOID, you must import cubrid.sql. * . (a)
  • You can get OIDs by specifying the class name in the SELECT statement. It can also be used together with other properties. (b)
  • ResultSet for queries must be received by CUBRIDResultSet. (c)
  • The method to get OIDs from CUBRIDResultSet is getOID (). (d)
  • You can get the value from OIDs by using the getValues () method and the result will be ResultSet. (e)
  • You can substitute OID with a value by using the setValues () method. (f)
  • When you use extended API, you must always execute commit () for connection. (g)

Example

import java.sql.*;
import cubrid.sql.*; //a
import cubrid.jdbc.driver.*;

/*
CREATE TABLE oid_test(
   id INTEGER,
   name VARCHAR(10),
   age INTEGER
);

INSERT INTO oid_test VALUES(1, 'Laura', 32);
INSERT INTO oid_test VALUES(2, 'Daniel', 39);
INSERT INTO oid_test VALUES(3, 'Stephen', 38);
*/

class OID_Sample
{
   public static void main (String args [])
   {
      // Making a connection
      String url= "jdbc:cubrid:localhost:33000:demodb:public::";
      String user = "dba";
      String passwd = "";

      // SQL statement to get OID values
      String sql = "SELECT oid_test from oid_test"; //b
      // columns of the table
      String[] attr = { "id", "name", "age" } ;


      // Declaring variables for Connection and Statement
      Connection con = null;
      Statement stmt = null;
      CUBRIDResultSet rs = null;
      ResultSetMetaData rsmd = null;

      try {
         Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
      } catch (ClassNotFoundException e) {
         throw new IllegalStateException("Unable to load Cubrid driver", e);
      }

      try {
         con = DriverManager.getConnection(url, user, passwd);
         stmt = con.createStatement();
         rs = (CUBRIDResultSet)stmt.executeQuery(sql); //c
         rsmd = rs.getMetaData();

         // Printing columns
         int numOfColumn = rsmd.getColumnCount();
         for (int i = 1; i <= numOfColumn; i++ ) {
            String ColumnName = rsmd.getColumnName(i);
            String JdbcType = rsmd.getColumnTypeName(i);
            System.out.print(ColumnName );
            System.out.print("("+ JdbcType + ")");
            System.out.print(" | ");
         }
         System.out.print("\n");

         // Printing rows
         CUBRIDResultSet rsoid = null;
         int k = 1;

         while (rs.next()) {
            CUBRIDOID oid = rs.getOID(1); //d
            System.out.print("OID");
            System.out.print(" | ");
            rsoid = (CUBRIDResultSet)oid.getValues(attr); //e

            while (rsoid.next()) {
               for( int j=1; j <= attr.length; j++ ) {
                  System.out.print(rsoid.getObject(j));
                  System.out.print(" | ");
               }
            }
            System.out.print("\n");

            // New values of the first row
            Object[] value = { 4, "Yu-ri", 19 };
            if (k == 1) oid.setValues(attr, value); //f

            k = 0;
         }
         con.commit(); //g

      } catch(CUBRIDException e) {
         e.printStackTrace();

      } catch(SQLException ex) {
         ex.printStackTrace();

      } finally {
         if(rs != null) try { rs.close(); } catch(SQLException e) {}
         if(stmt != null) try { stmt.close(); } catch(SQLException e) {}
         if(con != null) try { con.close(); } catch(SQLException e) {}
      }
   }
}
Using Collections

The line "a" in the example 1 is where data of collection types (SET, MULTISET, and LIST) is fetched from CUBRIDResultSet. The results are returned as array format. Note that this can be used only when data types of all elements defined in the collection types are same.

Example 1

import java.sql.*;
import java.lang.*;
import cubrid.sql.*;
import cubrid.jdbc.driver.*;

// create class collection_test(
// settest set(integer),
// multisettest multiset(integer),
// listtest list(Integer)
// );
//

// insert into collection_test values({1,2,3},{1,2,3},{1,2,3});
// insert into collection_test values({2,3,4},{2,3,4},{2,3,4});
// insert into collection_test values({3,4,5},{3,4,5},{3,4,5});

class Collection_Sample
{
   public static void main (String args [])
   {
       String url= "jdbc:cubrid:127.0.0.1:33000:demodb:public::";
       String user = "";
       String passwd = "";
       String sql = "select settest,multisettest,listtest from collection_test";
       try {
           Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
       } catch(Exception e){
           e.printStackTrace();
       }
       try {
           Connection con = DriverManager.getConnection(url,user,passwd);
           Statement stmt = con.createStatement();
           CUBRIDResultSet rs = (CUBRIDResultSet) stmt.executeQuery(sql);
           CUBRIDResultSetMetaData rsmd = (CUBRIDResultSetMetaData) rs.getMeta Data();
           int numbOfColumn = rsmd.getColumnCount();
           while (rs.next ()) {
               for (int j=1; j<=numbOfColumn; j++ ) {
                   Object[] reset = (Object[]) rs.getCollection(j); //a
                   for (int m=0 ; m < reset.length ; m++)
                       System.out.print(reset[m] +",");
                   System.out.print(" | ");
               }
               System.out.print("\n");
           }
           rs.close();
           stmt.close();
           con.close();
       } catch(SQLException e) {
           e.printStackTrace();
       }
   }
}

Example 2

import java.sql.*;
import java.io.*;
import java.lang.*;
import cubrid.sql.*;
import cubrid.jdbc.driver.*;

// create class collection_test(
// settest set(integer),
// multisettest multiset(integer),
// listtest list(Integer)
// );
//
// insert into collection_test values({1,2,3},{1,2,3},{1,2,3});
// insert into collection_test values({2,3,4},{2,3,4},{2,3,4});
// insert into collection_test values({3,4,5},{3,4,5},{3,4,5});

class SetOP_Sample
{
   public static void main (String args [])
   {
       String url = "jdbc:cubrid:127.0.0.1:33000:demodb:public::";
       String user = "";
       String passwd = "";
       String sql = "select collection_test from collection_test";
       try {
           Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
       } catch(Exception e){
           e.printStackTrace();
       }
       try {
           CUBRIDConnection con =(CUBRIDConnection)
           DriverManager.getConnection(url,user,passwd);
           Statement stmt = con.createStatement();
           CUBRIDResultSet rs = (CUBRIDResultSet)stmt.executeQuery(sql);
           while (rs.next ()) {
               CUBRIDOID oid = rs.getOID(1);
               oid.addToSet("settest",new Integer(10));
               oid.addToSet("multisettest",new Integer(20));
               oid.addToSequence("listtest",1,new Integer(30));
               oid.addToSequence("listtest",100,new Integer(100));
               oid.putIntoSequence("listtest",99,new Integer(99));
               oid.removeFromSet("settest",new Integer(1));
               oid.removeFromSet("multisettest",new Integer(2));
               oid.removeFromSequence("listtest",99);
               oid.removeFromSequence("listtest",1);
           }
           con.commit();
           rs.close();
           stmt.close();
           con.close();
       } catch(SQLException e) {
           e.printStackTrace();
       }
   }
}
Getting Auto Increment Column Value

Auto increment (AUTO_INCREMENT) is a column-related feature that increments the numeric value of each row. For more information, see Column Definition. It can be defined only for numeric domains (SMALLINT, INTEGER, DECIMAL (p, 0), and NUMERIC (p, 0)).

Auto increment is recognized as automatically created keys in the JDBC programs. To retrieve the key, you need to specify the time to insert a row from which the automatically created key value is to be retrieved. To perform it, you must set the flag by calling Connection.prepareStatement and Statement.execute methods. In this case, the command executed should be the INSERT statement or INSERT within SELECT statement. For other commands, the JDBC driver ignores the flag-setting parameter.

Steps

  • Use one of the following to indicate whether or not to return keys created automatically. The following method forms are used for tables of the database server that supports the auto increment columns. Each method form can be applied only to a single-row INSERT statement.

    • Write the PreparedStatement object as shown below.

      Connection.prepareStatement(sql statement, Statement.RETURN_GENERATED_KEYS);
      
    • To insert a row by using the Statement.execute method, use the Statement.execute method as shown below.

      Statement.execute(sql statement, Statement.RETURN_GENERATED_KEYS);
      
  • Get the ResultSet object containing automatically created key values by calling the PreparedStatement.getGeneratedKeys or Statement.getGeneratedKeys method. Note that the data type of the automatically created keys in ResultSet is DECIMAL regardless of the data type of the given domain.

Example

The following example shows how to create a table with auto increment, enter data into the table so that automatically created key values are entered into auto increment columns, and check whether the key values are successfully retrieved by using the Statement.getGeneratedKeys () method. Each step is explained in the comments for commands that correspond to the steps above.

import java.sql.*;
import java.math.*;
import cubrid.jdbc.driver.*;

Connection con;
Statement stmt;
ResultSet rs;
java.math.BigDecimal iDColVar;
...
stmt = con.createStatement();     // Create a Statement object

// Create table with identity column
stmt.executeUpdate(
    "CREATE TABLE EMP_PHONE (EMPNO CHAR(6), PHONENO CHAR(4), " +
    "IDENTCOL INTEGER AUTO_INCREMENT)");

stmt.execute(
    "INSERT INTO EMP_PHONE (EMPNO, PHONENO) " +
    "VALUES ('000010', '5555')",               // Insert a row  <Step 1>
    Statement.RETURN_GENERATED_KEYS);        // Indicate you want automatically


rs = stmt.getGeneratedKeys();    // generated keys

// Retrieve the automatically  <Step 2>
// generated key value in a ResultSet.
// Only one row is returned.
// Create ResultSet for query
while (rs.next()) {
    java.math.BigDecimal idColVar = rs.getBigDecimal(1);
    // Get automatically generated key value
    System.out.println("automatically generated key value = " + idColVar);
}

rs.close();                          // Close ResultSet
stmt.close();                        // Close Statement
Using BLOB/CLOB

The interface that handles LOB data in JDBC is implemented based on JDBC 4.0 specification. The constraints of the interface are as follows:

  • Only sequential write is supported when creating BLOB or CLOB object. Writing to arbitrary locations is not supported.

  • You cannot change BLOB or CLOB data by calling methods of BLOB or CLOB object fetched from ResultSet.

  • Blob.truncate, Clob.truncate, Blob.position, and Clob.position methods are supported.

  • You cannot bind the LOB data by calling PreparedStatement.setAsciiStream, PreparedStatement.setBinaryStream, and PreparedStatement.setCharacterStream methods for BLOB/CLOB type columns.

  • To use BLOB / CLOB type in the environment where JDBC 4.0 is not supported such as JDK versions 1.5 or earlier, you must do explicit type conversion for the conn object to CUBRIDConnection. See example below.

    //JDK 1.6 or higher
    
    import java.sql.*;
    
    Connection conn = DriverManager.getConnection(url, id, passwd);
    Blob blob = conn.createBlob();
    
    
    //JDK 1.5 or lower
    
    import java.sql.*;
    import cubrid.jdbc.driver.*;
    
    Connection conn = DriverManager.getConnection(url, id, passwd);
    Blob blob = ((CUBRIDConnection)conn).createBlob();
    

Storing LOB Data

You can bind the LOB type data in the following ways.

  • Create java.sql.Blob or java.sql.Clob object, store file content in the object, use setBlob () or setClob () of PreparedStatement (example 1).
  • Execute a query, get java.sql.Blob or java.sql.Clob object from the ResultSet object, and bind the object in PreparedStatement (example 2).

Example 1

Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
Connection conn = DriverManager.getConnection ("jdbc:cubrid:localhost:33000:image_db:user1:password1:", "", "");

PreparedStatement pstmt1 = conn.prepareStatement("INSERT INTO doc(image_id, doc_id, image) VALUES (?,?,?)");
pstmt1.setString(1, "image-21");
pstmt1.setString(2, "doc-21");

//Creating an empty file in the file system
Blob bImage = conn.createBlob();
byte[] bArray = new byte[256];
...

//Inserting data into the external file. Position is start with 1.
bImage.setBytes(1, bArray);
//Appending data into the external file
bImage.setBytes(257, bArray);
...

pstmt1.setBlob(3, bImage);
pstmt1.executeUpdate();
...

Example 2

Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
Connection conn = DriverManager.getConnection ("jdbc:cubrid:localhost:33000:image_db:user1:password1:", "", "");
conn.setAutoCommit(false);

PreparedStatement pstmt1 = conn.prepareStatement("SELECT image FROM doc WHERE image_id = ? ");
pstmt1.setString(1, "image-21");
ResultSet rs = pstmt1.executeQuery();

while (rs.next())
{
    Blob bImage = rs.getBlob(1);
    PreparedStatement pstmt2 = conn.prepareStatement("INSERT INTO doc(image_id, doc_id, image) VALUES (?,?,?)");
    pstmt2.setString(1, "image-22")
    pstmt2.setString(2, "doc-22")
    pstmt2.setBlob(3, bImage);
    pstmt2.executeUpdate();
    pstmt2.close();
}

pstmt1.close();
conn.commit();
conn.setAutoCommit(true);
conn.close();
...

Getting LOB Data

You can get the LOB type data in the following ways.

  • Get data directly from ResultSet by using getBytes () or getString () method (example 1).
  • Get the java.sql.Blob or java.sql.Clob object from ResultSet by calling getBlob () or getClob () method and get data for this object by using the getBytes () or getSubString () method (example 2).

Example 1

Connection conn = DriverManager.getConnection ("jdbc:cubrid:localhost:33000:image_db:user1:password1:", "", "");

// Getting data directly from ResetSet
PrepareStatement pstmt1 = conn.prepareStatement("SELECT content FROM doc_t WHERE doc_id = ? ");
pstmt2.setString(1, "doc-10");
ResultSet rs = pstmt1.executeQuery();

while (rs.next())
{
    String sContent = rs.getString(1);
    System.out.println("doc.content= "+sContent.);
}

Example 2

Connection conn = DriverManager.getConnection ("jdbc:cubrid:localhost:33000:image_db:user1:password1:", "", "");

// Getting BLOB data from ResultSet and getting data from the BLOB object
PrepareStatement pstmt2 = conn.prepareStatement("SELECT image FROM image_t WHERE image_id = ?");
pstmt2.setString(1,"image-20");
ResultSet rs = pstmt2.executeQuery();

while (rs.next())
{
    Blob bImage = rs.getBlob(1);
    Bytes[] bArray = bImange.getBytes(1, (int)bImage.length());
}

Note

If a string longer than defined max length is inserted (INSERT) or updated (UPDATE), the string will be truncated.

setBoolean
prepareStatement.setBoolean(1, true) will set
  • 1 for numeric types
  • '1' for string types
prepareStatement.setBooelan(1, false) will set
  • 0 for numeric types
  • '0' for string types

Note

Behavior of legacy versions

prepareStatement.setBoolean(1, true) set
  • as 2008 R4.1, 9.0, 1 of BIT(1) type
  • as 2008 R4.3, 2008 R4.4, 9.1, 9.2, 9.3, -128 of SHORT type
JDBC Error Codes and Error Messages

JDBC error codes which occur in SQLException are as follows.

  • All error codes are negative.
  • After SQLException, error number can be shown by SQLException.getErrorCode() and error message can be shown by SQLException.getMessage().
  • If the value of error code is between -21001 and -21999, it is caused by CUBRID JDBC methods.
  • If the value of error code is between -10000 and -10999, it is caused by CAS and transferred by JDBC methods. For CAS errors, see CAS Error.
  • If the value of error code is between 0 and -9999, it is caused by database server. For database server errors, see Database Server Errors.
Error Number Error Message
-21001 Index's Column is Not Object
-21002 Server error
-21003 Cannot communicate with the broker
-21004 Invalid cursor position
-21005 Type conversion error
-21006 Missing or invalid position of the bind variable provided
-21007 Attempt to execute the query when not all the parameters are binded
-21008 Internal Error: NULL value
-21009 Column index is out of range
-21010 Data is truncated because receive buffer is too small
-21011 Internal error: Illegal schema type
-21012 File access failed
-21013 Cannot connect to a broker
-21014 Unknown transaction isolation level
-21015 Internal error: The requested information is not available
-21016 The argument is invalid
-21017 Connection or Statement might be closed
-21018 Internal error: Invalid argument
-21019 Cannot communicate with the broker or received invalid packet
-21020 No More Result
-21021 This ResultSet do not include the OID
-21022 Command is not insert
-21023 Error
-21024 Request timed out
-21101 Attempt to operate on a closed Connection.
-21102 Attempt to access a closed Statement.
-21103 Attempt to access a closed PreparedStatement.
-21104 Attempt to access a closed ResultSet.
-21105 Not supported method
-21106 Unknown transaction isolation level.
-21107 invalid URL -
-21108 The database name should be given.
-21109 The query is not applicable to the executeQuery(). Use the executeUpdate() instead.
-21110 The query is not applicable to the executeUpdate(). Use the executeQuery() instead.
-21111 The length of the stream cannot be negative.
-21112 An IOException was caught during reading the inputstream.
-21113 Not supported method, because it is deprecated.
-21114 The object does not seem to be a number.
-21115 Missing or invalid position of the bind variable provided.
-21116 The column name is invalid.
-21117 Invalid cursor position.
-21118 Type conversion error.
-21119 Internal error: The number of attributes is different from the expected.
-21120 The argument is invalid.
-21121 The type of the column should be a collection type.
-21122 Attempt to operate on a closed DatabaseMetaData.
-21123 Attempt to call a method related to scrollability of non-scrollable ResultSet.
-21124 Attempt to call a method related to sensitivity of non-sensitive ResultSet.
-21125 Attempt to call a method related to updatability of non-updatable ResultSet.
-21126 Attempt to update a column which cannot be updated.
-21127 The query is not applicable to the executeInsert().
-21128 The argument row can not be zero.
-21129 Given InputStream object has no data.
-21130 Given Reader object has no data.
-21131 Insertion query failed.
-21132 Attempt to call a method related to scrollability of TYPE_FORWARD_ONLY Statement.
-21133 Authentication failure
-21134 Attempt to operate on a closed PooledConnection.
-21135 Attempt to operate on a closed XAConnection.
-21136 Illegal operation in a distributed transaction
-21137 Attempt to access a CUBRIDOID associated with a Connection which has been closed.
-21138 The table name is invalid.
-21139 Lob position to write is invalid.
-21140 Lob is not writable.
-21141 Request timed out.
JDBC Sample Program

The following sample shows how to connect to CUBRID by using the JDBC driver, and retrieve and insert data. To run the sample program, make sure that the database you are trying to connect to and the CUBRID broker are running. In the sample, you will use the demodb database that is automatically created during the installation.

Loading JDBC Driver

To connect to CUBRID, load the JDBC driver by using the forName () method of the Class. For more information, see JDBC Overview of the JDBC driver.

Class.forName("cubrid.jdbc.driver.CUBRIDDriver");

Connecting to Database

After loading the JDBC driver, use the getConnection () method of the DriverManager to connect to the database. To create a Connection object, you must specify information such as the URL which indicates the location of a database, user name, password, etc. For more information, see Configuration Connection.

String url = "jdbc:cubrid:localhost:33000:demodb:::";
String userid = "dba";
String password = "";

Connection conn = DriverManager.getConnection(url,userid,password);

To connect to a database, it is possible to use a DataSource object, too. If you want to include connection properties to a connection URL string, setURL method implemented in CUBRIDDataSource can be used.

import cubrid.jdbc.driver.CUBRIDDataSource;
...

ds = new CUBRIDDataSource();
ds.setURL("jdbc:cubrid:127.0.0.1:33000:demodb:::?charset=utf8&logSlowQueries=true&slowQueryThresholdMillis=1000&logTraceApi=true&logTraceNetwork=true");

For details about CUBRIDDataSource, see Connecting with DataSource.

Connecting to a DataSource Object

The following is an example to execute SELECT statements in multiple threads; they connect to DB with the setURL of CUBRIDDataSource, which is a DataSource implemented in CUBRID. Codes are separated with DataSourceMT.java and DataSourceExample.java.

  • DataSourceMT.java includes a main() function. After a CUBRIDDataSource object is created and a setURL method is called to connect to DB, multiple threads run DataSourceExample.test method.
  • In DataSourceExample.java, DataSourceExample.test is implemented; it is run on the threads in DataSourceMT.java.

DataSourceMT.java

import cubrid.jdbc.driver.*;

public class DataSourceMT {
    static int num_thread = 20;

    public static void main(String[] args) {
        CUBRIDDataSource ds = null;
        thrCPDSMT thread[];

        ds = new CUBRIDDataSource();
        ds.setURL("jdbc:cubrid:127.0.0.1:33000:demodb:::?charset=utf8&logSlowQueries=true&slowQueryThresholdMillis=1000&logTraceApi=true&logTraceNetwork=true");

        try {
            thread = new thrCPDSMT[num_thread];

            for (int i = 0; i < num_thread; i++) {
                Thread.sleep(1);
                thread[i] = new thrCPDSMT(i, ds);
                try {
                    Thread.sleep(1);
                    thread[i].start();
                } catch (Exception e) {
                }
            }

            for (int i = 0; i < num_thread; i++) {
                thread[i].join();
                System.err.println("join thread : " + i);
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }
}

class thrCPDSMT extends Thread {
    CUBRIDDataSource thread_ds;
    int thread_id;

    thrCPDSMT(int tid, CUBRIDDataSource ds) {
        thread_id = tid;
        thread_ds = ds;
    }

    public void run() {
        try {
            DataSourceExample.test(thread_ds);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }

    }
}

DataSourceExample.java

import java.sql.*;
import javax.sql.*;
import cubrid.jdbc.driver.*;

public class DataSourceExample {

    public static void printdata(ResultSet rs) throws SQLException {
        try {
            ResultSetMetaData rsmd = null;

            rsmd = rs.getMetaData();
            int numberofColumn = rsmd.getColumnCount();

            while (rs.next()) {
                for (int j = 1; j <= numberofColumn; j++)
                    System.out.print(rs.getString(j) + "  ");
                System.out.println("");
            }
        } catch (SQLException e) {
            System.out.println("SQLException : " + e.getMessage());
            throw e;
        }
    }

    public static void test(CUBRIDDataSource ds) throws Exception {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        for (int i = 1; i <= 20; i++) {
            try {
                connection = ds.getConnection("dba", "");
                statement = connection.createStatement();
                String SQL = "SELECT * FROM code";
                resultSet = statement.executeQuery(SQL);

                while (resultSet.next()) {
                    printdata(resultSet);
                }

                if (i % 5 == 0) {
                    System.gc();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeAll(resultSet, statement, connection);
            }
        }
    }

    public static void closeAll(ResultSet resultSet, Statement statement,
            Connection connection) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
            }
        }
    }
}

Manipulating Database (Executing Queries and Processing ResultSet)

To send a query statement to the connected database and execute it, create Statement, PrepardStatement, and CallableStatemen objects. After the Statement object is created, execute the query statement by using executeQuery () or executeUpdate () method of the Statement object. You can use the next () method to process the next row from the ResultSet that has been returned as a result of executing the executeQuery () method.

Note

In the version of 2008 R4.x or before, if you execute commit after query execution, ResultSet will be automatically closed. Therefore, you must not use ResultSet after commit. Generally CUBRID is executed in auto-commit mode; if you do not want for CUBRID being executed in auto-commit mode, you should specify conn.setAutocommit(false); in the code.

From 9.1, Cursor holdability is supported; therefore, you can use ResultSet after commit.

Disconnecting from Database

You can disconnect from a database by executing the close () method for each object.

CREATE, INSERT

The following is an example which connects to demodb, creates a table, executes a query with prepared statement and rolls back the query.

import java.util.*;
import java.sql.*;

public class Basic {
   public static Connection connect() {
      Connection conn = null;
      try {
           Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
           conn = DriverManager.getConnection("jdbc:cubrid:localhost:33000:demodb:::","dba","");
           conn.setAutoCommit (false) ;
      } catch ( Exception e ) {
           System.err.println("SQLException : " + e.getMessage());
      }
      return conn;
   }

   public static void printdata(ResultSet rs) {
      try {
          ResultSetMetaData rsmd = null;

          rsmd = rs.getMetaData();
          int numberofColumn = rsmd.getColumnCount();

          while (rs.next ()) {
              for(int j=1; j<=numberofColumn; j++ )
                  System.out.print(rs.getString(j) + "  " );
              System.out.println("");
          }
      } catch ( Exception e ) {
           System.err.println("SQLException : " + e.getMessage());
      }
   }

   public static void main(String[] args) throws Exception {
      Connection conn = null;
      Statement stmt = null;
      ResultSet rs = null;
      PreparedStatement preStmt = null;

      try {
           conn = connect();

           stmt = conn.createStatement();
           stmt.executeUpdate("CREATE TABLE xoo ( a INT, b INT, c CHAR(10))");

           preStmt = conn.prepareStatement("INSERT INTO xoo VALUES(?,?,''''100'''')");
           preStmt.setInt (1, 1) ;
           preStmt.setInt (2, 1*10) ;
           int rst = preStmt.executeUpdate () ;

           rs = stmt.executeQuery("select a,b,c from xoo" );

           printdata(rs);

           conn.rollback();
           stmt.close();
           conn.close();
      } catch ( Exception e ) {
           conn.rollback();
           System.err.println("SQLException : " + e.getMessage());
      } finally {
           if ( conn != null ) conn.close();
      }
   }
}

SELECT

The following example shows how to execute the SELECT statement by connecting to demodb which is automatically created when installing CUBRID.

import java.sql.*;

public class SelectData {
    public static void main(String[] args) throws Exception {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
            conn = DriverManager.getConnection("jdbc:cubrid:localhost:33000:demodb:::","dba","");

            String sql = "SELECT name, players FROM event";
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);

            while(rs.next()) {
               String name = rs.getString("name");
               String players = rs.getString("players");
               System.out.println("name ==> " + name);
               System.out.println("Number of players==> " + players);
               System.out.println("\n=========================================\n");
            }

            rs.close();
            stmt.close();
            conn.close();
        } catch ( SQLException e ) {
            System.err.println(e.getMessage());
        } catch ( Exception e ) {
            System.err.println(e.getMessage());
        } finally {
            if ( conn != null ) conn.close();
        }
    }
}

INSERT

The following example shows how to execute the INSERT statement by connecting to demodb which is automatically created when installing CUBRID. You can delete or update data the same way as you insert data so you can reuse the code below by simply modifying the query statement in the code.

import java.sql.*;

public class insertData {
   public static void main(String[] args) throws Exception {
       Connection conn = null;
       Statement stmt = null;

       try {
           Class.forName("cubrid.jdbc.driver.CUBRIDDriver");
           conn = DriverManager.getConnection("jdbc:cubrid:localhost:33000:demodb:::","dba","");
           String sql = "insert into olympic(host_year, host_nation, host_city, opening_date, closing_date) values (2008, 'China', 'Beijing', to_date('08-08-2008','mm-dd-yyyy'), to_date('08-24-2008','mm-dd-yyyy'))";
           stmt = conn.createStatement();
           stmt.executeUpdate(sql);
           System.out.println("A row is inserted.");
           stmt.close();
       } catch ( SQLException e ) {
           System.err.println(e.getMessage());
       } catch ( Exception e ) {
           System.err.println(e.getMessage());
       } finally {
           if ( conn != null ) conn.close();
       }
   }
}
JDBC API

For details about JDBC API, see Java API Specification (http://docs.oracle.com/javase/7/docs/api) and for details about Java, see Java SE Documentation (http://www.oracle.com/technetwork/java/javase/documentation/index.htm).

If cursor holdability is not configured, a cursor is maintained by default.

The following table shows the JDBC standard and extended interface supported by CUBRID. Note that some methods are not supported even though they are included in the JDBC 2.0 specification.

Supported JDBC Interface by CUBRID

JDBC Standard Interface JDBC Extended Interface Supported
java.sql.Blob   Supported
java.sql.CallableStatement   Supported
java.sql.Clob   Supported
java.sql.Connection   Supported
java.sql.DatabaseMetaData   Supported
java.sql.Driver   Supported
java.sql.PreparedStatement java.sql.CUBRIDPreparedStatement Supported
java.sql.ResultSet java.sql.CUBRIDResultSet Supported
java.sql.ResultSetMetaData java.sql.CUBRIDResultSetMetaData Supported
N/A CUBRIDOID Supported
java.sql.Statement java.sql.CUBRIDStatement The getGeneratedKeys() method of JDBC 3.0 is supported.
java.sql.DriverManager   Supported
Java.sql.SQLException Java.sql.CUBRIDException Supported
java.sql.Array   Not Supported
java.sql.ParameterMetaData   Not Supported
java.sql.Ref   Not Supported
java.sql.Savepoint   Not Supported
java.sql.SQLData   Not Supported
java.sql.SQLInput   Not Supported
java.sql.Struct   Not Supported

Note

  • If cursor holdability is not specified, cursor is hold in default.
  • From CUBRID 2008 R4.3 version, the behavior of batching the queries on the autocommit mode was changed. The methods that batch the queries are PreparedStatement.executeBatch and Statement.executeBatch. Until 2008 R4.1 version, these methods had committed the transaction after executing all queries on the array. From 2008 R4.3, they commit each query on the array.
  • In autocommit mode off, if the general error occurs during executing one of the queries in the array on the method which does a batch processing of the queries, the query with an error is ignored and the next query is executed continuously. But if the deadlock occurs, the error occurs as rolling back the transaction.

CCI Driver

CCI Overview

CUBRID CCI (CCI Client Interface) driver implements an interface to enable access from C-based application to CUBRID database server through broker. It is also used as back-end infrastructure for creating tools (PHP, ODBC, etc.) which use the CAS application servers. In this environment, the CUBRID broker sends queries received from applications to a database and transfers the result to applications.

It is automatically installed upon CUBRID installation and can be found in the $CUBRID/lib directory. A header file as well as library files is required to use the driver.

  Windows UNIX/Linux
C header file include/cas_cci.h include/cas_cci.h
Static library lib/cascci.lib lib/libcascci.a
Dynamic library bin/cascci.dll lib/libcascci.so

Because CUBRID CCI driver is connected through the CUBRID broker, you can manage it the same way as other interfaces such as JDBC, PHP, ODBC, etc. In fact, CCI provides back-end infrastructure to implement PHP, ODBC, Python, and Ruby interfaces.

_images/image54.jpg

To download CCI driver or get the latest information, click http://www.cubrid.org/wiki_apis/entry/cubrid-cci-driver .

CCI Programming
Writing CCI Applications

The applications using CCI interact with CUBRID in the process of connecting to CAS, preparing queries, executing queries, handling response, and disconnecting. In each process, CCI communicates with applications through connection handle, query handle, and response handle.

The default value of auto-commit mode can be configured by using CCI_DEFAULT_AUTOCOMMIT which is a broker parameter. If it is omitted, the default value is set to ON. To change auto-commit mode within applications, you should use the cci_set_autocommit() function. If auto-commit mode is OFF, you should explicitly commit or roll back transactions by using the cci_end_tran() function.

General process for writing applications is as follows. For using the prepared statement, additional step binding data to a variable is required; the examples 1 and 2 show the way to implement this.

Note

  • If you want to compile the CCI application on Windows, "WINDOWS" should be defined. Therefore, "-DWINDOWS" option should be defined on the compiler.
  • The database connection in thread-based programming must be used independently each other.
  • In autocommit mode, the transaction is not committed if all results are not fetched after running the SELECT statement. Therefore, although in autocommit mode, you should end the transaction by calling cci_end_tran() if some error occurs during fetching for the resultset.

Example 1

// Example to execute a simple query
// In Linux: gcc -o simple simple.c -m64 -I${CUBRID}/include -lnsl ${CUBRID}/lib/libcascci.so -lpthread

#include <stdio.h>
#include "cas_cci.h"
#define BUFSIZE  (1024)

int
main (void)
{
    int con = 0, req = 0, col_count = 0, i, ind;
    int error;
    char *data;
    T_CCI_ERROR cci_error;
    T_CCI_COL_INFO *col_info;
    T_CCI_CUBRID_STMT stmt_type;
    char *query = "select * from code";

    //getting a connection handle for a connection with a server
    con = cci_connect ("localhost", 33000, "demodb", "dba", "");
    if (con < 0)
    {
        printf ("cannot connect to database\n");
        return 1;
    }

    //preparing the SQL statement
    req = cci_prepare (con, query, 0, &cci_error);
    if (req < 0)
    {
        printf ("prepare error: %d, %s\n", cci_error.err_code,
                cci_error.err_msg);
        goto handle_error;
    }

    //getting column information when the prepared statement is the SELECT query
    col_info = cci_get_result_info (req, &stmt_type, &col_count);
    if (col_info == NULL)
    {
        printf ("get_result_info error: %d, %s\n", cci_error.err_code,
                cci_error.err_msg);
        goto handle_error;
    }

    //Executing the prepared SQL statement
    error = cci_execute (req, 0, 0, &cci_error);
    if (error < 0)
    {
        printf ("execute error: %d, %s\n", cci_error.err_code,
                cci_error.err_msg);
        goto handle_error;
    }
    while (1)
    {

        //Moving the cursor to access a specific tuple of results
        error = cci_cursor (req, 1, CCI_CURSOR_CURRENT, &cci_error);
        if (error == CCI_ER_NO_MORE_DATA)
        {
            break;
        }
        if (error < 0)
        {
            printf ("cursor error: %d, %s\n", cci_error.err_code,
                    cci_error.err_msg);
            goto handle_error;
        }

        //Fetching the query result into a client buffer
        error = cci_fetch (req, &cci_error);
        if (error < 0)
        {
            printf ("fetch error: %d, %s\n", cci_error.err_code,
                    cci_error.err_msg);
            goto handle_error;
        }
        for (i = 1; i <= col_count; i++)
        {

            //Getting data from the fetched result
            error = cci_get_data (req, i, CCI_A_TYPE_STR, &data, &ind);
            if (error < 0)
            {
                printf ("get_data error: %d, %d\n", error, i);
                goto handle_error;
            }
            printf ("%s\t|", data);
        }
        printf ("\n");
    }

    //Closing the request handle
    error = cci_close_req_handle (req);
    if (error < 0)
    {
        printf ("close_req_handle error: %d, %s\n", cci_error.err_code,
                cci_error.err_msg);
        goto handle_error;
    }

    //Disconnecting with the server
    error = cci_disconnect (con, &cci_error);
    if (error < 0)
    {
        printf ("error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
        goto handle_error;
    }

    return 0;

handle_error:
    if (req > 0)
        cci_close_req_handle (req);
    if (con > 0)
    cci_disconnect (con, &cci_error);

    return 1;
}

Example 2

// Example to execute a query with a bind variable
// In Linux: gcc -o cci_bind cci_bind.c -m64 -I${CUBRID}/include -lnsl ${CUBRID}/lib/libcascci.so -lpthread

#include <stdio.h>
#include <string.h>
#include "cas_cci.h"
#define BUFSIZE  (1024)

int
main (void)
{
    int con = 0, req = 0, col_count = 0, i, ind;
    int error;
    char *data;
    T_CCI_ERROR cci_error;
    T_CCI_COL_INFO *col_info;
    T_CCI_CUBRID_STMT stmt_type;
    char *query = "select * from nation where name = ?";
    char namebuf[128];

    //getting a connection handle for a connection with a server
    con = cci_connect ("localhost", 33000, "demodb", "dba", "");
    if (con < 0)
    {
        printf ("cannot connect to database\n");
        return 1;
    }

    //preparing the SQL statement
    req = cci_prepare (con, query, 0, &cci_error);
    if (req < 0)
    {
        printf ("prepare error: %d, %s\n", cci_error.err_code,
              cci_error.err_msg);
        goto handle_error;
    }

    //Binding date into a value
    strcpy (namebuf, "Korea");
    error =
    cci_bind_param (req, 1, CCI_A_TYPE_STR, namebuf, CCI_U_TYPE_STRING,
                    CCI_BIND_PTR);
    if (error < 0)
    {
        printf ("bind_param error: %d ", error);
        goto handle_error;
    }

    //getting column information when the prepared statement is the SELECT query
    col_info = cci_get_result_info (req, &stmt_type, &col_count);
    if (col_info == NULL)
    {
        printf ("get_result_info error: %d, %s\n", cci_error.err_code,
              cci_error.err_msg);
        goto handle_error;
    }

    //Executing the prepared SQL statement
    error = cci_execute (req, 0, 0, &cci_error);
    if (error < 0)
    {
        printf ("execute error: %d, %s\n", cci_error.err_code,
              cci_error.err_msg);
        goto handle_error;
    }

    //Executing the prepared SQL statement
    error = cci_execute (req, 0, 0, &cci_error);
    if (error < 0)
    {
        printf ("execute error: %d, %s\n", cci_error.err_code,
              cci_error.err_msg);
        goto handle_error;
    }

    while (1)
    {

        //Moving the cursor to access a specific tuple of results
        error = cci_cursor (req, 1, CCI_CURSOR_CURRENT, &cci_error);
        if (error == CCI_ER_NO_MORE_DATA)
        {
            break;
        }
        if (error < 0)
        {
            printf ("cursor error: %d, %s\n", cci_error.err_code,
                  cci_error.err_msg);
            goto handle_error;
        }

        //Fetching the query result into a client buffer
        error = cci_fetch (req, &cci_error);
        if (error < 0)
        {
            printf ("fetch error: %d, %s\n", cci_error.err_code,
                  cci_error.err_msg);
            goto handle_error;
        }
        for (i = 1; i <= col_count; i++)
        {

            //Getting data from the fetched result
            error = cci_get_data (req, i, CCI_A_TYPE_STR, &data, &ind);
            if (error < 0)
            {
                printf ("get_data error: %d, %d\n", error, i);
                goto handle_error;
            }
            if (ind == -1)
            {
                printf ("NULL\t");
            }
            else
            {
                printf ("%s\t|", data);
            }
        }
            printf ("\n");
    }

    //Closing the request handle
    error = cci_close_req_handle (req);
    if (error < 0)
    {
        printf ("close_req_handle error: %d, %s\n", cci_error.err_code,
                cci_error.err_msg);
        goto handle_error;
    }

    //Disconnecting with the server
    error = cci_disconnect (con, &cci_error);
    if (error < 0)
    {
        printf ("error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
        goto handle_error;
    }

    return 0;

handle_error:
    if (req > 0)
        cci_close_req_handle (req);
    if (con > 0)
        cci_disconnect (con, &cci_error);
    return 1;
}

Example 3

// Example to use connection/statement pool in CCI
// In Linux: gcc -o cci_pool cci_pool.c -m64 -I${CUBRID}/include -lnsl ${CUBRID}/lib/libcascci.so -lpthread

#include <stdio.h>
#include "cas_cci.h"

int main ()
{
    T_CCI_PROPERTIES *ps = NULL;
    T_CCI_DATASOURCE *ds = NULL;
    T_CCI_ERROR err;
    T_CCI_CONN cons;
    int rc = 1, i;

    ps = cci_property_create ();
    if (ps == NULL)
    {
        fprintf (stderr, "Could not create T_CCI_PROPERTIES.\n");
        rc = 0;
        goto cci_pool_end;
    }

    cci_property_set (ps, "user", "dba");
    cci_property_set (ps, "url", "cci:cubrid:localhost:33000:demodb:::");
    cci_property_set (ps, "pool_size", "10");
    cci_property_set (ps, "max_wait", "1200");
    cci_property_set (ps, "pool_prepared_statement", "true");
    cci_property_set (ps, "login_timeout", "300000");
    cci_property_set (ps, "query_timeout", "3000");

    ds = cci_datasource_create (ps, &err);
    if (ds == NULL)
    {
        fprintf (stderr, "Could not create T_CCI_DATASOURCE.\n");
        fprintf (stderr, "E[%d,%s]\n", err.err_code, err.err_msg);
        rc = 0;
        goto cci_pool_end;
    }

    for (i = 0; i < 3; i++)
    {
        cons = cci_datasource_borrow (ds, &err);
        if (cons < 0)
        {
            fprintf (stderr,
                    "Could not borrow a connection from the data source.\n");
            fprintf (stderr, "E[%d,%s]\n", err.err_code, err.err_msg);
            continue;
        }
        // put working code here.
        cci_work (cons);
        cci_datasource_release (ds, cons, &err);

    }

cci_pool_end:
  cci_property_destroy (ps);
  cci_datasource_destroy (ds);

  return 0;
}

// working code
int cci_work (T_CCI_CONN con)
{
    T_CCI_ERROR err;
    char sql[4096];
    int req, res, error, ind;
    int data;

    cci_set_autocommit (con, CCI_AUTOCOMMIT_TRUE);
    cci_set_lock_timeout (con, 100, &err);
    cci_set_isolation_level (con, TRAN_REP_CLASS_COMMIT_INSTANCE, &err);

    error = 0;
    snprintf (sql, 4096, "SELECT host_year FROM record WHERE athlete_code=11744");
    req = cci_prepare (con, sql, 0, &err);
    if (req < 0)
    {
        printf ("prepare error: %d, %s\n", err.err_code, err.err_msg);
        return error;
    }

    res = cci_execute (req, 0, 0, &err);
    if (res < 0)
    {
        printf ("execute error: %d, %s\n", err.err_code, err.err_msg);
        goto cci_work_end;
    }

    while (1)
    {
    error = cci_cursor (req, 1, CCI_CURSOR_CURRENT, &err);
    if (error == CCI_ER_NO_MORE_DATA)
    {
        break;
    }
    if (error < 0)
    {
        printf ("cursor error: %d, %s\n", err.err_code, err.err_msg);
        goto cci_work_end;
    }

    error = cci_fetch (req, &err);
    if (error < 0)
    {
        printf ("fetch error: %d, %s\n", err.err_code, err.err_msg);
        goto cci_work_end;
    }

    error = cci_get_data (req, 1, CCI_A_TYPE_INT, &data, &ind);
    if (error < 0)
    {
        printf ("get data error: %d\n", error);
        goto cci_work_end;
    }
    printf ("%d\n", data);
    }

    error = 1;
cci_work_end:
    cci_close_req_handle (req);
    return error;
}
Configuring Library

Once you have written applications using CCI, you should decide, according to its features, whether to execute CCI as static or dynamic link before you build it. See the table in CCI Overview to decide which library will be used.

The following is an example of Makefile, which makes a link by using the dynamic library on UNIX/Linux.

CC=gcc
CFLAGS = -g -Wall -I. -I$CUBRID/include
LDFLAGS = -L$CUBRID/lib -lcascci -lnsl
TEST_OBJS = test.o
EXES = test
all: $(EXES)
test: $(TEST_OBJS)
    $(CC) -o $@ $(TEST_OBJS) $(LDFLAGS)

The following image shows configuration to use static library on Windows.

_images/image55.png
Using BLOB/CLOB

Storing LOB Data

You can create LOB data file and bind the data by using the functions below in CCI applications.

Example

int con = 0; /* connection handle */
int req = 0; /* request handle */
int res;
int n_executed;
int i;
T_CCI_ERROR error;
T_CCI_BLOB blob = NULL;
char data[1024] = "bulabula";

con = cci_connect ("localhost", 33000, "tdb", "PUBLIC", "");
if (con < 0) {
    goto handle_error;
}
req = cci_prepare (con, "insert into doc (doc_id, content) values (?,?)", 0, &error);
if (req< 0)
{
    goto handle_error;
}

res = cci_bind_param (req, 1 /* binding index*/, CCI_A_TYPE_STR, "doc-10", CCI_U_TYPE_STRING, CCI_BIND_PTR);

/* Creating an empty LOB data file */
res = cci_blob_new (con, &blob, &error);
res = cci_blob_write (con, blob, 0 /* start position */, 1024 /* length */, data, &error);

/* Binding BLOB data */
res = cci_bind_param (req, 2 /* binding index*/, CCI_A_TYPE_BLOB, (void *)blob, CCI_U_TYPE_BLOB, CCI_BIND_PTR);

n_executed = cci_execute (req, 0, 0, &error);
if (n_executed < 0)
{
    goto handle_error;
}

/* Commit */
if (cci_end_tran(con, CCI_TRAN_COMMIT, &error) < 0)
{
    goto handle_error;
}

/* Memory free */
cci_blob_free(blob);
return 0;

handle_error:
if (blob != NULL)
{
    cci_blob_free(blob);
}
if (req > 0)
{
    cci_close_req_handle (req);
}
if (con > 0)
{
    cci_disconnect(con, &error);
}
return -1;

Retrieving LOB Data

You can retrieve LOB data by using the following functions in CCI applications. Note that if you enter data in the LOB type column, the actual LOB data is stored in the file located in external storage and Locator value is stored in the LOB type column. Thus, to retrieve the LOB data stored in the file, you should call the cci_blob_read() function but the cci_get_data() function.

  • Retrieving meta data (Locator) in the the LOB type column (related function: cci_get_data())
  • Retrieving the LOB data (related function: cci_blob_read())
  • Freeing memory for the LOB struct: (related function: cci_blob_free())

Example

int con = 0; /* connection handle */
int req = 0; /* request handle */
int ind; /* NULL indicator, 0 if not NULL, -1 if NULL*/
int res;
int i;
T_CCI_ERROR error;
T_CCI_BLOB blob;
char buffer[1024];

con = cci_connect ("localhost", 33000, "image_db", "PUBLIC", "");
if (con < 0)
{
    goto handle_error;
}
req = cci_prepare (con, "select content from doc_t", 0 /*flag*/, &error);
if (req< 0)
{
    goto handle_error;
}

res = cci_execute (req, 0/*flag*/, 0/*max_col_size*/, &error);

while (1) {
    res = cci_cursor (req, 1/* offset */, CCI_CURSOR_CURRENT/* cursor position */, &error);
    if (res == CCI_ER_NO_MORE_DATA)
    {
        break;
    }
    res = cci_fetch (req, &error);

    /* Fetching CLOB Locator */
    res = cci_get_data (req, 1 /* colume index */, CCI_A_TYPE_BLOB,
    (void *)&blob /* BLOB handle */, &ind /* NULL indicator */);
    /* Fetching CLOB data */
    res = cci_blob_read (con, blob, 0 /* start position */, 1024 /* length */, buffer, &error);
    printf ("content = %s\n", buffer);
}

/* Memory free */
cci_blob_free(blob);
res=cci_close_req_handle(req);
res = cci_disconnect (con, &error);
return 0;

handle_error:
if (req > 0)
{
    cci_close_req_handle (req);
}
if (con > 0)
{
    cci_disconnect(con, &error);
}
return -1;
CCI Error Codes and Error Messages

CCI API functions return a negative number as CCI or CAS (broker application server) error codes when an error occurs. The CCI error codes occur in CCI API functions and CAS error codes occur in CAS.

  • All error codes are negative.
  • All error codes and error messages of functions which have "T_CCI_ERROR err_buf" as a parameter can be found on err_buf.err_code and err_buf.err_msg.
  • All error messages of functions which have no "T_CCI_ERROR err_buf" as a parameter can output by using cci_get_err_msg().
  • If the value of error code is between -20002 and -20999, it is caused by CCI API functions.
  • If the value of error code is between -10000 and -10999, it is caused by CAS and transferred by CCI API functions. For CAS errors, see CAS Error.
  • If the value of error code is CCI_ER_DBMS (-20001), it is caused by database server. You can check server error codes in err_buf.err_code of the database error buffer (err_buf). For database server errors, see Database Server Errors.

Warning

If an error occurs in server, the value of CCI_ER_DBMS, which is error code returned by a function may be different from the value of the err_buf.err_code. Except server errors, every error code stored in err_buf is identical to that returned by a function.

Note

CCI and CAS error codes have different values between the earlier version of CUBRID 9.0 and the version of CUBRID 9.0 or later. Therefore, the users who developed the applications by using the error code names must recompile them and the users who developed them by directly assigning error code numbers must recompile them after changing the number values.

The database error buffer (err_buf) is a struct variable of T_CCI_ERROR defined in the cas_cci.h header file. For how to use it, see the example below.

CCI error codes which starting with CCI_ER are defined in enum called T_CCI_ERROR_CODE under the $CUBRID/include/cas_cci.h file. Therefore, to use this error code name in program code, you should include a header file in the upper side of code by entering #include "cas_cci.h".

The following example shows how to display error messages. In the example, the error code value (req) returned by cci_prepare() is CCI_ER_DBMS. -493 (server error code) is stored in cci_error.err_code and the error message, 'Syntax: Unknown class "notable". select * from notable' is stored in cci_error.err_msg of the database error buffer.

// gcc -o err err.c -m64 -I${CUBRID}/include -lnsl ${CUBRID}/lib/libcascci.so -lpthread
#include <stdio.h>
#include "cas_cci.h"

#define BUFSIZE  (1024)

int
main (void)
{
    int con = 0, req = 0, col_count = 0, i, ind;
    int error;
    char *data;
    T_CCI_ERROR err_buf;
    char *query = "select * from notable";

    //getting a connection handle for a connection with a server
    con = cci_connect ("localhost", 33000, "demodb", "dba", "");
    if (con < 0)
    {
        printf ("cannot connect to database\n");
        return 1;
    }

    //preparing the SQL statement
    req = cci_prepare (con, query, 0, &err_buf);
    if (req < 0)
    {
        if (req == CCI_ER_DBMS)
        {
            printf ("error from server: %d, %s\n", err_buf.err_code, err_buf.err_msg);
        }
        else
        {
            printf ("error from cci or cas: %d, %s\n", err_buf.err_code, err_buf.err_msg);
        }
        goto handle_error;
    }
    // ...
}

The following list shows CCI error codes. For CAS errors, see CAS Error.

Error Code (Error Number) Error Message Note
CCI_ER_DBMS (-20001) CUBRID DBMS Error Error codes returned by functions when an error occurs in server. The causes of the error can be checked with err_code and err_msg stored in the T_CCI_ERROR struct.
CCI_ER_CON_HANDLE (-20002) Invalid connection handle  
CCI_ER_NO_MORE_MEMORY (-20003) Memory allocation error Insufficient memory
CCI_ER_COMMUNICATION (-20004) Cannot communicate with server  
CCI_ER_NO_MORE_DATA (-20005) Invalid cursor position  
CCI_ER_TRAN_TYPE (-20006) Unknown transaction type  
CCI_ER_STRING_PARAM (-20007) Invalid string argument An error occurred when sql_stmt is NULL in cci_prepare(), and cci_prepare_and_execute()
CCI_ER_TYPE_CONVERSION (-20008) Type conversion error Cannot convert the given value into an actual data type.
CCI_ER_BIND_INDEX (-20009) Parameter index is out of range Index that binds data is not valid.
CCI_ER_ATYPE (-20010) Invalid T_CCI_A_TYPE value  
CCI_ER_NOT_BIND (-20011)   Not available
CCI_ER_PARAM_NAME (-20012) Invalid T_CCI_DB_PARAM value  
CCI_ER_COLUMN_INDEX (-20013) Column index is out of range  
CCI_ER_SCHEMA_TYPE (-20014)   Not available
CCI_ER_FILE (-20015) Cannot open file Fails to open/read/write a file.
CCI_ER_CONNECT (-20016) Cannot connect to CUBRID CAS Cannot connect to CUBRID CAS
CCI_ER_ALLOC_CON_HANDLE (-20017) Cannot allocate connection handle %  
CCI_ER_REQ_HANDLE (-20018) Cannot allocate request handle %  
CCI_ER_INVALID_CURSOR_POS (-20019) Invalid cursor position  
CCI_ER_OBJECT (-20020) Invalid oid string  
CCI_ER_CAS (-20021)   Not available
CCI_ER_HOSTNAME (-20022) Unknown host name  
CCI_ER_OID_CMD (-20023) Invalid T_CCI_OID_CMD value  
CCI_ER_BIND_ARRAY_SIZE (-20024) Array binding size is not specified  
CCI_ER_ISOLATION_LEVEL (-20025) Unknown transaction isolation level  
CCI_ER_SET_INDEX (-20026) Invalid set index Invalid index is specified when a set element in the T_CCI_SET struct is retrieved.
CCI_ER_DELETED_TUPLE (-20027) Current row was deleted %  
CCI_ER_SAVEPOINT_CMD (-20028) Invalid T_CCI_SAVEPOINT_CMD value Invalid T_CCI_SAVEPOINT_CMD value is used as an argument of the cci_savepoint() function.
CCI_ER_THREAD_RUNNING(-20029) Invalid T_CCI_SAVEPOINT_CMD value Invalid T_CCI_SAVEPOINT_CMD value is used as an argument of the cci_savepoint() function.
CCI_ER_INVALID_URL (-20030) Invalid url string  
CCI_ER_INVALID_LOB_READ_POS (-20031) Invalid lob read position  
CCI_ER_INVALID_LOB_HANDLE (-20032) Invalid lob handle  
CCI_ER_NO_PROPERTY (-20033) Could not find a property  
CCI_ER_PROPERTY_TYPE (-20034) Invalid property type  
CCI_ER_INVALID_DATASOURCE (-20035) Invalid CCI datasource  
CCI_ER_DATASOURCE_TIMEOUT (-20036) All connections are used  
CCI_ER_DATASOURCE_TIMEDWAIT (-20037) pthread_cond_timedwait error  
CCI_ER_LOGIN_TIMEOUT (-20038) Connection timed out  
CCI_ER_QUERY_TIMEOUT (-20039) Request timed out  
CCI_ER_RESULT_SET_CLOSED (-20040)    
CCI_ER_INVALID_HOLDABILITY (-20041) Invalid holdability mode. The only accepted values are 0 or 1  
CCI_ER_NOT_UPDATABLE (-20042) Request handle is not updatable  
CCI_ER_INVALID_ARGS (-20043) Invalid argument  
CCI_ER_USED_CONNECTION (-20044) This connection is used already.  

C Type Definition

The following shows the structs used in CCI API functions.

Name Type Member Description
T_CCI_ERROR struct char err_msg[1024] Representation of database error info
int err_code
T_CCI_BIT struct int size Representation of bit type
char *buf
T_CCI_DATE struct short yr Representation of datetime, timestamp, date, and time type
short mon
short day
short hh
short mm
short ss
short ms
T_CCI_DATE_TZ struct short yr Representation of date/time types with timezone
short mon
short day
short hh
short mm
short ss
short ms
char tz[64]
T_CCI_SET void*   Representation of set type
T_CCI_COL_INFO struct T_CCI_U_EXT_TYPE type Representation of column information for the SELECT statement
char is_non_null
short scale
int precision
char *col_name
char *real_attr
char *class_name
T_CCI_QUERY_RESULT struct int result_count Results of batch execution
int stmt_type
char *err_msg
char oid[32]
T_CCI_PARAM_INFO struct T_CCI_PARAM_MODE mode Representation of input parameter info
T_CCI_U_EXT_TYPE type
short scale
int precision
T_CCI_U_EXT_TYPE unsigned char   Database type info
T_CCI_U_TYPE enum CCI_U_TYPE_UNKNOWN Database type info
CCI_U_TYPE_NULL
CCI_U_TYPE_CHAR
CCI_U_TYPE_STRING
CCI_U_TYPE_BIT
CCI_U_TYPE_VARBIT
CCI_U_TYPE_NUMERIC
CCI_U_TYPE_INT
CCI_U_TYPE_SHORT
CCI_U_TYPE_FLOAT
CCI_U_TYPE_DOUBLE
CCI_U_TYPE_DATE
CCI_U_TYPE_TIME
CCI_U_TYPE_TIMESTAMP
CCI_U_TYPE_SET
CCI_U_TYPE_MULTISET
CCI_U_TYPE_SEQUENCE
CCI_U_TYPE_OBJECT
CCI_U_TYPE_BIGINT
CCI_U_TYPE_DATETIME
CCI_U_TYPE_BLOB
CCI_U_TYPE_CLOB
CCI_U_TYPE_ENUM
CCI_U_TYPE_UINT
CCI_U_TYPE_USHORT
CCI_U_TYPE_UBIGINT
CCI_U_TYPE_TIMESTAMPTZ
CCI_U_TYPE_TIMESTAMPLTZ
CCI_U_TYPE_DATETIMETZ
CCI_U_TYPE_DATETIMELTZ
T_CCI_A_TYPE enum CCI_A_TYPE_STR Representation of type info used in API
CCI_A_TYPE_INT
CCI_A_TYPE_FLOAT
CCI_A_TYPE_DOUBLE
CCI_A_TYPE_BIT
CCI_A_TYPE_DATE
CCI_A_TYPE_SET
CCI_A_TYPE_BIGINT
CCI_A_TYPE_BLOB
CCI_A_TYPE_CLOB
CCI_A_TYPE_CLOB
CCI_A_TYPE_REQ_HANDLE
CCI_A_TYPE_UINT
CCI_A_TYPE_UBIGINT
CCI_A_TYPE_DATE_TZ
CCI_A_TYPE_UINT
T_CCI_DB_PARAM enum CCI_PARAM_ISOLATION_LEVEL System parameter names
CCI_PARAM_LOCK_TIMEOUT
CCI_PARAM_MAX_STRING_LENGTH
CCI_PARAM_AUTO_COMMIT
T_CCI_SCH_TYPE enum CCI_SCH_CLASS  
CCI_SCH_VCLASS
CCI_SCH_QUERY_SPEC
CCI_SCH_ATTRIBUTE
CCI_SCH_CLASS_ATTRIBUTE
CCI_SCH_METHOD
CCI_SCH_CLASS_METHOD
CCI_SCH_METHOD_FILE
CCI_SCH_SUPERCLASS
CCI_SCH_SUBCLASS
CCI_SCH_CONSTRAIT
CCI_SCH_TRIGGER
CCI_SCH_CLASS_PRIVILEGE
CCI_SCH_ATTR_PRIVILEGE
CCI_SCH_DIRECT_SUPER_CLASS
CCI_SCH_PRIMARY_KEY
CCI_SCH_IMPORTED_KEYS
CCI_SCH_EXPORTED_KEYS
CCI_SCH_CROSS_REFERENCE
T_CCI_CUBRID_STMT enum CUBRID_STMT_ALTER_CLASS  
CUBRID_STMT_ALTER_SERIAL
CUBRID_STMT_COMMIT_WORK
CUBRID_STMT_REGISTER_DATABASE
CUBRID_STMT_CREATE_CLASS
CUBRID_STMT_CREATE_INDEX
CUBRID_STMT_CREATE_TRIGGER
CUBRID_STMT_CREATE_SERIAL
CUBRID_STMT_DROP_DATABASE
CUBRID_STMT_DROP_CLASS
CUBRID_STMT_DROP_INDEX
CUBRID_STMT_DROP_LABEL
CUBRID_STMT_DROP_TRIGGER
CUBRID_STMT_DROP_SERIAL
CUBRID_STMT_EVALUATE
CUBRID_STMT_RENAME_CLASS
CUBRID_STMT_ROLLBACK_WORK
CUBRID_STMT_GRANT
CUBRID_STMT_REVOKE
CUBRID_STMT_STATISTICS
CUBRID_STMT_INSERT
CUBRID_STMT_SELECT
CUBRID_STMT_UPDATE
CUBRID_STMT_DELETE
CUBRID_STMT_CALL
CUBRID_STMT_GET_ISO_LVL
CUBRID_STMT_GET_TIMEOUT
CUBRID_STMT_GET_OPT_LVL
CUBRID_STMT_SET_OPT_LVL
CUBRID_STMT_SCOPE
CUBRID_STMT_GET_TRIGGER
CUBRID_STMT_SET_TRIGGER
CUBRID_STMT_SAVEPOINT
CUBRID_STMT_PREPARE
CUBRID_STMT_ATTACH
CUBRID_STMT_USE
CUBRID_STMT_REMOVE_TRIGGER
CUBRID_STMT_RENAME_TRIGGER
CUBRID_STMT_ON_LDB
CUBRID_STMT_GET_LDB
CUBRID_STMT_SET_LDB
CUBRID_STMT_GET_STATS
CUBRID_STMT_CREATE_USER
CUBRID_STMT_DROP_USER
CUBRID_STMT_ALTER_USER
CUBRID_STMT_SET_SYS_PARAMS
CUBRID_STMT_ALTER_INDEX
CUBRID_STMT_CREATE_STORED_PROCEDURE
CUBRID_STMT_DROP_STORED_PROCEDURE
CUBRID_STMT_PREPARE_STATEMENT
CUBRID_STMT_EXECUTE_PREPARE
CUBRID_STMT_DEALLOCATE_PREPARE
CUBRID_STMT_TRUNCATE
CUBRID_STMT_DO
CUBRID_STMT_SELECT_UPDATE
CUBRID_STMT_SET_SESSION_VARIABLES
CUBRID_STMT_DROP_SESSION_VARIABLES
CUBRID_STMT_MERGE
CUBRID_STMT_SET_NAMES
CUBRID_STMT_ALTER_STORED_PROCEDURE
CUBRID_STMT_KILL
T_CCI_CURSOR_POS enum CCI_CURSOR_FIRST  
CCI_CURSOR_CURRENT
CCI_CURSOR_LAST
T_CCI_TRAN_ISOLATION enum TRAN_READ_COMMITTED  
TRAN_REPEATABLE_READ
TRAN_SERIALIZABLE
T_CCI_PARAM_MODE enum CCI_PARAM_MODE_UNKNOWN  
CCI_PARAM_MODE_IN
CCI_PARAM_MODE_OUT
CCI_PARAM_MODE_INOUT

Note

If a string longer than defined max length is inserted (INSERT) or updated (UPDATE), the string will be truncated.

CCI Sample Program

The sample program shows how to write a CCI application by using the demodb database which is included with the CUBRID installation package. You can practice the ways to connect to CAS, prepare queries, execute queries, handle response, disconnect from CAS, etc. by following sample program below. In the sample program, the dynamic link on Linux environment is used.

The code below shows information about olympic table schema in the demodb database which is used for sample program.

csql> ;sc olympic

=== <Help: Schema of a Class> ===


 <Class Name>

     olympic

 <Attributes>

     host_year            INTEGER NOT NULL
     host_nation          CHARACTER VARYING(40) NOT NULL
     host_city            CHARACTER VARYING(20) NOT NULL
     opening_date         DATE NOT NULL
     closing_date         DATE NOT NULL
     mascot               CHARACTER VARYING(20)
     slogan               CHARACTER VARYING(40)
     introduction         CHARACTER VARYING(1500)

 <Constraints>

     PRIMARY KEY pk_olympic_host_year ON olympic (host_year)

Preparing

Make sure that the demodb database and the broker are running before you execute the sample program. You can start the demodb database and the broker by executing the cubrid utility. The code below shows how to run a database server and broker by executing the cubrid utility.

[tester@testdb ~]$ cubrid server start demodb
@ cubrid master start
++ cubrid master start: success
@ cubrid server start: demodb

This may take a long time depending on the amount of recovery works to do.

CUBRID 9.2

++ cubrid server start: success
[tester@testdb ~]$ cubrid broker start
@ cubrid broker start
++ cubrid broker start: success

Building

With the program source and the Makefile prepared, executing make will create an executable file named test. If you use a static library, there is no need to deploy additional files and the execution will be faster. However, it increases the program size and memory usage. If you use a dynamic library, there will be some performance overhead but the program size and memory usage can be optimized.

The code below a command line that makes a test program build by using a dynamic library instead of using make on Linux.

cc -o test test.c -I$CUBRID/include -L$CUBRID/lib -lnsl -lcascci

Sample Code

#include <stdio.h>
#include <cas_cci.h>
char *cci_client_name = "test";
int main (int argc, char *argv[])
{
    int con = 0, req = 0, col_count = 0, res, ind, i;
    T_CCI_ERROR error;
    T_CCI_COL_INFO *res_col_info;
    T_CCI_CUBRID_STMT stmt_type;
    char *buffer, db_ver[16];
    printf("Program started!\n");
    if ((con=cci_connect("localhost", 30000, "demodb", "PUBLIC", ""))<0) {
        printf( "%s(%d): cci_connect fail\n", __FILE__, __LINE__);
        return -1;
    }

    if ((res=cci_get_db_version(con, db_ver, sizeof(db_ver)))<0) {
        printf( "%s(%d): cci_get_db_version fail\n", __FILE__, __LINE__);
        goto handle_error;
    }
    printf("DB Version is %s\n",db_ver);
    if ((req=cci_prepare(con, "select * from event", 0,&error))<0) {
        if (req < 0) {
            printf( "%s(%d): cci_prepare fail(%d)\n", __FILE__, __LINE__,error.err_code);
        }
        goto handle_error;
    }
    printf("Prepare ok!(%d)\n",req);
    res_col_info = cci_get_result_info(req, &stmt_type, &col_count);
    if (!res_col_info) {
        printf( "%s(%d): cci_get_result_info fail\n", __FILE__, __LINE__);
        goto handle_error;
    }

    printf("Result column information\n"
           "========================================\n");
    for (i=1; i<=col_count; i++) {
        printf("name:%s  type:%d(precision:%d scale:%d)\n",
            CCI_GET_RESULT_INFO_NAME(res_col_info, i),
            CCI_GET_RESULT_INFO_TYPE(res_col_info, i),
            CCI_GET_RESULT_INFO_PRECISION(res_col_info, i),
            CCI_GET_RESULT_INFO_SCALE(res_col_info, i));
    }
    printf("========================================\n");
    if ((res=cci_execute(req, 0, 0, &error))<0) {
        if (req < 0) {
            printf( "%s(%d): cci_execute fail(%d)\n", __FILE__, __LINE__,error.err_code);
        }
        goto handle_error;
    }

    while (1) {
        res = cci_cursor(req, 1, CCI_CURSOR_CURRENT, &error);
        if (res == CCI_ER_NO_MORE_DATA) {
            printf("Query END!\n");
            break;
        }
        if (res<0) {
            if (req < 0) {
                printf( "%s(%d): cci_cursor fail(%d)\n", __FILE__, __LINE__,error.err_code);
            }
            goto handle_error;
        }

        if ((res=cci_fetch(req, &error))<0) {
            if (res < 0) {
                printf( "%s(%d): cci_fetch fail(%d)\n", __FILE__, __LINE__,error.err_code);
            }
            goto handle_error;
        }

        for (i=1; i<=col_count; i++) {
            if ((res=cci_get_data(req, i, CCI_A_TYPE_STR, &buffer, &ind))<0) {
                printf( "%s(%d): cci_get_data fail\n", __FILE__, __LINE__);
                goto handle_error;
            }
            printf("%s \t|", buffer);
        }
        printf("\n");
    }
    if ((res=cci_close_req_handle(req))<0) {
        printf( "%s(%d): cci_close_req_handle fail", __FILE__, __LINE__);
       goto handle_error;
    }
    if ((res=cci_disconnect(con, &error))<0) {
        if (res < 0) {
            printf( "%s(%d): cci_disconnect fail(%d)", __FILE__, __LINE__,error.err_code);
        }
        goto handle_error;
    }
    printf("Program ended!\n");
    return 0;

    handle_error:
    if (req > 0)
        cci_close_req_handle(req);
    if (con > 0)
        cci_disconnect(con, &error);
    printf("Program failed!\n");
    return -1;
}
CCI API Reference

Contents

cci_bind_param
int cci_bind_param(int req_handle, int index, T_CCI_A_TYPE a_type, void *value, T_CCI_U_TYPE u_type, char flag)

The cci_bind_param function binds data in the bind variable of prepared statement. This function converts value of the given a_type to an actual binding type and stores it. Subsequently, whenever cci_execute() is called, the stored data is sent to the server. If cci_bind_param () is called multiple times for the same index, the latest configured value is valid.

Parameters:
  • req_handle -- (IN) Request handle of a prepared statement
  • index -- (IN) Location of binding; it starts with 1.
  • a_type -- (IN) Data type of value
  • value -- (IN) Data value to bind
  • u_type -- (IN) Data type to be applied to the database
  • flag -- (IN) bind_flag(CCI_BIND_PTR).
Returns:

Error code (0: success)

  • CCI_ER_BIND_INDEX
  • CCI_ER_CON_HANDLE
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_REQ_HANDLE
  • CCI_ER_TYPE_CONVERSION
  • CCI_ER_USED_CONNECTION

To bind NULL to the database, choose one of below settings.

  • Set the value of value to a NULL pointer
  • Set the value of u_type to CCI_U_TYPE_NULL

The following shows a part of code to bind NULL.

res = cci_bind_param (req, 2 /* binding index*/, CCI_A_TYPE_STR, NULL, CCI_U_TYPE_STRING, CCI_BIND_PTR);

or

res = cci_bind_param (req, 2 /* binding index*/, CCI_A_TYPE_STR, data, CCI_U_TYPE_NULL, CCI_BIND_PTR);

can be used.

If CCI_BIND_PTR is configured for flag, the pointer of value variable is copied (shallow copy), but no value is copied. If it is not configured for flag, the value of value variable is copied (deep copy) by allocating memory. If multiple columns are bound by using the same memory buffer, CCI_BIND_PTR must not be configured for the flag.

T_CCI_A_TYPE is a C language type that is used in CCI applications for data binding, and consists of primitive types such as int and float, and user-defined types defined by CCI such as T_CCI_BIT and T_CCI_DATE. The identifier for each type is defined as shown in the table below.

a_type value type
CCI_A_TYPE_STR char *
CCI_A_TYPE_INT int *
CCI_A_TYPE_FLOAT float *
CCI_A_TYPE_DOUBLE double *
CCI_A_TYPE_BIT T_CCI_BIT *
CCI_A_TYPE_SET T_CCI_SET
CCI_A_TYPE_DATE T_CCI_DATE *
CCI_A_TYPE_BIGINT int64_t * (For Windows: __int64 *)
CCI_A_TYPE_BLOB T_CCI_BLOB
CCI_A_TYPE_CLOB T_CCI_CLOB

T_CCI_U_TYPE is a column type of database and data bound though the value argument is converted into this type. The cci_bind_param () function uses two kinds of types to send information which is used to convert U-type data from A-type data; the U-type data can be interpreted by database language and the A-type data can be interpreted by C language.

There are various A-type data that are allowed by U-type data. For example, CCI_U_TYPE_INT can receive CCI_A_TYPE_STR as A-type data including CCI_A_TYPE_INT. For information on type conversion, see Implicit Type Conversion.

Both T_CCI_A_TYPE and T_CCI_U_TYPE enum(s) are defined in the cas_cci.h file. The definition of each identifier is described in the table below.

u_type Corresponding a_type (default)
CCI_U_TYPE_CHAR CCI_A_TYPE_STR
CCI_U_TYPE_STRING CCI_A_TYPE_STR
CCI_U_TYPE_BIT CCI_A_TYPE_BIT
CCI_U_TYPE_VARBIT CCI_A_TYPE_BIT
CCI_U_TYPE_NUMERIC CCI_A_TYPE_STR
CCI_U_TYPE_INT CCI_A_TYPE_INT
CCI_U_TYPE_SHORT CCI_A_TYPE_INT
CCI_U_TYPE_FLOAT CCI_A_TYPE_FLOAT
CCI_U_TYPE_DOUBLE CCI_A_TYPE_DOUBLE
CCI_U_TYPE_DATE CCI_A_TYPE_DATE
CCI_U_TYPE_TIME CCI_A_TYPE_DATE
CCI_U_TYPE_TIMESTAMP CCI_A_TYPE_DATE
CCI_U_TYPE_OBJECT CCI_A_TYPE_STR
CCI_U_TYPE_BIGINT CCI_A_TYPE_BIGINT
CCI_U_TYPE_DATETIME CCI_A_TYPE_DATE
CCI_U_TYPE_BLOB CCI_A_TYPE_BLOB
CCI_U_TYPE_CLOB CCI_A_TYPE_CLOB
CCI_U_TYPE_ENUM CCI_A_TYPE_STR

When the string including the date is used as an input parameter of DATE, DATETIME, or TIMESTAMP, "YYYY/MM/DD" or "YYYY-MM-DD" is allowed for the date string type. Therefore, "2012/01/31" or "2012-01-31" is valid, but "01/31/2012" is invalid. The following is an example of having the string that includes the date as an input parameter of the date type.

// "CREATE TABLE tbl(aa date, bb datetime)";

char *values[][3] =
{
    {"1994/11/30", "1994/11/30 20:08:08"},
    {"2008-10-31", "2008-10-31 20:08:08"}
};

req = cci_prepare(conn, "insert into tbl (aa, bb) values ( ?, ?)", CCI_PREPARE_INCLUDE_OID, &error);

for(i=0; i< 2; i++)
{
    res = cci_bind_param(req, 1, CCI_A_TYPE_STR, values[i][0], CCI_U_TYPE_DATE, (char)NULL);
    res = cci_bind_param(req, 2, CCI_A_TYPE_STR, values[i][1], CCI_U_TYPE_DATETIME, (char)NULL);
    cci_execute(req, CCI_EXEC_QUERY_ALL, 0, err_buf);
}
cci_bind_param_array
int cci_bind_param_array(int req_handle, int index, T_CCI_A_TYPE a_type, void *value, int *null_ind, T_CCI_U_TYPE u_type)

The cci_bind_param_array function binds a parameter array for a prepared cci_execute_array() is called, data is sent to the server by the stored value pointer. If cci_bind_param_array () is called multiple times for the same index, the last configured value is valid. If NULL is bound to the data, a non-zero value is configured in null_ind. If value is a NULL pointer, or u_type is CCI_U_TYPE_NULL, all data are bound to NULL and the data buffer used by value cannot be reused. For the data type of value for a_type, see the cci_bind_param() function description.

Parameters:
  • req_handle -- (IN) Request handle of the prepared statement
  • index -- (IN) Binding location
  • a_type -- (IN) Data type of value
  • value -- (IN) Data value to be bound
  • null_ind -- (IN) NULL indicator array (0 : not NULL, 1 : NULL)
  • u_type -- (IN) Data type to be applied to the database.
Returns:

Error code (0: success)

  • CCI_ER_BIND_INDEX
  • CCI_ER_BIND_ARRAY_SIZE
  • CCI_ER_CON_HANDLE
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_REQ_HANDLE
  • CCI_ER_TYPE_CONVERSION
  • CCI_ER_USED_CONNECTION

cci_bind_param_array_size
int cci_bind_param_array_size(int req_handle, int array_size)

The cci_bind_param_array_size function determines the size of the array to be used in cci_bind_param_array(). cci_bind_param_array_size () must be called first before cci_bind_param_array() is used.

Parameters:
  • req_handle -- Request handle of a prepared statement
  • array_size -- (IN) binding array size
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_REQ_HANDLE
  • CCI_ER_USED_CONNECTION

cci_bind_param_ex
int cci_bind_param_ex(int req_handle, int index, T_CCI_A_TYPE a_type, void *value, int length, T_CCI_U_TYPE u_type, char flag)

The cci_bind_param_ex function works as the same with cci_bind_param(). However, it has an additional argument, length, which specifies the byte length of a string if bound data is a string.

Parameters:
  • req_handle -- (IN) Request handle of the prepared statement
  • index -- (IN) Binding location, starting from 1
  • a_type -- (IN) Data type of value
  • value -- (IN) Data value to be bound
  • length -- (IN) Byte length of a string to be bound
  • u_type -- (IN) Data type to be applied to the database.
  • flag -- (IN) bind_flag(CCI_BIND_PTR).
Returns:

Error code(0: success)

The length argument can be used for binding a string which includes '\0' as below.

cci_bind_param_ex(statement, 1, CCI_A_TYPE_STR, "aaa\0bbb", 7, CCI_U_TYPE_STRING, 0);
cci_blob_free
int cci_blob_free(T_CCI_BLOB blob)

The cci_blob_free function frees memory of blob struct.

Returns:Error code (0: success)
  • CCI_ER_INVALID_LOB_HANDLE
cci_blob_new
int cci_blob_new(int conn_handle, T_CCI_BLOB* blob, T_CCI_ERROR* error_buf)

The cci_blob_new function creates an empty file where LOB data is stored and returns locator referring to the data to blob struct.

Parameters:
  • conn_handle -- (IN) Connection handle
  • blob -- (OUT) LOB locator
  • error_buf -- (OUT) Error buffer
Returns:

Error code (0: success)

  • CCI_ER_COMMUNICATION
  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_DBMS
  • CCI_ER_INVALID_LOB_HANDLE
  • CCI_ER_LOGIN_TIMEOUT
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_USED_CONNECTION

cci_blob_read
int cci_blob_read(int conn_handle, T_CCI_BLOB blob, long start_pos, int length, char *buf, T_CCI_ERROR* error_buf)

The cci_blob_read function reads as much as data from start_pos to length of the LOB data file specified in blob; then it stores it in buf and returns it.

Parameters:
  • conn_handle -- (IN) Connection handle
  • blob -- (OUT) LOB locator
  • start_pos -- (IN) Index location of LOB data file
  • length -- (IN) LOB data length from buffer
  • buf -- (IN) Data buffer to read
  • error_buf -- (OUT) Error buffer
Returns:

Size of read value (>= 0: success), Error code (< 0: error)

  • CCI_ER_COMMUNICATION
  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_DBMS
  • CCI_ER_INVALID_LOB_HANDLE
  • CCI_ER_INVALID_LOB_READ_POS
  • CCI_ER_LOGIN_TIMEOUT
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_QUERY_TIMEOUT
  • CCI_ER_USED_CONNECTION

cci_blob_size
long long cci_blob_size(T_CCI_BLOB* blob)

The cci_blob_size function returns data file size that is specified in blob.

Parameters:
  • blob -- (OUT) LOB locator
Returns:

Size of BLOB data file (>= 0: success), Error code (< 0: error)

  • CCI_ER_INVALID_LOB_HANDLE

cci_blob_write
int cci_blob_write(int conn_handle, T_CCI_BLOB blob, long start_pos, int length, const char *buf, T_CCI_ERROR* error_buf)

The cci_blob_write function reads as much as data from buf to length and stores it from start_pos of the LOB data file specified in blob.

Parameters:
  • conn_handle -- (IN) Connection handle
  • blob -- (OUT) LOB locator
  • start_pos -- (IN) Index location of LOB data file
  • length -- (IN) Data length from buffer
  • buf -- (OUT) Data buffer to write
  • error_buf -- (OUT) Error buffer
Returns:

Size of written value (>= 0: success), Error code (< 0: error)

  • CCI_ER_COMMUNICATION
  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_DBMS
  • CCI_ER_INVALID_LOB_HANDLE
  • CCI_ER_LOGIN_TIMEOUT
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_QUERY_TIMEOUT
  • CCI_ER_USED_CONNECTION

cci_cancel
int cci_cancel(int conn_handle)

Cancel the running query on the other thread. This function executes the same behavior as Statement.cancel() method in JAVA.

Parameters:
  • conn_handle -- (IN) Connection handle
Returns:

Error code

  • CCI_ER_COMMUNICATION
  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT

The following shows how to cancel the query execution of a thread.

/* gcc -o pthr pthr.c -m64 -I${CUBRID}/include -lnsl ${CUBRID}/lib/libcascci.so -lpthread
*/


#include <stdio.h>
#include <cas_cci.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <time.h>

#define QUERY "select * from db_class A, db_class B, db_class C, db_class D, db_class E"

static void *thread_main (void *arg);
static void *execute_statement (int con, char *sql_stmt);

int
main (int argc, char *argv[])
{
    int thr_id = 0, conn_handle = 0, res = 0;
    void *jret;
    pthread_t th;
    char url[1024];
    T_CCI_ERROR error;
    snprintf (url, 1024, "cci:CUBRID:localhost:33000:demodb:PUBLIC::");

    conn_handle = cci_connect_with_url_ex (url, NULL, NULL, &error);

    if (conn_handle < 0)
    {
        printf ("ERROR: %s\n", error.err_msg);
        return -1;
    }

    res = pthread_create (&th, NULL, &thread_main, (void *) &conn_handle);

    if (res < 0)
    {
        printf ("thread fork failed.\n");
        return -1;
    }
    else
    {
        printf ("thread started\n");
    }
    sleep (5);
    // If thread_main is still running, below cancels the query of thread_main.
    res = cci_cancel (conn_handle);
    if (res < 0)
    {
        printf ("cci_cancel failed\n");
        return -1;
    }
    else
    {
        printf ("The query was canceled by cci_cancel.\n");
    }
    res = pthread_join (th, &jret);
    if (res < 0)
    {
        printf ("thread join failed.\n");
        return -1;
    }

    printf ("thread_main was cancelled with\n\t%s\n", (char *) jret);
    free (jret);

    res = cci_disconnect (conn_handle, &error);
    if (res < 0)
    {
        printf ("ERROR: %s\n", error.err_msg);
      return res;
    }

    return 0;
}

void *
thread_main (void *arg)
{
    int con = *((int *) arg);
    int ret_val;
    void *ret_ptr;
    T_CCI_ERROR error;

    cci_set_autocommit (con, CCI_AUTOCOMMIT_TRUE);
    ret_ptr = execute_statement (con, QUERY);
    return ret_ptr;
}

static void *
execute_statement (int con, char *sql_stmt)
{
    int col_count = 1, ind, i, req;
    T_CCI_ERROR error;
    char *buffer;
    char *error_msg;
    int res = 0;

    error_msg = (char *) malloc (128);
    if ((req = cci_prepare (con, sql_stmt, 0, &error)) < 0)
    {
        snprintf (error_msg, 128, "cci_prepare ERROR: %s\n", error.err_msg);
        goto conn_err;
    }

    if ((res = cci_execute (req, 0, 0, &error)) < 0)
    {
        snprintf (error_msg, 128, "cci_execute ERROR: %s\n", error.err_msg);
        goto execute_error;
    }

    if (res >= 0)
    {
        while (1)
        {
            res = cci_cursor (req, 1, CCI_CURSOR_CURRENT, &error);
            if (res == CCI_ER_NO_MORE_DATA)
            {
                break;
            }
            if (res < 0)
            {
                snprintf (error_msg, 128, "cci_cursor ERROR: %s\n",
                    error.err_msg);
                return error_msg;
            }

            if ((res = cci_fetch (req, &error)) < 0)
            {
                snprintf (error_msg, 128, "cci_fetch ERROR: %s\n",
                    error.err_msg);
                return error_msg;
            }

            for (i = 1; i <= col_count; i++)
            {
                if ((res = cci_get_data (req, i, CCI_A_TYPE_STR, &buffer, &ind)) < 0)
                {
                    snprintf (error_msg, 128, "cci_get_data ERROR\n");
                    return error_msg;
                }
            }
        }
    }

    if ((res = cci_close_query_result (req, &error)) < 0)
    {
        snprintf (error_msg, 128, "cci_close_query_result ERROR: %s\n", error.err_msg);
        return error_msg;
    }
execute_error:
    if ((res = cci_close_req_handle (req)) < 0)
    {
        snprintf (error_msg, 128, "cci_close_req_handle ERROR\n");
    }
conn_err:
    return error_msg;
}
cci_clob_free
int cci_clob_free(T_CCI_CLOB clob)

The cci_clob_free function frees memory of CLOB struct.

Parameters:
  • clob -- (IN) LOB locator
Returns:

Error code (0: success)

  • CCI_ER_INVALID_LOB_HANDLE

cci_clob_new
int cci_clob_new(int conn_handle, T_CCI_CLOB* clob, T_CCI_ERROR* error_buf)

The cci_clob_new function creates an empty file where LOB data is stored and returns locator referring to the data to clob struct.

Parameters:
  • conn_handle -- ((IN) Connection handle
  • clob -- (OUT) LOB locator
  • error_buf -- (OUT) Error buffer
Returns:

Error code (0: success)

  • CCI_ER_COMMUNICATION
  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_DBMS
  • CCI_ER_INVALID_LOB_HANDLE
  • CCI_ER_LOGIN_TIMEOUT
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_USED_CONNECTION

cci_clob_read
int cci_clob_read(int conn_handle, T_CCI_CLOB clob, long start_pos, int length, char *buf, T_CCI_ERROR* error_buf)

The cci_clob_read function reads as much as data from start_pos to length in the LOB data file specified in clob; then it stores it in buf and returns it.

Parameters:
  • conn_handle -- (IN) Connection handle
  • clob -- (IN) LOB locator
  • start_pos -- (IN) Index location of LOB data file
  • length -- (IN) LOB data length from buffer
  • buf -- (IN) Data buffer to read
  • error_buf -- (OUT) Error buffer
Returns:

Size of read value (>= 0: success), Error code (< 0: Error)

  • CCI_ER_COMMUNICATION
  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_DBMS
  • CCI_ER_INVALID_LOB_HANDLE
  • CCI_ER_INVALID_LOB_READ_POS
  • CCI_ER_LOGIN_TIMEOUT
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_QUERY_TIMEOUT
  • CCI_ER_USED_CONNECTION

cci_clob_size
long long cci_clob_size(T_CCI_CLOB* clob)

The cci_clob_size function returns data file size that is specified in clob.

Parameters:
  • clob -- (IN) LOB locator
Returns:

Size of CLOB data file (>= 0: success), Error code (< 0: error)

  • CCI_ER_INVALID_LOB_HANDLE

cci_clob_write
int cci_clob_write(int conn_handle, T_CCI_CLOB clob, long start_pos, int length, const char *buf, T_CCI_ERROR* error_buf)

The cci_clob_write function reads as much as data from buf to length and then stores the value from start_pos in LOB data file specified in clob.

Parameters:
  • conn_handle -- (IN) Connection handle
  • clob -- (IN) LOB locator
  • start_pos -- (IN) Index location of LOB data file
  • length -- (IN) Data length from buffer
  • buf -- (OUT) Data buffer to write
  • error_buf -- (OUT) Error buffer
Returns:

Size of written value (>= 0: success), Error code (< 0: Error)

  • CCI_ER_COMMUNICATION
  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_DBMS
  • CCI_ER_INVALID_LOB_HANDLE
  • CCI_ER_LOGIN_TIMEOUT
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_QUERY_TIMEOUT
  • CCI_ER_USED_CONNECTION

cci_close_query_result
int cci_close_query_result(int req_handle, T_CCI_ERROR *err_buf)

The cci_close_query_result funciton closes the resultset returned by cci_execute(), cci_execute_array() or cci_execute_batch(). If you run cci_prepare() repeatedly without closing the request handle(req_handle), it is recommended to call this function before calling cci_close_req_handle().

Parameters:
  • req_handle -- (IN) Request handle
  • err_buf -- (OUT) Error buffer
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_COMMUNICATION
  • CCI_ER_DBMS
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_REQ_HANDLE
  • CCI_ER_RESULT_SET_CLOSED
  • CCI_ER_USED_CONNECTION

cci_close_req_handle
int cci_close_req_handle(int req_handle)

The cci_close_req_handle function closes the request handle obtained by cci_prepare().

Parameters:
  • req_handle -- (IN) Request handle
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_REQ_HANDLE
  • CCI_ER_COMMUNICATION
  • CCI_ER_DBMS
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_USED_CONNECTION

cci_col_get
int cci_col_get(int conn_handle, char *oid_str, char *col_attr, int *col_size, int *col_type, T_CCI_ERROR *err_buf)

The cci_col_get function gets an attribute value of collection type. If the name of the class is C, and the domain of set_attr is set (multiset, sequence), the query looks like as follows:

SELECT a FROM C, TABLE(set_attr) AS t(a) WHERE C = oid;

That is, the number of members becomes the number of records.

Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • col_attr -- (IN) Collection attribute name
  • col_size -- (OUT) Collection size (-1 : null)
  • col_type -- (OUT) Collection type (set, multiset, sequence: u_type)
  • err_buf -- (OUT) Database error buffer
Returns:

Request handle

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_OBJECT
  • CCI_ER_DBMS

cci_col_seq_drop
int cci_col_seq_drop(int conn_handle, char *oid_str, char *col_attr, int index, T_CCI_ERROR *err_buf)

The cci_col_seq_drop function drops the index-th (base: 1) member of the sequence attribute values. The following example shows how to drop the first member of the sequence attribute values.

cci_col_seq_drop(conn_handle, oid_str, seq_attr, 1, err_buf);
Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • col_attr -- (IN) Collection attribute name
  • index -- (IN) Index
  • err_buf -- (OUT) Database error buffer
Returns:

Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_OBJECT
  • CCI_ER_DBMS

cci_col_seq_insert
int cci_col_seq_insert(int conn_handle, char *oid_str, char *col_attr, int index, char *value, T_CCI_ERROR *err_buf)

The cci_col_seq_insert function inserts one member at the index-th (base: 1) position of the sequence attribute values. The following example shows how to insert "a" at the first position of the sequence attribute values.

cci_col_seq_insert(conn_handle, oid_str, seq_attr, 1, "a", err_buf);
Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • col_attr -- (IN) Collection attribute name
  • index -- (IN) Index
  • value -- (IN) Sequential element (string)
  • err_buf -- (OUT) Database error buffer
Returns:

Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_OBJECT
  • CCI_ER_DBMS

cci_col_seq_put
int cci_col_seq_put(int conn_handle, char *oid_str, char *col_attr, int index, char *value, T_CCI_ERROR *err_buf)

The cci_col_seq_put function replaces the index-th (base: 1) member of the sequence attribute values with a new value. The following example shows how to replace the first member of the sequence attributes values with "a".

cci_col_seq_put(conn_handle, oid_str, seq_attr, 1, "a", err_buf);
Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • col_attr -- (IN) Collection attribute name
  • index -- (IN) Index
  • value -- (IN) Sequential value
  • err_buf -- (OUT) Database error buffer
Returns:

Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_OBJECT
  • CCI_ER_DBMS

cci_col_set_add
int cci_col_set_add(int conn_handle, char *oid_str, char *col_attr, char *value, T_CCI_ERRROR *err_buf)

The cci_col_set_add function adds one member to the set attribute values. The following example shows how to add "a" to the set attribute values.

cci_col_set_add(conn_handle, oid_str, set_attr, "a", err_buf);
Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • col_attr -- (IN) collection attribute name
  • value -- (IN) set element
  • err_buf -- (OUT) Database error buffer
Returns:

Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_OBJECT
  • CCI_ER_DBMS

cci_col_set_drop
int cci_col_set_drop(int conn_handle, char *oid_str, char *col_attr, char *value, T_CCI_ERROR *err_buf)

The cci_col_set_drop function drops one member from the set attribute values. The following example shows how to drop "a" from the set attribute values.

cci_col_set_drop(conn_handle, oid_str, set_attr, "a", err_buf);
Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • col_attr -- (IN) collection attribute name
  • value -- (IN) set element (string)
  • err_buf -- (OUT) Database error buffer
Returns:

Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_QUERY_TIMEOUT
  • CCI_ER_LOGIN_TIMEOUT
  • CCI_ER_COMMUNICATION

cci_col_size
int cci_col_size(int conn_handle, char *oid_str, char *col_attr, int *col_size, T_CCI_ERROR *err_buf)

The cci_col_size function gets the size of the set (seq) attribute.

Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • col_attr -- (IN) Collection attribute name
  • col_size -- (OUT) Collection size (-1: NULL)
  • err_buf -- Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_OBJECT
  • CCI_ER_DBMS

cci_connect
int cci_connect(char *ip, int port, char *db_name, char *db_user, char *db_password)

A connection handle to the database server is assigned and it tries to connect to the server. If it has succeeded, the connection handle ID is returned; if fails, an error code is returned.

Parameters:
  • ip -- (IN) A string that represents the IP address of the server (host name)
  • port -- (IN) Broker port (The port configured in the $CUBRID/conf/cubrid_broker.conf file)
  • db_name -- (IN) Database name
  • db_user -- (IN) Database user name
  • db_passwd -- (IN) Database user password
Returns:

Success: Connection handle ID (int), Failure: Error code

  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_HOSTNAME
  • CCI_ER_CON_HANDLE
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_CONNECT

cci_connect_ex
int cci_connect_ex(char *ip, int port, char *db_name, char *db_user, char *db_password, T_CCI_ERROR * err_buf)

The cci_connect_ex function returns CCI_ER_DBMS error and checks the error details in the database error buffer (err_buf) at the same time. In that point, it is different from cci_connect() and the others are the same as the cci_connect() function.

Parameters:
  • ip -- (IN) A string that represents the IP address of the server (host name)
  • port -- (IN) Broker port (The port configured in the $CUBRID/conf/cubrid_broker.conf file)
  • db_name -- (IN) Database name
  • db_user -- (IN) Database user name
  • db_passwd -- (IN) Database user password
  • err_buf -- Database error buffer
Returns:

Success: Connection handle ID (int), Failure: Error code

  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_HOSTNAME
  • CCI_ER_CON_HANDLE
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_CONNECT

cci_connect_with_url
int cci_connect_with_url(char *url, char *db_user, char *db_password)

The cci_connect_with_url function connects a database by using connection information passed with a url argument. If broker's HA feature is used in CCI, you must specify the connection information of the standby broker server with altHosts property, which is used for the failover, in the url argument of this function. It returns the ID of a connection handle on success; it returns an error code on failure. For details about HA features of broker, see Duplexing Brokers.

Parameters:
  • url -- (IN) A string that contains server connection information.
  • db_user -- (IN) Database user name. If this is NULL, it becomes <db_user> in url. If this is an empty string ("") or <db_user> in url is not specified, DB user name becomes PUBLIC.
  • db_passwd -- (IN) Database user password. If this is NULL, <db_password> in url is used. If <db_password> in url is not specified, DB password becomes an empty string ("").
Returns:

Success: Connection handle ID (int), Failure: Error code

  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_HOSTNAME
  • CCI_ER_INVALID_URL
  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_LOGIN_TIMEOUT

<url> ::= cci:CUBRID:<host>:<port>:<db_name>:<db_user>:<db_password>:[?<properties>]

<properties> ::= <property> [&<property>]
<property> ::= altHosts=<alternative_hosts> [ &rcTime=<time>] [ &loadBalance=true|false]
             |{login_timeout|loginTimeout}=<milli_sec>
             |{query_timeout|queryTimeout}=<milli_sec>
             |{disconnect_on_query_timeout|disconnectOnQueryTimeout}=true|false
             | logFile=<file_name>
             | logBaseDir=<dir_name>
             | logSlowQueries=true|false[&slowQueryThresholdMillis=<milli_sec>]
             | logTraceApi=true|false
             | logTraceNetwork=true|false

<alternative_hosts> ::= <host>:<port> [,<host>:<port>]

<host> := HOSTNAME | IP_ADDR
<time> := SECOND
<milli_sec> := MILLI SECOND

altHosts is the property related to connection target and loginTimeout, queryTimeout, and disconnectOnQueryTimeout are the properties related to timeout; logSlowQueries, logTraceApi, and logTraceNetwork are the properties related to log information configuration for debugging. Note that a property name which is a value to be entered in the url argument is not case sensitive.

  • host: A host name or IP address of the master database

  • port: A port number

  • db_name: A name of the database

  • db_user: A name of the database user

  • db_password: A database user password. You cannot include ':' in the password of the url string.

  • altHosts = standby_broker1_host, standby_broker2_host, ...: Specifies the broker information of the standby server, which is used for failover when it is impossible to connect to the active server. You can specify multiple brokers for failover, and the connection to the brokers is attempted in the order listed in alhosts.

    Note

    Even if there are RW and RO together in ACCESS_MODE* setting of brokers of main host and altHosts, application decides the target host to access without the relation for the setting of ACCESS_MODE. Therefore, you should define the main host and altHosts as considering ACCESS_MODE of target brokers.

  • rcTime: After the failure occurred on the first connected broker, the application connects to the broker specified by altHosts(broker failover). Then it attempts to reconnect to the first connected broker at every rcTime(default value: 600 seconds).

  • loadBalance: When this value is true, the applications try to connect to the main host and alternative hosts specified with the altHosts property as a random order. (default value: false).

  • login_timeout | loginTimeout: Timeout value (unit: msec.) for database login. Upon timeout, a CCI_ER_LOGIN_TIMEOUT (-38) error is returned. The default value is 30,000(30 sec.). If this value is 0, it means infinite waiting. This value is also applied when internal reconnection occurs after the initial connection.

  • query_timeout | queryTimeout: If time specified in these properties has expired when calling cci_prepare(), cci_execute(), etc. a cancellation message for query request which was sent to a server will be delivered and called function returns a CCI_ER_QUERY_TIMEOUT (-39) error. The value returned upon timeout may vary depending on a value specified in disconnect_on_query_timeout. For details, see disconnect_on_query_timeout.

    Note

    If you use cci_execute_batch() or cci_execute_array()function, or set CCI_EXEC_QUERY_ALL in cci_execute() function to run multiple queries at once, query timeout is applied to one function, not to one query. In other words, if query timeout occurs after the start of a function, a function running is quit.

  • disconnect_on_query_timeout | disconnectOnQueryTimeout: Whether to disconnect socket immediately after time for query request has expired. It determines whether to terminate a socket connection immediately or wait for server response after sending cancellation message for query request to a server when calling cci_prepare(), cci_execute(), etc. The default value is false, meaning that it will wait for server response. It this value is true, a socket will be closed immediately after sending a cancellation message to a server upon timeout and returns the CCI_ER_QUERY_TIMEOUT (-39) error. (If an error occurs on database server side, not on broker side, it returns -1. If you want to view error details, see error codes in "database error buffer." You can get information how to check error codes in CCI Error Codes and Error Messages.) Please note that there is a possibility that a database server does not get a cancellation message and execute a query even after an error is returned.

  • logFile: A log file name for debugging (default value: cci_ <handle_id> .log). <handle_id> indicates the ID of a connection handle returned by this function.

  • logBaseDir: A directory where a debug log file is created. The file name including the path will be logBaseDir/logFile, and the relative path is possible.

  • logSlowQueries: Whether to log slow query for debugging (default value: false)

  • slowQueryThresholdMillis: Timeout for slow query logging if slow query logging is enabled (default value: 60000, unit: milliseconds)

  • logTraceApi: Whether to log the start and end of CCI functions

  • logTraceNetwork: Whether to log network data content transferred of CCI functions

Example

--connection URL string when a property(altHosts) is specified for HA
URL=cci:CUBRID:192.168.0.1:33000:demodb:::?altHosts=192.168.0.2:33000,192.168.0.3:33000

--connection URL string when properties(altHosts,rcTime) is specified for HA
URL=cci:CUBRID:192.168.0.1:33000:demodb:::?altHosts=192.168.0.2:33000,192.168.0.3:33000&rcTime=600

--connection URL string when properties(logSlowQueries,slowQueryThresholdMills, logTraceApi, logTraceNetwork) are specified for interface debugging
URL = "cci:cubrid:192.168.0.1:33000:demodb:::?logSlowQueries=true&slowQueryThresholdMillis=1000&logTraceApi=true&logTraceNetwork=true"
cci_connect_with_url_ex
int cci_connect_with_url_ex(char *url, char *db_user, char *db_password, T_CCI_ERROR * err_buf)

The cci_connect_with_url_ex function returns CCI_ER_DBMS error and checks the error details in the database error buffer (err_buf) at the same time. In that point, it is different from cci_connect_with_url() and the others are the same as the cci_connect_with_url() function.

Parameters:
  • err_buf -- Database error buffer
int cci_cursor(int req_handle, int offset, T_CCI_CURSOR_POS origin, T_CCI_ERROR *err_buf)

The cci_cursor function moves the cursor specified in the request handle to access the specific record in the query result executed by cci_execute(). The position of cursor is moved by the values specified in the origin and offset values. If the position to be moved is not valid, CCI_ER_NO_MORE_DATA is returned.

Parameters:
  • req_handle -- (IN) Request handle
  • offset -- (IN) Offset to be moved
  • origin -- (IN) Variable to represent a position. The type is T_CCI_CURSOR_POS. T_CCI_CURSOR_POS enum consists of CCI_CURSOR_FIRST, CCI_CURSOR_CURRENT and CCI_CURSOR_LAST.
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_REQ_HANDLE
  • CCI_ER_NO_MORE_DATA
  • CCI_ER_COMMUNICATION

Example

//the cursor moves to the first record
cci_cursor(req, 1, CCI_CURSOR_FIRST, &err_buf);

//the cursor moves to the next record
cci_cursor(req, 1, CCI_CURSOR_CURRENT, &err_buf);

//the cursor moves to the last record
cci_cursor(req, 1, CCI_CURSOR_LAST, &err_buf);

//the cursor moves to the previous record
cci_cursor(req, -1, CCI_CURSOR_CURRENT, &err_buf);
cci_cursor_update
int cci_cursor_update(int req_handle, int cursor_pos, int index, T_CCI_A_TYPE a_type, void *value, T_CCI_ERROR *err_buf)

The cci_cursor_update function updates cursor_pos from the value of the index -th column to value. If the database is updated to NULL, value becomes NULL. For update conditions, see cci_prepare(). The data types of value for a_type are shown in the table below.

Parameters:
  • req_handle -- (IN) Request handle
  • cursor_pos -- (IN) Cursor position
  • index -- (IN) Column index
  • a_type -- (IN) value Type
  • value -- (IN) A new value
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_REQ_HANDLE
  • CCI_ER_TYPE_CONVERSION
  • CCI_ER_ATYPE

Data types of value for a_type are as below.

a_type value type
CCI_A_TYPE_STR char *
CCI_A_TYPE_INT int *
CCI_A_TYPE_FLOAT float *
CCI_A_TYPE_DOUBLE double *
CCI_A_TYPE_BIT T_CCI_BIT *
CCI_A_TYPE_SET T_CCI_SET
CCI_A_TYPE_DATE T_CCI_DATE *
CCI_A_TYPE_BIGINT int64_t * (For Windows: __int64 *)
CCI_A_TYPE_BLOB T_CCI_BLOB
CCI_A_TYPE_CLOB T_CCI_CLOB
cci_datasource_borrow
T_CCI_CONN cci_datasource_borrow(T_CCI_DATASOURCE *datasource, T_CCI_ERROR *err_buf)

The cci_datasource_borrow function obtains CCI connection to be used in T_CCI_DATASOURCE struct.

Parameters:
  • datasource -- (IN) T_CCI_DATASOURCE struct pointer in which CCI connection exists
  • err_buf -- (OUT) Error code and message returned upon error occurrence
Returns:

Success: CCI connection handler identifier, Failure: -1

cci_datasource_change_property
int cci_datasource_change_property(T_CCI_DATASOURCE *datasource, const char *key, const char *val)

A property name of a DATASOURCE is specified in key, a value in val. The changed property value by this function is applied to all connections in the datasource.

Parameters:
  • datasource -- (IN) T_CCI_DATASOURCE struct pointer to obtain CCI connections.
  • key -- (IN) A pointer to the string of a property name
  • val -- (IN) A pointer to the string of a property value
Returns:

Error code(0: success)

  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_NO_PROPERTY
  • CCI_ER_PROPERTY_TYPE

The following shows names and values of changeable properties.

Property name Type Value Description
default_autocommit bool true/false Whether auto-commit or not. The default is CCI_DEFAULT_AUTOCOMMIT in cubrid_broker.conf; the default of this is ON(true)
default_lock_timeout msec number lock timeout
default_isolation string See the table of cci_property_set() isolation level. The default is isolation_level in cubrid.conf; the default of this is "READ COMMITTED".
login_timeout msec number login timeout. The default is 0(infinite wait). It can also be used when you call prepare or execute functions; at this time reconnection can happen.

Example

...
ps = cci_property_create ();
...
ds = cci_datasource_create (ps, &err);
...
cci_datasource_change_property(ds, "login_timeout", "5000");
cci_datasource_change_property(ds, "default_lock_timeout", "2000");
cci_datasource_change_property(ds, "default_isolation", "TRAN_REP_CLASS_COMMIT_INSTANCE");
cci_datasource_change_property(ds, "default_autocommit", "true");
...
cci_datasource_create
T_CCI_DATASOURCE * cci_datasource_create(T_CCI_PROPERTIES *properties, T_CCI_ERROR *err_buf)

The cci_datasource_create function creates DATASOURCE of CCI.

Parameters:
  • properties -- (IN) T_CCI_PROPERTIES struct pointer in which configuration of struct pointer is stored. Values of properties will be set with cci_property_set().
  • err_buf -- (OUT) Error buffer. Error code and message returned upon error occurrence
Returns:

Success: T_CCI_DATASOURCE struct pointer created, Failure: NULL

cci_datasource_destroy
void cci_datasource_destroy(T_CCI_DATASOURCE *datasource)

The cci_datasource_destroy function destroys DATASOURCE of CCI.

Parameters:
  • datasource -- (IN) T_CCI_DATASOURCE struct pointer to be deleted
Returns:

void

cci_datasource_release
int cci_datasource_release(T_CCI_DATASOURCE *datasource, T_CCI_CONN conn, T_CCI_ERROR *err_buf)

The cci_datasource_release function returns CCI connection released in T_CCI_DATASOURCE struct. If you want to reuse the connection after calling this function, recall cci_datasource_borrow().

Parameters:
  • datasource -- (IN) T_CCI_DATASOURCE struct pointer which returns CCI connection
  • conn -- (IN) CCI connection handler identifier released
  • err_buf -- (OUT) Error buffer(returns error code and error message when an error occurs)
Returns:

Success: 1, Failure: 0

cci_disconnect
int cci_disconnect(int conn_handle, T_CCI_ERROR *err_buf)

The cci_disconnect function disconnects all request handles created for conn_handle. If a transaction is being performed, the handles are disconnected after cci_end_tran() is executed.

Parameters:
  • conn_handle -- (IN) Connection handle
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION

cci_end_tran
int cci_end_tran(int conn_handle, char type, T_CCI_ERROR *err_buf)

The cci_end_tran function performs commit or rollback on the current transaction. At this point, all open request handles are terminated and the connection to the database server is disabled. However, even after the connection to the server is disabled, the connection handle remains valid.

Parameters:
  • conn_handle -- (IN) Connection handle
  • type -- (IN) CCI_TRAN_COMMIT or CCI_TRAN_ROLLBACK
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_TRAN_TYPE

You can configure the default value of auto-commit mode by using CCI_DEFAULT_AUTOCOMMIT broker parameter upon startup of an application. If configuration on broker parameter is omitted, the default value is ON; use the cci_set_autocommit() function to change auto-commit mode within an application. If auto-commit mode is OFF, you must explicitly commit or roll back transaction by using the cci_end_tran() function.

cci_escape_string
long cci_escape_string(int conn_handle, char *to, const char *from, unsigned long length, T_CCI_ERROR *err_buf)

Converts the input string to a string that can be used in the CUBRID query. The following parameters are specified in this function: connection handle or no_backslash_escapes setting value, output string pointer, input string pointer, the length of the input string, and the address of the T_CCI_ERROR struct variable.

Parameters:
  • conn_handle -- (IN) connection handle or no_backslash_escapes setting value. When a connection handle is given, the no_backslash_escapes parameter value is read to determine how to convert. Instead of the connection handle, CCI_NO_BACKSLASH_ESCAPES_TRUE or CCI_NO_BACKSLASH_ESCAPES_FALSE value can be sent to determine how to convert.
  • to -- (OUT) Result string
  • from -- (IN) Input string
  • length -- (IN) Maximum byte length of the input string
  • err_buf -- (OUT) Database error buffer
Returns:

Success: Byte length of the changed string, Failure: Error Code

  • CCI_ER_CON_HANDLE
  • CCI_ER_COMMUNICATION

When the system parameter no_backslash_escapes is yes (default) or when the CCI_NO_BACKSLASH_ESCAPES_TRUE value is sent to the connection handle location, the string is converted to the following characters.

  • ' (single quote) => ' + ' (escaped single quote)

When the system parameter no_backslash_escapes is no or when the CCI_NO_BACKSLASH_ESCAPES_FALSE value is sent to the connection handle location, the string is converted to the following characters:

  • \n (new line character, ASCII 10) => \ + n (backslash + Alphabet n)
  • \r (carriage return, ASCII 13) => \ + r (backslash + Alphabet r)
  • \0 (ASCII 0) => \ + 0 (backslash + 0(ASCII 48)
  • \ (backslash) => \ + \

You can assign the space where the result string will be saved by using the length parameter. It will take as much as the byte length of the maximum input string * 2 + 1.

cci_execute
int cci_execute(int req_handle, char flag, int max_col_size, T_CCI_ERROR *err_buf)

The cci_execute function executes the SQL statement (prepared statement) that has executed cci_prepare(). A request handle, flag, the maximum length of a column to be fetched, and the address of a T_CCI_ERROR construct variable in which error information being stored are specified as arguments.

Parameters:
  • req_handle -- (IN) Request handle of the prepared statement
  • flag -- (IN) exec flag ( CCI_EXEC_QUERY_ALL )
  • max_col_size -- (IN) The maximum length of a column to be fetched when it is a string data type in bytes. If this value is 0, full length is fetched.
  • err_buf -- (OUT) Database error buffer
Returns:

  • SELECT : Returns the number of results
  • INSERT, UPDATE : Returns the number of rows reflected
  • Others queries : 0
  • Failure : Error code
    • CCI_ER_REQ_HANDLE
    • CCI_ER_BIND
    • CCI_ER_DBMS
    • CCI_ER_COMMUNICATION
    • CCI_ER_QUERY_TIMEOUT
    • CCI_ER_LOGIN_TIMEOUT

Through a flag, the way of query execution can be set as all queries or the first one.

Note

In 2008 R4.4 and from 9.2, CUBRID does not support setting the flag as CCI_EXEC_ASYNC, which brings the results as an asynchronous method.

If the flag is set to CCI_EXEC_QUERY_ALL, all prepared queries(separated by semicolon) are executed. If not, only the first query is executed.

If the flag is set to CCI_EXEC_QUERY_ALL, the following rules are applied.

  • The return value is the result of the first query.
  • If an error occurs in any query, the execution is processed as a failure.
  • For a query composed of in a query composed of q1; q2; q3, even if an error occurs in q2 after q1 succeeds the execution, the result of q1 remains valid. That is, the previous successful query executions are not rolled back when an error occurs.
  • If a query is executed successfully, the result of the second query can be obtained using cci_next_result().

max_col_size is a value that is used to determine the maximum length of a column to be sent to a client when the columns of the prepared statement are CHAR, VARCHAR, BIT or VARBIT. If this value is 0, full length is fetched.

cci_execute_array
int cci_execute_array(int req_handle, T_CCI_QUERY_RESULT **query_result, T_CCI_ERROR *err_buf)

If more than one value is bound to the prepared statement, this gets the values of the variables to be bound and executes the query by binding each value to the variable.

Parameters:
  • req_handle -- (IN) Request handle of the prepared statement
  • query_result -- (OUT) Query results
  • err_buf -- (OUT) Database error buffer
Returns:

Success: The number of executed queries, Failure: Negative number

  • CCI_ER_REQ_HANDLE
  • CCI_ER_BIND
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_QUERY_TIMEOUT
  • CCI_ER_LOGIN_TIMEOUT

To bind the data, call the cci_bind_param_array_size() function to specify the size of the array, bind each value to the variable by using the cci_bind_param_array() function, and execute the query by calling the cci_execute_array() function. The query result will be stored on the array of T_CCI_QUERY_RESULT structure.

cci_execute_array() function returns the results of queries to the query_result variable. You can use below macros to get the result of each query. In the macro, note that the validation check for each parameter entered is not performed.

After using the query_result variable, you must delete the query_result by using the cci_query_result_free() function.

Macro Return Type Description
CCI_QUERY_RESULT_RESULT int the number of affected rows or error identifier (-1: CAS error, -2: DBMS error)
CCI_QUERY_RESULT_ERR_NO int error number about a query
CCI_QUERY_RESULT_ERR_MSG char * error message about a query
CCI_QUERY_RESULT_STMT_TYPE int(T_CCI_CUBRID_STMT enum) type of a query statement

If autocommit mode is on, each query in the array is committed after executing.

Note

  • In the previous version of 2008 R4.3, if the autocommit mode is on, all queries in the array were committed after all of them are executed. From 2008 R4.3 version, the transaction is committed every time when a query is executed.
  • In autocommit mode off, if the general error occurs during executing one of the queries in the array on the cci_execute_array function which does a batch processing of the queries, the query with an error is ignored and the next query is executed continuously. But if the deadlock occurs, the error occurs as rolling back the transaction.
char *query =
    "update participant set gold = ? where host_year = ? and nation_code = 'KOR'";
int gold[2];
char *host_year[2];
int null_ind[2];
T_CCI_QUERY_RESULT *result;
int n_executed;
...

req = cci_prepare (con, query, 0, &cci_error);
if (req < 0)
{
    printf ("prepare error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
    goto handle_error;
}

gold[0] = 20;
host_year[0] = "2004";

gold[1] = 15;
host_year[1] = "2008";

null_ind[0] = null_ind[1] = 0;
error = cci_bind_param_array_size (req, 2);
if (error < 0)
{
    printf ("bind_param_array_size error: %d\n", error);
    goto handle_error;
}

error =
    cci_bind_param_array (req, 1, CCI_A_TYPE_INT, gold, null_ind, CCI_U_TYPE_INT);
if (error < 0)
{
    printf ("bind_param_array error: %d\n", error);
    goto handle_error;
}
error =
    cci_bind_param_array (req, 2, CCI_A_TYPE_STR, host_year, null_ind, CCI_U_TYPE_INT);
if (error < 0)
{
    printf ("bind_param_array error: %d\n", error);
    goto handle_error;
}

n_executed = cci_execute_array (req, &result, &cci_error);
if (n_executed < 0)
{
    printf ("execute error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
    goto handle_error;
}
for (i = 1; i <= n_executed; i++)
{
    printf ("query %d\n", i);
    printf ("result count = %d\n", CCI_QUERY_RESULT_RESULT (result, i));
    printf ("error message = %s\n", CCI_QUERY_RESULT_ERR_MSG (result, i));
    printf ("statement type = %d\n",
            CCI_QUERY_RESULT_STMT_TYPE (result, i));
}
error = cci_query_result_free (result, n_executed);
if (error < 0)
{
    printf ("query_result_free: %d\n", error);
    goto handle_error;
}
error = cci_end_tran(con, CCI_TRAN_COMMIT, &cci_error);
if (error < 0)
{
    printf ("end_tran: %d, %s\n", cci_error.err_code, cci_error.err_msg);
    goto handle_error;
}
cci_execute_batch
int cci_execute_batch(int conn_handle, int num_sql_stmt, char **sql_stmt, T_CCI_QUERY_RESULT **query_result, T_CCI_ERROR *err_buf)

In CCI, multiple jobs can be processed simultaneously when using DML queries such as INSERT / UPDATE / DELETE. CCI_QUERY_RESULT_RESULT and cci_execute_batch() functions can be used to execute such batch jobs. Note that prepared statements cannot be used in the cci_execute_batch() function. The query result will be stored on the array of T_CCI_QUERY_RESULT structure.

Parameters:
  • conn_handle -- (IN) Connection handle
  • num_sql_stmt -- (IN) The number of sql_stmt
  • sql_stmt -- (IN) SQL statement array
  • query_result -- (OUT) The results of sql_stmt
  • err_buf -- (OUT) Database error buffer
Returns:

Success: The number of executed queries, Failure: Negative number

  • CCI_ER_CON_HANDLE
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_CONNECT
  • CCI_ER_QUERY_TIMEOUT
  • CCI_ER_LOGIN_TIMEOUT

Executes sql_stmt as many times as num_sql_stmt specified as a parameter and returns the number of queries executed with the query_result variable. You can use CCI_QUERY_RESULT_RESULT, c:macro:CCI_QUERY_RESULT_ERR_NO, CCI_QUERY_RESULT_ERR_MSG and CCI_QUERY_RESULT_STMT_TYPE macros to get the result of each query. Regarding the summary of these macros, see the cci_execute_array() function.

Note that the validity check is not performed for each parameter entered in the macro.

After using the query_result variable, you must delete the query result by using the cci_query_result_free() function.

If autocommit mode is on, each query in the array is committed after executing.

Note

  • In the previous version of 2008 R4.3, if the autocommit is on, all queries in the array were committed after all of them are executed. From 2008 R4.3 version, each query in the array is committed right after each running.
  • If autocommit mode is off, after the general error occurs during executing one of the queries in the array on the cci_execute_batch function which does a batch processing of the queries, the query with an error is ignored and the next query is executed. But if the deadlock occurs, the error occurs as rolling back the transaction.
...
char **queries;
T_CCI_QUERY_RESULT *result;
int n_queries, n_executed;
...
count = 3;
queries = (char **) malloc (count * sizeof (char *));
queries[0] =
    "insert into athlete(name, gender, nation_code, event) values('Ji-sung Park', 'M', 'KOR', 'Soccer')";
queries[1] =
    "insert into athlete(name, gender, nation_code, event) values('Joo-young Park', 'M', 'KOR', 'Soccer')";
queries[2] =
    "select * from athlete order by code desc limit 2";

//calling cci_execute_batch()
n_executed = cci_execute_batch (con, count, queries, &result, &cci_error);
if (n_executed < 0)
{
    printf ("execute_batch: %d, %s\n", cci_error.err_code, cci_error.err_msg);
    goto handle_error;
}
printf ("%d statements were executed.\n", n_executed);

for (i = 1; i <= n_executed; i++)
{
    printf ("query %d\n", i);
    printf ("result count = %d\n", CCI_QUERY_RESULT_RESULT (result, i));
    printf ("error message = %s\n", CCI_QUERY_RESULT_ERR_MSG (result, i));
    printf ("statement type = %d\n",
            CCI_QUERY_RESULT_STMT_TYPE (result, i));
}

error = cci_query_result_free (result, n_executed);
if (error < 0)
{
    printf ("query_result_free: %d\n", error);
    goto handle_error;
}
...
cci_execute_result
int cci_execute_result(int req_handle, T_CCI_QUERY_RESULT **query_result, T_CCI_ERROR *err_buf)

The cci_execute_result function stores the execution results (e.g. statement type, result count) performed by cci_execute() to the array of T_CCI_QUERY_RESULT structure. You can use CCI_QUERY_RESULT_RESULT, CCI_QUERY_RESULT_ERR_NO, CCI_QUERY_RESULT_ERR_MSG, CCI_QUERY_RESULT_STMT_TYPE macros to get the results of each query. Regarding the summary of these macros, see the cci_execute_array() function.

Note that the validity check is not performed for each parameter entered in the macro.

The memory of used query results must be released by the cci_query_result_free() function.

Parameters:
  • req_handle -- (IN) Request handle of the prepared statement
  • query_result -- (OUT) Query results
  • err_buf -- (OUT) Database error buffer
Returns:

Success: The number of queries, Failure: Negative number

  • CCI_ER_REQ_HANDLE
  • CCI_ER_COMMUNICATION

...
T_CCI_QUERY_RESULT *qr;
...

cci_execute( ... );
res = cci_execute_result(req_h, &qr, &err_buf);
if (res < 0)
{
    /* error */
}
else
{
    for (i=1 ; i <= res ; i++)
    {
        result_count = CCI_QUERY_RESULT_RESULT(qr, i);
        stmt_type = CCI_QUERY_RESULT_STMT_TYPE(qr, i);
    }
    cci_query_result_free(qr, res);
}
...
cci_fetch
int cci_fetch(int req_handle, T_CCI_ERROR *err_buf)

The cci_fetch function fetches the query result executed by cci_execute() from the server-side CAS and stores it to the client buffer. The cci_get_data() function can be used to identify the data of a specific column from the fetched query result.

Parameters:
  • req_handle -- (IN) Request handle
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_REQ_HANDLE
  • CAS_ER_HOLDABLE_NOT_ALLOWED
  • CCI_ER_NO_MORE_DATA
  • CCI_ER_RESULT_SET_CLOSED
  • CCI_ER_DELETED_TUPLE
  • CCI_ER_COMMUNICATION
  • CCI_ER_NO_MORE_MEMORY

cci_fetch_buffer_clear
int cci_fetch_buffer_clear(int req_handle)

The cci_fetch_buffer_clear function clears the records temporarily stored in the client buffer.

Parameters:
  • req_handle -- Request handle
Returns:

Error code (0: success)

  • CCI_ER_REQ_HANDLE

cci_fetch_sensitive
int cci_fetch_sensitive(int req_handle, T_CCI_ERROR *err_buf)

The cci_fetch_sensitive function sends changed values for sensitive column when the SELECT query result is delivered. If the results by req_handle are not sensitive, they are same as the ones by cci_fetch(). The return value of CCI_ER_DELETED_TUPLE means that the given row has been deleted.

Parameters:
  • req_handle -- (IN) Request handle
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_REQ_HANDLE
  • CCI_ER_NO_MORE_DATA
  • CCI_ER_COMMUNICATION
  • CCI_ER_DBMS
  • CCI_ER_DELETED_TUPLE

sensitive column means the item that can provide updated value in the SELECT list when you re-request the results. For example, if a column is directly used as an item of the SELECT list without aggregation operation, this column can be called a sensitive column.

When you fetch the result again, the sensitive result receive the data from the server, not from the client buffer.

cci_fetch_size
int cci_fetch_size(int req_handle, int fetch_size)

This function is deprecated. Even if it's called, there will be ignored.

cci_get_autocommit
CCI_AUTOCOMMIT_MODE cci_get_autocommit(int conn_handle)

The cci_get_autocommit function returns the auto-commit mode currently configured.

Parameters:
  • conn_handle -- (IN) Connection handle
Returns:

  • CCI_AUTOCOMMIT_TRUE: Auto-commit mode is ON
  • CCI_AUTOCOMMIT_FALSE: Auto-commit mode is OFF
  • CCI_ER_CON_HANDLE
  • CCI_ER_USED_CONNECTION

cci_get_bind_num
int cci_get_bind_num(int req_handle)

The cci_get_bind_num function gets the number of input bindings. If the SQL statement used during preparation is composed of multiple queries, it represents the number of input bindings used in all queries.

Parameters:
  • req_handle -- (IN) Request handle for the prepared statement
Returns:

The number of input bindings

  • CCI_ER_REQ_HANDLE

cci_get_cas_info
int cci_get_cas_info(int conn_handle, char *info_buf, int buf_length, T_CCI_ERROR * err_buf)

Retrieve CAS information which is connected to conn_handle. The string of the below format is returned to the info_buf.

<host>:<port>,<cas id>,<cas process id>

The below is an example.

127.0.0.1:33000,1,12916

Through CAS ID, you can check the SQL log file of this CAS easily.

For details, see Checking SQL Log.

Parameters:
  • conn_handle -- (IN) connection handle
  • info_buf -- (OUT) connection information buffer
  • buf_length -- (IN) buffer length of the connection information
  • err_buf -- (OUT) Error buffer
Returns:

error code

  • CCI_ER_INVALID_ARGS
  • CCI_ER_CON_HANDLE

cci_get_class_num_objs
int cci_get_class_num_objs(int conn_handle, char *class_name, int flag, int *num_objs, int *num_pages, T_CCI_ERROR *err_buf)

The cci_get_class_num_objs function gets the number of objects of the class_name class and the number of pages being used. If the flag is configured to 1, an approximate value is fetched; if it is configured to 0, an exact value is fetched.

Parameters:
  • conn_handle -- (IN) Connection handle
  • class_name -- (IN) Class name
  • flag -- (IN) 0 or 1
  • num_objs -- (OUT) The number of objects
  • num_pages -- (OUT) The number of pages
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_REQ_HANDLE
  • CCI_ER_COMMUNICATION
  • CCI_ER_CONNECT

CCI_GET_COLLECTION_DOMAIN
#define CCI_GET_COLLECTION_DOMAIN(u_type)

If u_type is set, multiset, or sequence type, this macro gets the domain of the set, multiset or sequence. If u_type is not a set type, the return value is the same as u_type.

Returns:Type (CCI_U_TYPE)
cci_get_cur_oid
int cci_get_cur_oid(int req_handle, char *oid_str_buf)

The cci_get_cur_oid function gets OID of the currently fetched records if CCI_INCLUDE_OID is configured in execution. The OID is represented in string for a page, slot, or volume.

Parameters:
  • conn_handle -- (IN) Request handle
  • oid_str_buf -- (OUT) OID string
Returns:

Error code (0: success)

  • CCI_ER_REQ_HANDLE

cci_get_data
int cci_get_data(int req_handle, int col_no, int type, void *value, int *indicator)

The cci_get_data function gets the col_no -th value from the currently fetched result.

Parameters:
  • req_handle -- (IN) Request handle
  • col_no -- (IN) One-based column index. It starts with 1.
  • type -- (IN) Data type (defined in the T_CCI_A_TYPE) of value variable
  • value -- (OUT) Variable address for data to be stored. If type is one of (CCI_A_TYPE_STR, CCI_A_TYPE_SET, CCI_A_TYPE_BLOB or CCI_A_TYPE_CLOB) and the value of a column is NULL, the value will be NULL, too.
  • indicator --

    (OUT) NULL indicator. (-1 : NULL)

    • If type is CCI_A_TYPE_STR : -1 is returned in case of NULL; the length of string stored in value is returned, otherwise.
    • If type is not CCI_A_TYPE_STR : -1 is returned in case of NULL, 0 is returned, otherwise.
Returns:

Error code (0: success)

  • CCI_ER_REQ_HANDLE
  • CCI_ER_TYPE_CONVERSION
  • CCI_ER_COLUMN_INDEX
  • CCI_ER_ATYPE

The type of the value variable is determined based on the given type argument, and the value or the pointer is copied to the value variable accordingly. For a value to be copied, the memory for the address to be transferred to the value variable must have been previously assigned. Note that if a pointer is copied, a pointer in the application client library is returned, so the value becomes invalid next time the cci_get_data() function is called.

In addition, the pointer returned by the pointer copy must not be freed. However, if the type is CCI_A_TYPE_SET, the memory must be freed by using the cci_set_free() function after using the set because the set is returned after the T_CCI_SET type memory is allocated. The following table shows the summary of type arguments and data types of their corresponding value values.

type value Type Meaning
CCI_A_TYPE_STR char ** pointer copy
CCI_A_TYPE_INT int * value copy
CCI_A_TYPE_FLOAT float * value copy
CCI_A_TYPE_DOUBLE double * value copy
CCI_A_TYPE_BIT T_CCI_BIT * value copy (pointer copy for each member)
CCI_A_TYPE_SET T_CCI_SET * memory allocation and value copy
CCI_A_TYPE_DATE T_CCI_DATE * value copy
CCI_A_TYPE_BIGINT int64_t * (For Windows: __int64 *) value copy
CCI_A_TYPE_BLOB T_CCI_BLOB * memory allocation and value copy
CCI_A_TYPE_CLOB T_CCI_CLOB * memory allocation and value copy

Remark

  • For LOB type, if the cci_get_data() function is called, meta data with the LOB type column (locator) is displayed. To call data of the LOB type column, the cci_blob_read() function should be called.

The below example shows a part of a code to print out the fetched result with cci_get_data().

...

if ((res=cci_get_data(req, i, CCI_A_TYPE_INT, &buffer, &ind))<0) {
    printf( "%s(%d): cci_get_data fail\n", __FILE__, __LINE__);
    goto handle_error;
}
if (ind != -1)
        printf("%d \t|", buffer);
else
        printf("NULL \t|");
...
cci_get_db_parameter
int cci_get_db_parameter(int conn_handle, T_CCI_DB_PARAM param_name, void *value, T_CCI_ERROR *err_buf)

The cci_get_db_parameter function gets a parameter value specified in the database.

Parameters:
  • conn_handle -- (IN) Connection handle
  • param_name -- (IN) System parameter name
  • value -- (OUT) Parameter value
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_PARAM_NAME
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_CONNECT

The data type of value for param_name is shown in the table below.

param_name value Type note
CCI_PARAM_ISOLATION_LEVEL int * get/set
CCI_PARAM_LOCK_TIMEOUT int * get/set
CCI_PARAM_MAX_STRING_LENGTH int * get only

In cci_get_db_parameter() and cci_set_db_parameter(), the input/output unit of CCI_PARAM_LOCK_TIMEOUT is milliseconds.

Warning

In the earlier version of CUBRID 9.0, you should be careful that the output unit of CCI_PARAM_LOCK_TIMEOUT is second.

CCI_PARAM_MAX_STRING_LENGTH is measured in bytes and it gets a value defined in the MAX_STRING_LENGTH broker parameter.

cci_get_db_version
int cci_get_db_version(int conn_handle, char *out_buf, int out_buf_size)

The cci_get_db_version function gets the Database Management System (DBMS) version.

Parameters:
  • conn_handle -- (IN) Connection handle
  • out_buf -- (OUT) Result buffer
  • out_buf_size -- (IN) out_buf size
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_COMMUNICATION
  • CCI_ER_CONNECT

cci_get_err_msg
int cci_get_err_msg(int err_code, char *msg_buf, int msg_buf_size)

The cci_get_err_msg function stores error messages corresponding to the error code in the error message buffer. For details on error codes and error messages, see CCI Error Codes and Error Messages.

Parameters:
  • err_code -- (IN) Error code
  • msg_buf -- (OUT) Error message buffer
  • msg_buf_size -- (IN) msg_buf size
Returns:

0: Success, -1: Failure

note:: From CUBRID 9.1, CUBRID ensures that all functions which have err_buf parameter store an error value into err_buf parameter, so you don't need to use cci_get_err_msg function if a function has err_buf parameter.

req = cci_prepare (con, query, 0, &err_buf);
if (req < 0)
{
    printf ("error: %d, %s\n", err_buf.err_code, err_buf.err_msg);
    goto handle_error;
}

On the previous version of 9.1, an err_buf value was stored only when CCI_ER_DBMS error occurred. So printing an error message should have been separated by CCI_ER_DBMS error.

req = cci_prepare (con, query, 0, &err_buf);
if (req < 0)
{
    if (req == CCI_ER_DBMS)
    {
        printf ("error: %s\n", err_buf.err_msg);
    }
    else
    {
        char msg_buf[1024];
        cci_get_err_msg(req, msg_buf, 1024);
        printf ("error: %s\n", msg_buf);
    }
    goto handle_error;
}

From 9.1, you can simplify the branch of the above code by using cci_get_error_msg function.

req = cci_prepare (con, query, 0, &err_buf);
if (req < 0)
{
    char msg_buf[1024];
    cci_get_error_msg(req, err_buf, msg_buf, 1024);
    printf ("error: %s\n", msg_buf);
    goto handle_error;
}
cci_get_error_msg
int cci_get_error_msg(int err_code, T_CCI_ERROR *err_buf, char *msg_buf, int msg_buf_size)

Saves the error messages corresponding to the CCI error codes in the message buffer. If the value of CCI error code is CCI_ER_DBMS, the database error buffer (err_buf) receives the error message sent from the data server and saves it in the message buffer(msg_buf). For details on error codes and messages, see CCI Error Codes and Error Messages.

Parameters:
  • err_code -- (IN) Error code
  • err_buf -- (IN) Database error buffer
  • msg_buf -- (OUT) Error message buffer
  • msg_buf_size -- (IN) msg_buf size
Returns:

0: Success, -1: Failure

cci_get_holdability
int cci_get_holdability(int conn_handle)

Returns the cursor holdability setting value about the result set from the connection handle. When it is 1, the connection is disconnected or the cursor is holdable until the result set is intentionally closed regardless of commit. When it is 0, the result set is closed when committed and the cursor is not holdable. For more details on cursor holdability, see Cursor Holdability.

Parameters:
  • conn_handle -- (IN) Connection handle
Returns:

0 (not holdable), 1 (holdable)

  • CCI_ER_CON_HANDLE

cci_get_last_insert_id
int cci_get_last_insert_id(int conn_handle, void *value, T_CCI_ERROR *err_buf)

Gets the primary key of the INSERT statement which executed at the last time.

Parameters:
  • conn_handle -- (IN) Request handle
  • value -- (OUT) The pointer of the result buffer pointer(char **). It stores the last primary key of INSERT statement executed on the last time. The memory which this pointer indicates doesn't need to be released, because it is the fixed buffer inside the connection handle.
  • err_buf -- (OUT) Error buffer
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_USED_CONNECTION
  • CCI_ER_INVALID_ARGS

#include <stdio.h>
#include "cas_cci.h"

int main ()
{
    int con = 0;
    int req = 0;

    int error;
    T_CCI_ERROR cci_error;


    char *query = "insert into t1 values(NULL);";
    char *value = NULL;

    con = cci_connect ("localhost", 33000, "demodb", "dba", "");

    if (con < 0)
    {
        printf ("con error\n");
        return;
    }

    req = cci_prepare (con, query, 0, &cci_error);
    if (req < 0)
    {
        printf ("cci_prepare error: %d\n", req);
        printf ("cci_error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
        return;
    }
    error = cci_execute (req, 0, 0, &cci_error);
    if (error < 0)
    {
        printf ("cci_execute error: %d\n", error);
        return;
    }

    error = cci_get_last_insert_id (con, &value, &cci_error);
    if (error < 0)
    {
        printf ("cci_get_last_insert_id error: %d\n", error);
        return;
    }

    printf ("## last insert id: %s\n", value);

    error = cci_close_req_handle (req);
    error = cci_disconnect (con, &cci_error);
    return 0;
}
cci_get_login_timeout
int cci_get_login_timeout(int conn_handle, int *timeout, T_CCI_ERROR *err_buf)

Return login timeout value to timeout.

Parameters:
  • conn_handle -- (IN) Connection handle
  • timeout -- (OUT) A pointer to login timeout value(unit: millisecond)
  • err_buf -- (OUT) Error buffer
Returns:

Error code (0: success)

  • CCI_ER_INVALID_ARGS
  • CCI_ER_CON_HANDLE
  • CCI_ER_USED_CONNECTION

cci_get_query_plan
int cci_get_query_plan(int req_handle, char **out_buf_p)

Saves the query plan to the result buffer; the query plan about the request handle which the cci_prepare function returned. You can call this function whether to call the cci_execute function or not.

After calling the cci_get_query_plan function, if the use of a result buffer ends, you should call the cci_query_info_free() function to release the result buffer created by cci_get_query_plan function.

char *out_buf;
...
req = cci_prepare (con, query, 0, &cci_error);
...
ret = cci_get_query_plan(req, &out_buf);
...
printf("plan = %s", out_buf);
cci_query_info_free(out_buf);
Parameters:
  • req_handle -- (IN) Request handle
  • out_buf_p -- (OUT) The pointer of a result buffer pointer
Returns:

Error code

  • CCI_ER_REQ_HANDLE
  • CCI_ER_CON_HANDLE
  • CCI_ER_USED_CONNECTION

cci_query_info_free
int cci_query_info_free(char *out_buf)

Releases the result buffer memory allocated from the cci_get_query_plan() function.

Parameters:
  • req_handle -- (IN) Request handle
  • out_buf -- (OUT) Result buffer pointer
Returns:

Error code

  • CCI_ER_NO_MORE_MEMORY

cci_get_query_timeout
int cci_get_query_timeout(int req_handle)

The cci_get_query_timeout function returns timeout configured for query execution.

Parameters:
  • req_handle -- (IN) Request handle
Returns:

Success: Timeout value configured in current request handle (unit: msec.), Failure: Error code

  • CCI_ER_REQ_HANDLE

cci_get_result_info
T_CCI_COL_INFO* cci_get_result_info(int req_handle, T_CCI_CUBRID_STMT *stmt_type, int *num)

If the prepared statement is SELECT, the T_CCI_COL_INFO struct that stores the column information about the execution result can be obtained by using this function. If it is not SELECT, NULL is returned and the num value becomes 0.

Parameters:
  • req_handle -- (IN) Request handle for the prepared statement
  • stmt_type -- (OUT) Command type
  • num -- (OUT) he number of columns in the SELECT statement (if stmt_type is CUBRID_STMT_SELECT)
Returns:

Success: Result info pointer, Failure: NULL

You can access the T_CCI_COL_INFO struct directly to get the column information from the struct, but you can also use a macro to get the information, which is defined as follows. The address of the T_CCI_COL_INFO struct and the column index are specified as parameters for each macro. The macro can be called only for the SELECT query. Note that the validity check is not performed for each parameter entered in each macro. If the return type of the macro is char*, do not free the memory pointer.

Macro Return Type Meaning
CCI_GET_RESULT_INFO_TYPE T_CCI_U_TYPE column type
CCI_GET_RESULT_INFO_SCALE short column scale
CCI_GET_RESULT_INFO_PRECISION int column precision
CCI_GET_RESULT_INFO_NAME char * column name
CCI_GET_RESULT_INFO_ATTR_NAME char * column attribute name
CCI_GET_RESULT_INFO_CLASS_NAME char * column class name
CCI_GET_RESULT_INFO_IS_NON_NULL char (0 or 1) whether a column is NULL
col_info = cci_get_result_info (req, &stmt_type, &col_count);
if (col_info == NULL)
{
  printf ("get_result_info error\n");
  goto handle_error;
}

for (i = 1; i <= col_count; i++)
{
  printf ("%-12s = %d\n", "type", CCI_GET_RESULT_INFO_TYPE (col_info, i));
  printf ("%-12s = %d\n", "scale",
          CCI_GET_RESULT_INFO_SCALE (col_info, i));
  printf ("%-12s = %d\n", "precision",
          CCI_GET_RESULT_INFO_PRECISION (col_info, i));
  printf ("%-12s = %s\n", "name", CCI_GET_RESULT_INFO_NAME (col_info, i));
  printf ("%-12s = %s\n", "attr_name",
          CCI_GET_RESULT_INFO_ATTR_NAME (col_info, i));
  printf ("%-12s = %s\n", "class_name",
          CCI_GET_RESULT_INFO_CLASS_NAME (col_info, i));
  printf ("%-12s = %s\n", "is_non_null",
          CCI_GET_RESULT_INFO_IS_NON_NULL (col_info,i) ? "true" : "false");
}
CCI_GET_RESULT_INFO_ATTR_NAME
#define CCI_GET_RESULT_INFO_ATTR_NAME(T_CCI_COL_INFO* res_info, int index)

The CCI_GET_RESULT_INFO_ATTR_NAME macro gets the actual attribute name of the index-th column of a prepared SELECT list. If there is no name for the attribute (constant, function, etc), " " (empty string) is returned. It does not check whether the specified argument, res_info, is NULL and whether index is valid. You cannot delete the returned memory pointer with free().

Parameters:
  • res_info -- (IN) A pointer to the column information fetched by cci_get_result_info()
  • index -- (IN) Column index
Returns:

Attribute name (char *)

CCI_GET_RESULT_INFO_CLASS_NAME
#define CCI_GET_RESULT_INFO_CLASS_NAME(T_CCI_COL_INFO* res_info, int index)

The CCI_GET_RESULT_INFO_CLASS_NAME macro gets the index-th column's class name of a prepared SELECT list. It does not check whether the specified argument, res_info, is NULL and whether index is valid. You cannot delete the returned memory pointer with free (). The return value can be NULL.

Parameters:
Returns:

Class name (char *)

CCI_GET_RESULT_INFO_IS_NON_NULL
#define CCI_GET_RESULT_INFO_IS_NON_NULL(T_CCI_COL_INFO* res_info, int index)

The CCI_GET_RESULT_INFO_IS_NON_NULL macro gets a value indicating whether the index-th column of a prepared SELECT list is nullable. It does not check whether the specified argument, res_info, is NULL and whether index is valid.

When a column of a SELECT list is not a column but an expression, CUBRID cannot judge it's NON_NULL or not; therefore, CCI_GET_RESULT_INFO_IS_NON_NULL macro always returns 0.

Parameters:
Returns:

0: nullable, 1: non NULL

CCI_GET_RESULT_INFO_NAME
#define CCI_GET_RESULT_INFO_NAME(T_CCI_COL_INFO* res_info, int index)

The CCI_GET_RESULT_INFO_NAME macro gets the index-th column's name of a prepared SELECT list. It does not check whether the specified argument, res_info, is NULL and whether index is valid. You cannot delete the returned memory pointer with free ().

Parameters:
Returns:

Column name (char *)

CCI_GET_RESULT_INFO_PRECISION
#define CCI_GET_RESULT_INFO_PRECISION(T_CCI_COL_INFO* res_info, int index)

The CCI_GET_RESULT_INFO_PRECISION macro gets the index-th column's precision of a prepared SELECT list. It does not check whether the specified argument, res_info, is NULL and whether index is valid.

Parameters:
Returns:

precision (int)

CCI_GET_RESULT_INFO_SCALE
#define CCI_GET_RESULT_INFO_SCALE(T_CCI_COL_INFO* res_info, int index)

The CCI_GET_RESULT_INFO_SCALE macro gets the index-th column's scale of a prepared SELECT list. It does not check whether the specified argument, res_info, is NULL and whether index is valid.

Parameters:
Returns:

scale (int)

CCI_GET_RESULT_INFO_TYPE
#define CCI_GET_RESULT_INFO_TYPE(T_CCI_COL_INFO* res_info, int index)

The CCI_GET_RESULT_INFO_TYPE macro gets the index-th column's type of a prepared SELECT list. It does not check whether the specified argument, res_info, is NULL and whether index is valid.

If you want to check which column is a SET type or not, use CCI_IS_SET_TYPE.

Parameters:
  • res_info -- (IN) pointer to the column information fetched by cci_get_result_info()
  • index -- (IN) Column index
Returns:

Column type (T_CCI_U_TYPE)

CCI_IS_SET_TYPE
#define CCI_IS_SET_TYPE(u_type)

The CCI_IS_SET_TYPE macro check whether u_type is set type.

Parameters:
  • u_type -- (IN)
Returns:

1 : set, 0 : not set

CCI_IS_MULTISET_TYPE
#define CCI_IS_MULTISET_TYPE(u_type)

The CCI_IS_SET_TYPE macro check whether u_type is multiset type.

Parameters:
  • u_type -- (IN)
Returns:

1 : multiset, 0 : not multiset

CCI_IS_SEQUENCE_TYPE
#define CCI_IS_SEQUENCE_TYPE(u_type)

The CCI_IS_SET_TYPE macro check whether u_type is sequence type.

Parameters:
  • u_type -- (IN)
Returns:

1 : sequence, 0 : not sequence

CCI_IS_COLLECTION_TYPE
#define CCI_IS_COLLECTION_TYPE(u_type)

The CCI_IS_SET_TYPE macro check whether u_type is collection (set, multiset, sequence) type.

Parameters:
  • u_type -- (IN)
Returns:

1 : collection (set, multiset, sequence), 0 : not collection

cci_get_version
int cci_get_version(int *major, int *minor, int *patch)

The cci_get_version function gets the version of CCI library. In case of version "9.2.0.0001", 9 is the major version, 2 is the minor version, and 0 is the patch version.

Parameters:
  • major -- (OUT) major version
  • minor -- (OUT) minor version
  • patch -- (OUT) patch version
Returns:

Zero without exception (success)

Note

In CUBRID for Linux, you can check the file version of CCI library by using the strings command.

$ strings /home/usr1/CUBRID/lib/libcascci.so | grep VERSION
VERSION=9.2.0.0001
cci_init
void cci_init()

If you compile the CCI application program for Windows with static linking library(.lib), this function should be called always. In the other cases, this does not need to be called.

cci_is_holdable
int cci_is_holdable(int req_handle)

The cci_is_holdable function returns whether the request handle(req_handle) is holdable or not.

Parameters:
  • req_handle -- (IN) Request handle for the prepared statement
Returns:

  • 1: holdable
  • 0: not holdable
  • CCI_ER_REQ_HANDLE

See also

cci_prepare()

cci_is_updatable
int cci_is_updatable(int req_handle)

The cci_is_updatable function checks the SQL statement executing cci_prepare() can make updatable result set (which means CCI_PREPARE_UPDATABLE is configured in flag when executing cci_prepare()).

Parameters:
  • req_handle -- (IN) Request handle for the prepared statement
Returns:

  • 1 : updatable
  • 0 : not updatable
  • CCI_ER_REQ_HANDLE

cci_next_result
int cci_next_result(int req_handle, T_CCI_ERROR *err_buf)

The cci_next_result function gets results of next query if CCI_EXEC_QUERY_ALL flag is set upon cci_execute(). The information about the query fetched by next_result can be obtained with cci_get_result_info(). If next_result is executed successfully, the database is updated with the information of the current query.

You can execute multiple queries in the written order when CCI_EXEC_QUERY_ALL flag is set on cci_execute(). At this time, CUBRID brings the first query's result after calling cci_execute(); CUBRID brings the second and the other queries' results after calling cci_next_result function. At this time, the column information about the query result can be brought by calling cci_get_result_info() function whenever cci_execute() function or cci_next_result function is called.

In other words, when you run Q1, Q2, and Q3 at once with calling cci_prepare() function, the result of Q1 is brought by calling cci_execute(); the result of Q2 or Q3 is brought by calling cci_next_result. The result of Q1, Q2 or Q3 is brought by calling cci_get_result_info() function for each time.

sql = "SELECT * FROM athlete; SELECT * FROM nation; SELECT * FROM game";
req = cci_prepare (con, sql, 0, &error);
...
ret = cci_execute (req, CCI_EXEC_QUERY_ALL, 0, &error);
res_col_info = cci_get_result_info (req, &cmd_type, &col_count);
...
ret = cci_next_result (req, &error);
res_col_info = cci_get_result_info (req, &cmd_type, &col_count);
...
ret = cci_next_result (req, &error);
res_col_info = cci_get_result_info (req, &cmd_type, &col_count);
Parameters:
  • req_handle -- (IN) Request handle of a prepared statement
  • err_buf -- (OUT) Database error buffer
Returns:

  • SELECT : The number of results
  • INSERT, UPDATE : The number of records reflected
  • Others : 0
  • Failure : Error code
    • CCI_ER_REQ_HANDLE
    • CCI_ER_DBMS
    • CCI_ER_COMMUNICATION

The error code CAS_ER_NO_MORE_RESULT_SET means that no more result set exists.

cci_oid
int cci_oid(int conn_handle, T_CCI_OID_CMD cmd, char *oid_str, T_CCI_ERROR *err_buf)

By the value of cmd argument, it executes the following behavior.

  • CCI_OID_DROP: Deletes the given oid.
  • CCI_OID_IS_INSTANCE: Checks whether the given oid is an instance oid.
  • CCI_OID_LOCK_READ: Sets read lock on the given oid.
  • CCI_OID_LOCK_WRITE: Sets write lock on the given oid.
Parameters:
  • conn_handle -- (IN) Connection handle
  • cmd -- (IN) CCI_OID_DROP, CCI_OID_IS_INSTANCE, CCI_OID_LOCK_READ, CCI_OID_LOCK_WRITE
  • oid_str -- (IN) oid
  • err_buf -- (OUT) Database error buffer
Returns:

  • when cmd is CCI_OID_IS_INSTANCE

    • 0 : Non-instance
    • 1 : Instance
    • < 0 : error
  • when cmd is CCI_OID_DROP, CCI_OID_LOCK_READ or CCI_OID_LOCK_WRITE

    Error code (0: success)

    • CCI_ER_CON_HANDLE
    • CCI_ER_CONNECT
    • CCI_ER_OID_CMD
    • CCI_ER_OBJECT
    • CCI_ER_DBMS

cci_oid_get
int cci_oid_get(int conn_handle, char *oid_str, char **attr_name, T_CCI_ERROR *err_buf)

The cci_oid_get function gets the attribute values of the given oid. attr_name is an array of the attributes, and it must end with NULL. If attr_name is NULL, the information of all attributes is fetched. The request handle has the same form as when the SQL statement "SELECT attr_name FROM oid_class WHERE oid_class = oid" is executed.

Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • attr_name -- (IN) A list of attributes
  • err_buf -- (OUT) Database error buffer
Returns:

Success: Request handle, Failure: Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_CONNECT

cci_oid_get_class_name
int cci_oid_get_class_name(int conn_handle, char *oid_str, char *out_buf, int out_buf_len, T_CCI_ERROR *err_buf)

The cci_oid_get_class_name function gets the class name of the given oid.

Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • out_buf -- (OUT) Out buffer
  • out_buf_len -- (IN) out_buf length
  • err_buf -- (OUT) Database error buffer
Returns:

Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_OBJECT
  • CCI_ER_DBMS

cci_oid_put
int cci_oid_put(int conn_handle, char *oid_str, char **attr_name, char **new_val_str, T_CCI_ERROR *err_buf)

The cci_oid_put function configures the attr_name attribute values of the given oid to new_val_str. The last value of attr_name must be NULL. Any value of any type must be represented as a string. The value represented as a string is applied to the database after being converted depending on the attribute type on the server. To insert a NULL value, configure the value of new_val_str [i] to NULL.

Parameters:
  • conn_handle -- (IN) Connection handle
  • oid_str -- (IN) oid
  • attr_name -- (IN) The list of attribute names
  • new_val_str -- (IN) The list of new values
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT

cci_oid_put2
int cci_oid_put2(int conn_handle, char *oidstr, char **attr_name, void **new_val, int *a_type, T_CCI_ERROR *err_buf)

The cci_oid_put2 function sets the attr_name attribute values of the given oid to new_val. The last value of attr_name must be NULL. To insert a NULL value, set the value of new_val [i] to NULL.

Parameters:
  • conn_handle -- (IN) Connection handle
  • oidstr -- (IN) oid
  • attr_name -- (IN) A list of attribute names
  • new_val -- (IN) A new value array
  • a_type -- (IN) new_val type array
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT

The type of new_val [i] for a_type is shown in the table below.

Type of new_val[i] for a_type

Type value type
CCI_A_TYPE_STR char **
CCI_A_TYPE_INT int *
CCI_A_TYPE_FLOAT float *
CCI_A_TYPE_DOUBLE double *
CCI_A_TYPE_BIT T_CCI_BIT *
CCI_A_TYPE_SET T_CCI_SET *
CCI_A_TYPE_DATE T_CCI_DATE *
CCI_A_TYPE_BIGINT int64_t * (For Windows: __int64 *)
char *attr_name[array_size]
void *attr_val[array_size]
int a_type[array_size]
int int_val

...

attr_name[0] = "attr_name0"
attr_val[0] = &int_val
a_type[0] = CCI_A_TYPE_INT
attr_name[1] = "attr_name1"
attr_val[1] = "attr_val1"
a_type[1] = CCI_A_TYPE_STR

...
attr_name[num_attr] = NULL

res = cci_put2(con_h, oid_str, attr_name, attr_val, a_type, &error)
cci_prepare
int cci_prepare(int conn_handle, char *sql_stmt, char flag, T_CCI_ERROR *err_buf)

The cci_prepare() function prepares SQL execution by acquiring request handle for SQL statements. If a SQL statement consists of multiple queries, the preparation is performed only for the first query. With the parameter of this function, an address to T_CCI_ERROR where connection handle, SQL statement, flag, and error information are stored.

Parameters:
  • conn_handle -- (IN) Connection handle
  • sql_stmt -- (IN) SQL statement
  • flag -- (IN) prepare flag (CCI_PREPARE_UPDATABLE, CCI_PREPARE_INCLUDE_OID, CCI_PREPARE_CALL or CCI_PREPARE_HOLDABLE)
  • err_buf -- (OUT) Database error buffer
Returns:

Success: Request handle ID (int), Failure: Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_STR_PARAM
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_CONNECT
  • CCI_ER_QUERY_TIMEOUT
  • CCI_ER_LOGIN_TIMEOUT

CCI_PREPARE_UPDATABLE, CCI_PREPARE_INCLUDE_OID, CCI_PREPARE_CALL or CCI_PREPARE_HOLDABLE can be configured in flag. If CCI_PREPARE_UPDATABLE is configured, updatable resultset is created and CCI_PREPARE_INCLUDE_OID is automatically configured. CCI_PREPARE_UPDATABLE and CCI_PREPARE_HOLDABLE cannot be used simultaneously in flag. If you want to call the Java Stored Procedure, specify CCI_PREPARE_CALL flag into the cci_prepare function. You can see an related example on cci_register_out_param().

The default value of whether to keep result set after commit is cursor holdability. Thus, if you want to configure CCI_PREPARE_UPDATABLE in flag of cci_prepare(), you should call cci_set_holdability() first before calling cci_prepare() so that cursor cannot be maintained.

However, not all updatable resultsets are created even though CCI_PREPARE_UPDATABLE is configured. So you need to check if the results are updatable by using cci_is_updatable() after preparation. You can use cci_oid_put() or cci_oid_put2() to update result sets.

The conditions of updatable queries are as follows:

  • Must be SELECT.
  • OID can be included in the query result.
  • The column to be updated must be the one that belongs to the table specified in the FROM clause.

If CCI_PREPARE_HOLDABLE is set, a cursor is held as long as result set is closed or connection is disconnected after the statement is committed(see Cursor Holdability).

cci_prepare_and_execute
int cci_prepare_and_execute(int conn_handle, char *sql_stmt, int max_col_size, int *exec_retval, T_CCI_ERROR *err_buf)

The cci_prepare_and_execute function executes the SQL statement immediately and returns a request handle for the SQL statement. A request handle, SQL statement, the maximum length of a column to be fetched, error code, and the address of a T_CCI_ERROR construct variable in which error information being stored are specified as arguments. max_col_size is a value to configure the maximum length of a column to be sent to a client when the column of a SQL statement is CHAR, VARCHAR, BIT, or VARBIT. If this value is 0, full length is fetched.

Parameters:
  • conn_handle -- (IN) Connection handle
  • sql_stmt -- (IN) SQL statement
  • max_col_size -- (IN) The maximum length of a column to be fetched when it is a string data type in bytes. If this value is 0, full length is fetched.
  • exec_retval -- (OUT) Success: Affected rows, Failure: Error code
  • err_buf -- (OUT) Database error buffer
Returns:

Success: Request handle ID (int), Failure: Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_STR_PARAM
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_CONNECT
  • CCI_ER_QUERY_TIMEOUT

cci_property_create
T_CCI_PROPERTIES * cci_property_create()

The cci_property_create function creates T_CCI_PROPERTIES struct to configure DATASOURCE of CCI.

Returns:Success: T_CCI_PROPERTIES struct pointer in which memory is allocated, Failure: NULL
cci_property_destroy
void cci_property_destroy(T_CCI_PROPERTIES * properties)

The cci_property_destroy function destroys T_CCI_PROPERTIES struct.

Parameters:
  • properties -- T_CCI_PROPERTIES struct pointer to be destroyed
cci_property_get
char *cci_property_get(T_CCI_PROPERTIES * properties, char *key)

The cci_property_get function retrieves the property value configured in the T_CCI_PROPERTIES struct.

Parameters:
  • properties -- T_CCI_PROPERTIES struct pointer which gets value corresponding to key
  • key -- Name of property to be retrieved (For name and description available properties, see the cci_property_set())
Returns:

Success: String pointer of value corresponding to key, Failure: NULL

cci_property_set
int cci_property_set(T_CCI_PROPERTIES *properties, char *key, char *value)

It configures a property value in T_CCI_PROPERTIES struct.

Parameters:
  • properties -- T_CCI_PROPERTIES struct pointer in which key and value are stored
  • key -- String pointer of property name
  • value -- String pointer of property value
Returns:

Success: 1, Failure: 0

The property names and its meanings that can be configured in the struct are as follows:

Property name Type Default Description
user string   DB user name.
password string   DB user password.
url string   Connection URL. For specifying connection URL string, see cci_connect_with_url().
pool_size int 10 Maximum number of connections which a connection pool can have.
max_pool_size int pool_size Total number of connections to create when creating an initial datasource. maximum value is INT_MAX.
max_wait msec 1000 Maximum waiting time to get connection.
pool_prepared_statement bool false Whether to enable statement pooling. true or false.
max_open_prepared_statement int 1000 The maximum number of prepared statements to maintain in the statement pool.
login_timeout msec 0(inf.) Login timeout applied when you create a datasource with cci_datasource_create() function or internal timeout occurs in prepare/execute function.
query_timeout msec 0(inf.) Query timeout.
disconnect_on_query_timeout bool no Whether to terminate connection when execution is discarded due to query execution timeout. yes or no.
default_autocommit bool CCI_DEFAULT_AUTOCOMMIT in cubrid_broker.conf Auto-commit mode specified when a datasource is created by cci_datasource_create() function. true or false.
default_isolation string isolation_level in cubrid.conf Transaction isolation level specified when a datasource is created by cci_datasource_create() function. See the below table.
default_lock_timeout msec lock_timeout in cubrid.conf lock timeout specified when a datasource is created by cci_datasource_create() function.

If the number of prepared statements exceeds max_open_prepared_statement value, the oldest prepared statement is released from the statement pool. If you reuse it later, it is added to the statement pool again.

A number of connections which a connection pool can contain is changable by using cci_datasource_change_property() function when it's required, but it cannot exceed max_pool_size. You can change this number when you want to handle the limitation of the number of connections. For example, usually set the number less than max_pool_size; raise the number when more connections are required than expected; shrink the number again when many connections are not required.

The number of connections which a connection pool can contain is limited until pool_size; it's maximum value is max_pool_size.

When you set login_timeout, default_autocommit, default_isolation or default_lock_timeout, these specified values are used in a connection which is returend when calling cci_datasource_borrow() function.

login_timeout, default_autocommit, default_isolation or default_lock_timeout can be changed even after calling cci_datasource_borrow() function. Regarding this, see cci_set_login_timeout(), cci_set_autocommit(), cci_set_isolation_level(), cci_set_lock_timeout(). Changed values by functions which the name starts with cci_set_ are only applied to the changed connection objects, and after the connection is released, they are restored as the specified values by cci_property_set(). It is restored as the default value when there is no value specified by cci_property_set() function.

Note

  • When specifying values together in cci_property_set() function and URL string, values specified in cci_property_set() function have the first priority.
  • login_timeout is applied when you create a DATASOURCE object and internal reconnection occurs in cci_prepare() or cci_execute() function. Internal reconnection occurs when you get the connection object from DATASOURCE and from cci_connect()/cci_connect_with_url() function.
  • Creating time of a DATASOURCE object can take more than an internal reconnection time; therefore, you can consider to apply login_timeout differently on these two cases. For example, if you want to set 5000(5 sec.) in the former and 2000(2 sec.) in the later, for the later, use cci_set_login_timeout() after creating a DATASOURCE.

default_isolation has one of the following configuration values. For details on isolation level, see SET TRANSACTION ISOLATION LEVEL.

isolation_level Configuration Value
SERIALIZABLE "TRAN_SERIALIZABLE"
REPEATABLE READ "TRAN_REP_READ"
READ COMMITTED "TRAN_READ_COMMITTED"

DB user's name and password can be specified by the setting of user and password directly, or by the setting of user and password in url.

The following shows how to work as the first priority if both are specified.

  • If both are specified, the value of direct setting will be first.
  • If one of them is NULL, the value which is not NULL is used.
  • If both are NULL, they are used as NULL value.
  • If the direct setting value of DB user is NULL then "public" is used, else if the direct setting value of the password is NULL then NULL is used.
  • If the direct setting value of the password is NULL, it follows the setting of URL.

The following shows that the DB user's name becomes "dba" and the password becomes "cubridpwd".

cci_property_set(ps, "user", "dba");
cci_property_set(ps, "password", "cubridpwd");
  ...
cci_property_set(ps, "url", "cci:cubrid:192.168.0.1:33000:demodb:public:mypwd:?logSlowQueries=true&slowQueryThresholdMillis=1000&logTraceApi=true&logTraceNetwork=true");
cci_query_result_free
int cci_query_result_free(T_CCI_QUERY_RESULT* query_result, int num_query)

The cci_query_result_free function releases query results created by cci_execute_batch(), cci_execute_array() or cci_execute_result() function from memory.

Parameters:
  • query_result -- (IN) Query results to release from memory
  • num_query -- (IN) The number of arrays in query_result
Returns:

0: success

T_CCI_QUERY_RESULT *qr;
char **sql_stmt;

...

res = cci_execute_array(conn, &qr, &err_buf);

...

cci_query_result_free(qr, res);
CCI_QUERY_RESULT_ERR_NO
#define CCI_QUERY_RESULT_ERR_NO(T_CCI_QUERY_RESULT* query_result, int index)

Since query results performed by cci_execute_batch(), cci_execute_array(), or cci_execute_result() function are stored as an array of T_CCI_QUERY_RESULT structure, you need to check the query result for each item of the array.

CCI_QUERY_RESULT_ERR_NO fetches the error number for the array item specified as index, if it is not an error, it returns 0.

Parameters:
  • query_result -- (IN) Query result to retrieve
  • index -- (IN) Index of the result array(base :1). It represents a specific location of the result array.
Returns:

Error number

CCI_QUERY_RESULT_ERR_MSG
#define CCI_QUERY_RESULT_ERR_MSG(T_CCI_QUERY_RESULT* query_result, int index)

The CCI_QUERY_RESULT_ERR_MSG macro gets error messages about query results executed by cci_execute_batch(), cci_execute_array() or cci_execute_result() function. If there is no error message, this macro returns ""(empty string). It does not check whether the specified argument, query_result, is NULL, and whether index is valid.

Parameters:
  • query_result -- (IN) Query results of to be executed
  • index -- (IN) Column index (base: 1)
Returns:

Error message

CCI_QUERY_RESULT_RESULT
#define CCI_QUERY_RESULT_RESULT(T_CCI_QUERY_RESULT* query_result, int index)

The CCI_QUERY_RESULT_RESULT macro gets the result count executed by cci_execute_batch(), cci_execute_array() or cci_execute_result() function. It does not check whether the specified argument, query_result, is NULL and whether index is valid.

Parameters:
  • query_result -- (IN) Query results to be retrieved
  • index -- (IN) Column index (base: 1)
Returns:

result count

CCI_QUERY_RESULT_STMT_TYPE
#define CCI_QUERY_RESULT_STMT_TYPE(T_CCI_QUERY_RESULT* query_result, int index)

Since query results performed by cci_execute_batch(), cci_execute_array() or cci_execute_result() fuction are stored as an array of T_CCI_QUERY_RESULT type, you need to check the query result for each item of the array.

The CCI_QUERY_RESULT_STMT_TYPE macro gets the statement type for the array items specified as index.

It does not check whether the specified argument, query_result, is NULL and whether index is valid.

Parameters:
  • query_result -- (IN) Query results to be retrieved
  • index -- (IN) Column index (base: 1)
Returns:

statement type (T_CCI_CUBRID_STMT)

cci_register_out_param
int cci_register_out_param(int req_handle, int index)

The cci_register_out_param function is used to bind the parameters as outbind in Java Stored Procedure. The index value begins from 1. To call this function, CCI_PREPARE_CALL flag of cci_prepare function should be specified.

Parameters:
  • req_handle -- (IN) Request handle
Returns:

Error code

  • CCI_ER_BIND_INDEX
  • CCI_ER_REQ_HANDLE
  • CCI_ER_CON_HANDLE
  • CCI_ER_USED_CONNECTION

The following shows to print out "Hello, CUBRID" string with Java Stored Procedure.

To use Java Stored Procedure, firstly specify java_stored_procedure parameter in cubrid.conf as yes, then start the database.

$ vi cubrid.conf
java_stored_procedure=yes

$ cubrid service start
$ cubrid server start demodb

Implement and compile the class to be used as Java Stored Procedure.

public class SpCubrid{
    public static void outTest(String[] o) {
        o[0] = "Hello, CUBRID";
    }
}

%javac SpCubrid.java

Load the compiled Java class into CUBRID.

$ loadjava demodb SpCubrid.class

Register the loaded Java class.

   -- csql>

   CREATE PROCEDURE test_out(x OUT STRING)
   AS LANGUAGE JAVA
   NAME 'SpCubrid.outTest(java.lang.String[] o)';

On the CCI application program, specify **CCI_PREPARE_CALL** flag into the **cci_prepare** function, and bring the fetching result after setting the position of the outbind parameter by calling **cci_register_out_param**.
// On Linux, compile with "gcc -g -o jsp jsp.c -I$CUBRID/include/ -L$CUBRID/lib/ -lcascci -lpthread"

#include <stdio.h>
#include <unistd.h>
#include <cas_cci.h>
char *cci_client_name = "test";

int
main (int argc, char *argv[])
{
    int con = 0, req = 0, res, ind, i, col_count;
    T_CCI_ERROR error;
    T_CCI_COL_INFO *res_col_info;
    T_CCI_CUBRID_STMT cmd_type;
    char *buffer, db_ver[16];

    if ((con = cci_connect ("localhost", 33000, "demodb", "dba", "")) < 0)
    {
        printf ("%s(%d): cci_connect fail\n", __FILE__, __LINE__);
        return -1;
    }

    if ((req = cci_prepare (con, "call test_out(?)", CCI_PREPARE_CALL, &error)) < 0)
    {
        printf ("%s(%d): cci_prepare fail(%d)\n", __FILE__, __LINE__,
            error.err_code);
        goto handle_error;
    }
    if ((res = cci_register_out_param (req, 1)) < 0)
    {
        printf ("%s(%d): cci_register_out_param fail(%d)\n", __FILE__, __LINE__,
            error.err_code);
        goto handle_error;
    }
    if ((res = cci_execute (req, 0, 0, &error)) < 0)
    {
      printf ("%s(%d): cci_execute fail(%d)\n", __FILE__, __LINE__,
            error.err_code);
      goto handle_error;
    }
    res = cci_cursor (req, 1, CCI_CURSOR_CURRENT, &error);
    if (res == CCI_ER_NO_MORE_DATA)
    {
        printf ("%s(%d): cci_cursor fail(%d)\n", __FILE__, __LINE__,
            error.err_code);
        goto handle_error;
    }

    if ((res = cci_fetch (req, &error) < 0))
    {
        printf ("%s(%d): cci_fetch(%d, %s)\n", __FILE__, __LINE__,
            error.err_code, error.err_msg);
      goto handle_error;
    }
    if ((res = cci_get_data (req, 1, CCI_A_TYPE_STR, &buffer, &ind)) < 0)
    {
        printf ("%s(%d): cci_get_data fail\n", __FILE__, __LINE__);
        goto handle_error;
    }
    // ind: string length, buffer: a string which came from the out binding parameter of test_out(?) Java SP.
    if (ind != -1)
        printf ("%d, (%s)\n", ind, buffer);
    else // if ind== -1, then data is NULL
        printf ("NULL\n");

    if ((res = cci_close_query_result (req, &error)) < 0)
    {
        printf ("%s(%d): cci_close_query_result fail(%d)\n", __FILE__, __LINE__, error.err_code);
        goto handle_error;
    }

    if ((res = cci_close_req_handle (req)) < 0)
    {
        printf ("%s(%d): cci_close_req_handle fail\n", __FILE__, __LINE__);
        goto handle_error;
    }

    if ((res = cci_disconnect (con, &error)) < 0)
    {
        printf ("%s(%d): cci_disconnect fail(%d)\n", __FILE__, __LINE__,
            error.err_code);
        goto handle_error;
    }
    printf ("Program ended!\n");
    return 0;

handle_error:
    if (req > 0)
        cci_close_req_handle (req);
    if (con > 0)
        cci_disconnect (con, &error);
    printf ("Program failed!\n");
    return -1;
}

See also

cci_prepare()

cci_row_count
int cci_row_count(int conn_handle, int *row_count, T_CCI_ERROR * err_buf)

The cci_row_count function gets the number of rows affected by the last executed query.

Parameters:
  • conn_handle -- (IN) Connection handle
  • row_count -- (OUT) The number of rows affected by the last executed query
  • err_buf -- (OUT) Error buffer
Returns:

Error code

  • CCI_ER_COMMUNICATION
  • CCI_ER_LOGIN_TIMEOUT
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_DBMS

cci_savepoint
int cci_savepoint(int conn_handle, T_CCI_SAVEPOINT_CMD cmd, char* savepoint_name, T_CCI_ERROR *err_buf)

The cci_savepoint function configures savepoint or performs transaction rollback to a specified savepoint. If cmd is set to CCI_SP_SET, it configures savepoint and if it is set to CCI_SP_ROLLBACK, it rolls back transaction to specified savepoint.

Parameters:
  • conn_handle -- (IN) Connection handle
  • cmd -- (IN) CCI_SP_SET or CCI_SP_ROLLBACK
  • savepoint_name -- (IN) Savepoint name
  • err_buf -- (OUT) Database error buffer
Returns:

Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_COMMUNICATION
  • CCI_ER_QUERY_TIMEOUT
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_DBMS

con = cci_connect( ... );
... /* query execute */

/* Sets the savepoint named "savepoint1" */
cci_savepoint(con, CCI_SP_SET, "savepoint1", err_buf);

... /* query execute */

/* Rolls back to specified savepoint,"savepoint1" */
cci_savepoint(con, CCI_SP_ROLLBACK, "savepoint1", err_buf);
cci_schema_info
int cci_schema_info(int conn_handle, T_CCI_SCHEMA_TYPE type, char *class_name, char *attr_name, char flag, T_CCI_ERROR *err_buf)

The cci_schema_info function gets schema information. If it is performed successfully, the results are managed by the request handle and can be fetched by fetch and getdata. If you want to retrieve a class_name and attr_name by using pattern matching of the LIKE statement, you should configure flag.

Parameters:
  • conn_handle -- (IN) Connection handle
  • type -- (IN) Schema type
  • class_name -- (IN) Class name or NULL
  • attr_name -- (IN) Attribute name or NULL
  • flag -- (IN) Pattern matching flag (CCI_CLASS_NAME_PATTERN_MATCH or CCI_ATTR_NAME_PATTERN_MATCH)
  • err_buf -- (OUT) Database error buffer
Returns:

Success: Request handle, Failure: Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_CONNECT

Two types of flag s, CCI_CLASS_NAME_PATTERN_MATCH, and CCI_ATTR_NAME_PATTERN_MATCH, are used for pattern matching; you can configure these two flag s by using the OR operator ( | ). To use pattern matching, search by using the LIKE statement. For example, to search the information on a column whose class_name is "athlete" and attr_name is "code," you can enter as follows (in the example, "%code" is entered in the value of attr_name).

cci_schema_info(conn, CCI_SCH_ATTRIBUTE, "athlete", "%code", CCI_ATTR_NAME_PATTERN_MATCH, &error);

The table below shows record type for each type.

Record for Each Type

Type Column Order Column Name Column Type
CCI_SCH_CLASS 1 NAME char *
2 TYPE

short

  • 0: system class
  • 1: vclass
  • 2: class
  • 3: proxy
3 REMARKS char *
CCI_SCH_VCLASS 1 NAME char *
2 TYPE

short

  • 1: vclass
  • 3: proxy
3 REMARKS char *
CCI_SCH_QUERY_SPEC 1 QUERY_SPEC char *
CCI_SCH_ATTRIBUTE 1 NAME char *
2 DOMAIN short
3 SCALE short
4 PRECISION int
5 INDEXED

short

1: indexed

6 NON_NULL

short

1: non null

7 SHARED

short

1: shared

8 UNIQUE

short

1: unique

9 DEFAULT char *
10 ATTR_ORDER

int

base = 1

11 CLASS_NAME char *
12 SOURCE_CLASS char *
13 IS_KEY

short

1: key

14 REMARKS char *

CCI_SCH_CLASS_ATTRIBUTE

When the attribute of the CCI_SCH_CLASS_ATTRIBUTE column is INSTANCE or SHARED, the order and the name values are identical to those of the column of CCI_SCH_ATTRIBUTE.

     
CCI_SCH_CLASS_METHOD 1 NAME char *
2 RET_DOMAIN short
3 ARG_DOMAIN char *
CCI_SCH_METHOD_FILE 1 METHOD_FILE char *
CCI_SCH_SUPERCLASS 1 CLASS_NAME char *
2 TYPE short
CCI_SCH_SUBCLASS 1 CLASS_NAME char *
2 TYPE short
CCI_SCH_CONSTRAINT 1 TYPE

short

  • 0: unique
  • 1: index
  • 2: reverse unique
  • 3: reverse index
2 NAME char *
3 ATTR_NAME char *
4 NUM_PAGES int
5 NUM_KEYS int
6 PRIMARY_KEY

short

  • 1: primary key
7 KEY_ORDER

short

base = 1

8 ASC_DESC char *
CCI_SCH_TRIGGER 1 NAME char *
2 STATUS char *
3 EVENT char *
4 TARGET_CLASS char *
5 TARGET_ATTR char *
6 ACTION_TIME char *
7 ACTION char *
8 PRIORITY float
9 CONDITION_TIME char *
10 CONDITION char *
11 REMARKS char *
CCI_SCH_CLASS_PRIVILEGE 1 CLASS_NAME char *
2 PRIVILEGE char *
3 GRANTABLE char *
CCI_SCH_ATTR_PRIVILEGE 1 ATTR_NAME char *
2 PRIVILEGE char *
3 GRANTABLE char *
CCI_SCH_DIRECT_SUPER_CLASS 1 CLASS_NAME char *
2 SUPER_CLASS_NAME char *
CCI_SCH_PRIMARY_KEY 1 CLASS_NAME char *
2 ATTR_NAME char *
3 KEY_SEQ

int

base = 1

4 KEY_NAME char *

CCI_SCH_IMPORTED_KEYS

Used to retrieve primary key columns that are referred by a foreign key column in a given table. The results are sorted by PKTABLE_NAME and KEY_SEQ.

If this type is specified as a parameter, a foreign key table is specified for class_name , and NULL is specified for attr_name.

1 PKTABLE_NAME char *
2 PKCOLUMN_NAME char *
3 FKTABLE_NAME char *
4 FKCOLUMN_NAME char *
5 KEY_SEQ short
6 UPDATE_ACTION

short

  • 0: cascade
  • 1: restrict
  • 2: no action
  • 3: set null
7 DELETE_ACTION

short

  • 0: cascade
  • 1: restrict
  • 2: no action
  • 3: set null
8 FK_NAME char *
9 PK_NAME char *

CCI_SCH_EXPORTED_KEYS

Used to retrieve primary key columns that are referred by all foreign key columns. The results are sorted by FKTABLE_NAME and KEY_SEQ. If this type is specified as a parameter, a primary key table is specified for class_name , and NULL is specified for attr_name.

1 PKTABLE_NAME char *
2 PKCOLUMN_NAME char *
3 FKTABLE_NAME char *
4 FKCOLUMN_NAME char *
5 KEY_SEQ short
6 UPDATE_ACTION

short

  • 0: cascade
  • 1: restrict
  • 2: no action
  • 3: set null
7 DELETE_ACTION

short

  • 0: cascade
  • 1: restrict
  • 2: no action
  • 3: set null
8 FK_NAME char *
9 PK_NAME char *

CCI_SCH_CROSS_REFERENCE

Used to retrieve foreign key information when primary keys and foreign keys in a given table are cross referenced. The results are sorted by FKTABLE_NAME and KEY_SEQ.

If this type is specified as a parameter, a primary key is specified for class_name , and a foreign key table is specified for attr_name.

1 PKTABLE_NAME char *
2 PKCOLUMN_NAME char *
3 FKTABLE_NAME char *
4 FKCOLUMN_NAME char *
5 KEY_SEQ short
6 UPDATE_ACTION

short

  • 0: cascade
  • 1: restrict
  • 2: no action
  • 3: set null
7 DELETE_ACTION

short

  • 0: cascade
  • 1: restrict
  • 2: no action
  • 3: set null
8 FK_NAME char *
9 PK_NAME char *

In the cci_schema_info function, the type argument supports the pattern matching of the LIKE statement for the class_name and attr_name.

type, class_name(table name), and attr_name(column name) That Supports Pattern Matching

type class_name attr_name
CCI_SCH_CLASS (VCLASS) string or NULL always NULL
CCI_SCH_ATTRIBUTE (CLASS ATTRIBUTE) string or NULL string or NULL
CCI_SCH_CLASS_PRIVILEGE string or NULL always NULL
CCI_SCH_ATTR_PRIVILEGE always NULL string or NULL
CCI_SCH_PRIMARY_KEY string or NULL always NULL
CCI_SCH_TRIGGER string or NULL always NULL
  • The type with "NULL" in class_name doesn't support the pattern matching about the table name.
  • The type with "NULL" in attr_name doesn't support the pattern matching about the column name.
  • If the pattern flag is not configured, exact matching will be used for the given table and column names; in this case, no result will be returned if the value is NULL.
  • If flag is configured and the value is NULL, the result will be the same as when "%" is given in the LIKE statement. In other words, the result about all tables or all columns will be returned.

Note

TYPE column of CCI_SCH_CLASS and CCI_SCH_VCLASS: The proxy type is added. When used in OLEDB, ODBC or PHP, vclass is represented without distinguishing between proxy and vclass.

// gcc -o schema_info schema_info.c -m64 -I${CUBRID}/include -lnsl ${CUBRID}/lib/libcascci.so -lpthread

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cas_cci.h"

int
main ()
{
  int conn = 0, req = 0, col_count = 0, res = 0, i, ind;
  char *data, query_result_buffer[1024];
  T_CCI_ERROR cci_error;
  T_CCI_COL_INFO *col_info;
  T_CCI_CUBRID_STMT cmd_type;


  conn = cci_connect ("localhost", 33000, "demodb", "dba", "");
  // get all columns' information of table "athlete"
  // req = cci_schema_info(conn, CCI_SCH_ATTRIBUTE, "athlete", "code", 0, &cci_error);
  req =
    cci_schema_info (conn, CCI_SCH_ATTRIBUTE, "athlete", NULL,
                     CCI_ATTR_NAME_PATTERN_MATCH, &cci_error);

  if (req < 0)
  {
      fprintf (stdout, "(%s, %d) ERROR : %s [%d] \n\n", __FILE__, __LINE__,
               cci_error.err_msg, cci_error.err_code);
      goto _END;
  }
  col_info = cci_get_result_info (req, &cmd_type, &col_count);
  if (!col_info && col_count == 0)
  {
      fprintf (stdout, "(%s, %d) ERROR : cci_get_result_info\n\n", __FILE__,
               __LINE__);
      goto _END;
  }
  res = cci_cursor (req, 1, CCI_CURSOR_FIRST, &cci_error);
  if (res == CCI_ER_NO_MORE_DATA)
  {
      goto _END;
  }
  if (res < 0)
  {
      fprintf (stdout, "(%s, %d) ERROR : %s [%d] \n\n", __FILE__, __LINE__,
               cci_error.err_msg, cci_error.err_code);
      goto _END;
  }


  while (1)
  {
      res = cci_fetch (req, &cci_error);
      if (res < 0)
      {
          fprintf (stdout, "(%s, %d) ERROR : %s [%d] \n\n", __FILE__,
                   __LINE__, cci_error.err_msg, cci_error.err_code);
          goto _END;
      }

      for (i = 1; i <= col_count; i++)
      {
          if ((res = cci_get_data (req, i, CCI_A_TYPE_STR, &data, &ind)) < 0)
          {
              goto _END;
          }
          if (ind != -1)
          {
              strcat (query_result_buffer, data);
              strcat (query_result_buffer, "|");
          }
          else
          {
              strcat (query_result_buffer, "NULL|");
          }
      }
      strcat (query_result_buffer, "\n");

      res = cci_cursor (req, 1, CCI_CURSOR_CURRENT, &cci_error);
      if (res == CCI_ER_NO_MORE_DATA)
      {
          goto _END;
      }
      if (res < 0)
        {
          fprintf (stdout, "(%s, %d) ERROR : %s [%d] \n\n", __FILE__,
                   __LINE__, cci_error.err_msg, cci_error.err_code);
          goto _END;
        }
  }

_END:
  if (req > 0)
    cci_close_req_handle (req);
  if (conn > 0)
    res = cci_disconnect (conn, &cci_error);
  if (res < 0)
    fprintf (stdout, "(%s, %d) ERROR : %s [%d] \n\n", __FILE__, __LINE__,
             cci_error.err_msg, cci_error.err_code);

  fprintf (stdout, "Result : %s\n", query_result_buffer);

  return 0;
}
cci_set_allocators
int cci_set_allocators(CCI_MALLOC_FUNCTION malloc_func, CCI_FREE_FUNCTION free_func, CCI_REALLOC_FUNCTION realloc_func, CCI_CALLOC_FUNCTION calloc_func)

The cci_set_allocators function registers the memory allocation/release functions used by users. By executing this function, you can use user-defined functions for every memory allocation/release jobs being processed in CCI API. If you do not use this function, system functions (malloc, free, realloc, and calloc) are used.

Note

This function can be used only on Linux, so cannot be used on Windows.

Parameters:
  • malloc_func -- (IN) Pointer of externally defined function corresponding to malloc
  • free_func -- (IN) Pointer of externally defined function corresponding to free
  • realloc_func -- (IN) Pointer of externally defined function corresponding to realloc
  • calloc_func -- Pointer of externally defined function corresponding to calloc
Returns:

Error code (0: success)

  • CCI_ER_NOT_IMPLEMENTED

/*
       How to build: gcc -Wall -g -o test_cci test_cci.c -I${CUBRID}/include -L${CUBRID}/lib -lcascci
*/

#include <stdio.h>
#include <stdlib.h>
#include "cas_cci.h"

void *my_malloc(size_t size)
{
    printf ("my malloc: size: %ld\n", size);
    return malloc (size);
}

void *my_calloc(size_t nm, size_t size)
{
    printf ("my calloc: nm: %ld, size: %ld\n", nm, size);
    return calloc (nm, size);
}

void *my_realloc(void *ptr, size_t size)
{
    printf ("my realloc: ptr: %p, size: %ld\n", ptr, size);
    return realloc (ptr, size);
}

void my_free(void *ptr)
{
    printf ("my free: ptr: %p\n", ptr);
    return free (ptr);
}


int test_simple (int con)
{
    int req = 0, col_count = 0, i, ind;
    int error;
    char *data;
    T_CCI_ERROR cci_error;
    T_CCI_COL_INFO *col_info;
    T_CCI_CUBRID_STMT stmt_type;
    char *query = "select * from db_class";

    //preparing the SQL statement
    req = cci_prepare (con, query, 0, &cci_error);
    if (req < 0)
    {
        printf ("prepare error: %d, %s\n", cci_error.err_code,
            cci_error.err_msg);
        goto handle_error;
    }

    //getting column information when the prepared statement is the SELECT query
    col_info = cci_get_result_info (req, &stmt_type, &col_count);
    if (col_info == NULL)
    {
        printf ("get_result_info error\n");
        goto handle_error;
    }

    //Executing the prepared SQL statement
    error = cci_execute (req, 0, 0, &cci_error);
    if (error < 0)
    {
        printf ("execute error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
        goto handle_error;
    }
    while (1)
    {
        //Moving the cursor to access a specific tuple of results
        error = cci_cursor (req, 1, CCI_CURSOR_CURRENT, &cci_error);
        if (error == CCI_ER_NO_MORE_DATA)
        {
            break;
        }
        if (error < 0)
        {
            printf ("cursor error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
            goto handle_error;
        }

        //Fetching the query result into a client buffer
        error = cci_fetch (req, &cci_error);
        if (error < 0)
        {
            printf ("fetch error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
            goto handle_error;
        }
        for (i = 1; i <= col_count; i++)
        {

            //Getting data from the fetched result
            error = cci_get_data (req, i, CCI_A_TYPE_STR, &data, &ind);
            if (error < 0)
            {
                printf ("get_data error: %d, %d\n", error, i);
                goto handle_error;
            }
            printf ("%s\t|", data);
        }
         printf ("\n");
    }

    //Closing the query result
    error = cci_close_query_result(req, &cci_error);
     if (error < 0)
    {
        printf ("cci_close_query_result error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
        goto handle_error;
    }

    //Closing the request handle
    error = cci_close_req_handle(req);
    if (error < 0)
    {
        printf ("cci_close_req_handle error\n");
        goto handle_error;
    }

    //Disconnecting with the server
    error = cci_disconnect (con, &cci_error);
    if (error < 0)
    {
        printf ("cci_disconnect error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
        goto handle_error;
    }
    return 0;

handle_error:
    if (req > 0)
        cci_close_req_handle (req);
    if (con > 0)
        cci_disconnect (con, &cci_error);

    return 1;
}

int main()
{
    int con = 0;

    if (cci_set_allocators (my_malloc, my_free, my_realloc, my_calloc) != 0)
    {
        printf ("cannot register allocators\n");
        return 1;
    };

    //getting a connection handle for a connection with a server
    con = cci_connect ("localhost", 33000, "demodb", "dba", "");
    if (con < 0)
    {
        printf ("cannot connect to database\n");
        return 1;
    }

    test_simple (con);
    return 0;
}
cci_set_autocommit
int cci_set_autocommit(int conn_handle, CCI_AUTOCOMMIT_MODE  autocommit_mode)

The cci_set_autocommit function configures the auto-commit mode of current database connection. It is only used to turn ON/OFF of auto-commit mode. When this function is called, every transaction being processed is committed regardless of configured mode.

Note

CCI_DEFAULT_AUTOCOMMIT in cubrid_broker.conf determines the default autocommit mode upon program startup.

Parameters:
  • conn_handle -- (IN) Connection handle
  • autocommit_mode -- (IN) Configures the auto-commit mode. It has one of the following value: CCI_AUTOCOMMIT_FALSE or CCI_AUTOCOMMIT_TRUE
Returns:

Error code (0: success)

Note

CCI_DEFAULT_AUTOCOMMIT, a broker parameter configured in the cubrid_broker.conf file, determines whether it is in auto-commit mode upon program startup.

cci_set_db_parameter
int cci_set_db_parameter(int conn_handle, T_CCI_DB_PARAM param_name, void* value, T_CCI_ERROR *err_buf)

The cci_set_db_parameter function configures a system parameter. For the type of value for param_name, see cci_get_db_parameter().

Parameters:
  • conn_handle -- (IN) Connection handle
  • param_name -- (IN) System parameter name
  • value -- (IN) Parameter value
  • err_buf -- (OUT) Database error buffer
Returns:

Error code (0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_PARAM_NAME
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_CONNECT

cci_set_element_type
int cci_set_element_type(T_CCI_SET set)

The cci_set_element_type function gets the element type of the T_CCI_SET type value.

Parameters:
  • set -- (IN) cci set pointer
Returns:

Type

cci_set_free
void cci_set_free(T_CCI_SET set)

The cci_set_free function releases the memory allocated to the type value of T_CCI_SET fetched by CCI_A_TYPE_SET with cci_get_data(). The T_CCI_SET type value can be created through fetching cci_get_data() or cci_set_make() function.

Parameters:
  • set -- (IN) cci set pointer
cci_set_get
int cci_set_get(T_CCI_SET set, int index, T_CCI_A_TYPE a_type, void *value, int *indicator)

The cci_set_get function gets the index -th data for the type value of T_CCI_SET.

Parameters:
  • set -- (IN) cci set pointer
  • index -- (IN) set index (base: 1)
  • a_type -- (IN) Type
  • value -- (OUT) Result buffer
  • indicator -- (OUT) null indicator
Returns:

Error code

  • CCI_ER_SET_INDEX
  • CCI_ER_TYPE_CONVERSION
  • CCI_ER_NO_MORE_MEMORY
  • CCI_ER_COMMUNICATION

The data type of value for a_type is shown in the table below.

a_type value type
CCI_A_TYPE_STR char **
CCI_A_TYPE_INT int *
CCI_A_TYPE_FLOAT float *
CCI_A_TYPE_DOUBLE double *
CCI_A_TYPE_BIT T_CCI_BIT *
CCI_A_TYPE_DATE T_CCI_DATE *
CCI_A_TYPE_BIGINT int64_t * (For Windows: __int64 *)
cci_set_holdability
int cci_set_holdability(int conn_handle, int holdable)

Sets whether to enable or disable cursor holdability of the result set from the connection level. When it is 1, the connection is disconnected or the cursor is holdable until the result set is intentionally closed regardless of commit. When it is 0, the result set is closed when committed and the cursor is not holdable. For more details on cursor holdability, see Cursor Holdability.

Parameters:
  • conn_handle -- (IN) Connection handle
  • holdable -- (IN) Cursor holdability setting value (0: not holdable, 1: holdable)
Returns:

Error Code

  • CCI_ER_INVALID_HOLDABILITY

cci_set_isolation_level
int cci_set_isolation_level(int conn_handle, T_CCI_TRAN_ISOLATION  new_isolation_level, T_CCI_ERROR *err_buf)

The cci_set_isolation_level function sets the transaction isolation level of connections. All further transactions for the given connections work as new_isolation_level.

Parameters:
  • conn_handle -- (IN) Connection handle
  • new_isolation_level -- (IN) Transaction isolation level
  • err_buf -- (OUT) Database error buffer
Returns:

Error code

  • CCI_ER_CON_HANDLE
  • CCI_ER_CONNECT
  • CCI_ER_ISOLATION_LEVEL
  • CCI_ER_DBMS

Note If the transaction isolation level is set by cci_set_db_parameter(), only the current transaction is affected. When the transaction is complete, the transaction isolation level returns to the one set by CAS. You must use cci_set_isolation_level () to set the isolation level for the entire connection.

cci_set_lock_timeout
int cci_set_lock_timeout(int conn_handle, int locktimeout, T_CCI_ERROR * err_buf)

The cci_set_lock_timeout function specifies the connection lock timeout as milliseconds. This is the same with calling cci_set_db_parameter (conn_id, CCI_PARAM_LOCK_TIMEOUT, &val, err_buf). See cci_set_db_parameter().

Parameters:
  • conn_handle -- (IN) Connection handle
  • locktimeout -- (IN) lock timeout value(Unit: milliseconds).
Returns:

Error code(0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_PARAM_NAME
  • CCI_ER_DBMS
  • CCI_ER_COMMUNICATION
  • CCI_ER_CONNECT

cci_set_login_timeout
int cci_set_login_timeout(int conn_handle, int timeout, T_CCI_ERROR *err_buf)

The cci_set_login_timeout function specifies the login timeout as milliseconds. The login timeout is applied when an internal reconnection occurs as cci_prepare() or cci_execute() function is called. This change is only applied to the current connection.

Parameters:
  • conn_handle -- (IN) Connection handle
  • timeout -- (IN) Login timeout(unit: milliseconds)
  • err_buf -- (OUT) Error buffer
Returns:

Error code(0: success)

  • CCI_ER_CON_HANDLE
  • CCI_ER_USED_CONNECTION

cci_set_make
int cci_set_make(T_CCI_SET *set, T_CCI_U_TYPE u_type, int size, void *value, int *indicator)

The cci_set_make function makes a set of a new CCI_A_TYPE_SET type. The created set is sent to the server as CCI_A_TYPE_SET by cci_bind_param(). The memory for the set created by cci_set_make() must be freed by cci_set_free(). The type of value for u_type is shown in the table below.

Parameters:
  • set -- (OUT) cci set pointer
  • u_type -- (IN) Element type
  • size -- (IN) set size
  • value -- (IN) set element
  • indicator -- (IN) null indicator array
Returns:

Error code

cci_set_max_row
int cci_set_max_row(int req_handle, int max)

The cci_set_max_row function configures the maximum number of records for the results of the SELECT statement executed by cci_execute(). If the max value is 0, it is the same as not setting the value.

Parameters:
  • req_handle -- (IN) Connection handle
  • max -- (IN) The maximum number of rows
Returns:

Error code

req = cci_prepare( ... );
cci_set_max_row(req, 1);
cci_execute( ... );
cci_set_query_timeout
int cci_set_query_timeout(int req_handle, int milli_sec)

The cci_set_query_timeout function configures timeout value for query execution.

Parameters:
  • req_handle -- (IN) Request handle
  • milli_sec -- Timeout (unit: msec.)
Returns:

Success: Request handle ID (int), Failure: Error code

  • CCI_ER_REQ_HANDLE

The timeout value configured by cci_set_query_timeout affects cci_prepare(), cci_execute(), cci_execute_array(), cci_execute_batch() functions. When timeout occurs in the function and if the disconnect_on_query_timeout value configured in cci_connect_with_url() connection URL is yes, it returns the CCI_ER_QUERY_TIMEOUT error.

These functions can return the CCI_ER_LOGIN_TIMEOUT error if login_timeout is configured in the connection URL, which is an argument of cci_connect_with_url() function; this means that login timeout happens between application client and CAS during re-connection.

It is going through the process of re-connection between application client and CAS when an application restarts or it is re-scheduled. Re-scheduling is a process that CAS chooses an application client, and starts and stops connection in the unit of transaction. If KEEP_CONNECTION, broker parameter, is OFF, it always happens; if AUTO, it can happen depending on its situation. For details, see the description of KEEP_CONNECTION in the Parameter by Broker

cci_set_size
int cci_set_size(T_CCI_SET set)

The cci_set_size function gets the number of elements for the type value of T_CCI_SET.

Parameters:
  • set -- (IN) cci set pointer
Returns:

Size

PHP Driver

CUBRID PHP driver implements an interface to enable access from application in PHP to CUBRID database. Every function offered by CUBRID PHP driver has a prefix cubrid_ such as cubrid_connect() and cubrid_connect_with_url().

The official one is available as a PECL package. PECL is a repository for PHP extensions, providing a directory of all known extensions and holding facilities for downloading and development of PHP extensions. For more information about PECL, visit http://pecl.php.net/ .

CUBRID PHP driver is written based on CCI API so affected by CCI configurations such as CCI_DEFAULT_AUTOCOMMIT.

To download PHP driver or get the latest information, click http://www.cubrid.org/wiki_apis/entry/cubrid-php-driver .

Installing and Configuring PHP

The easiest and fastest way to get all applications installed on your system is to install CUBRID, Apache web server, PHP, and CUBRID PHP driver at the same time. For details, see http://www.cubrid.org/wiki_apis/entry/install-cubrid-with-apache-and-php-on-ubuntu .

For Linux

Configuring the Environment

Installing CUBRID PHP Driver using PECL

If PECL package has been installed on your system, the installation of CUBRID PHP driver is straightforward. PECL will download and compile the driver for you. If you do not have PECL installed, follow the instructions at http://www.cubrid.org/wiki_apis/entry/installing-cubrid-php-driver-using-pecl to get it installed.

  1. Enter the following command to install the latest version of CUBRID PHP driver.

    sudo pecl install cubrid
    

    If you need earlier versions of the driver, you can install exact versions as follows:

    sudo pecl install cubrid-8.3.0.0005
    

    During the installation, you will be prompted to enter CUBRID base install dir autodetect :. Just to make sure your installation goes smoothly, enter the full path to the directory where you have installed CUBRID. For example, if CUBRID has been installed at /home/cubridtest/CUBRID, then enter /home/cubridtest/CUBRID.

  2. Edit the configuration file.

    If you are using CentOS 6.0 and later or Fedora 15 and later, create a file named cubrid.ini, enter a command line extension=cubrid.so, and store the fine in the /etc/php.d directory.

    If you are using earlier versions of CentOS 6.0 or Fedora 15, edit the php.ini file (default location: /etc/php5/apache2/ or /etc/) and add the following two command lines at the end of the file.

    [CUBRID]
    extension=cubrid.so
    
  3. Restart the web server to apply changes.

Installing using apt-get on Ubuntu

  1. If you do not have PHP itself installed, install it using the following command; if you have PHP installed on your system, skip this step.

    sudo apt-get install php5
    
  2. To install CUBRID PHP driver using apt-get, we need to add CUBRID's repository so that Ubuntu knows where to download the packages from and tell the operating system to update its indexes.

    sudo add-apt-repository ppa:cubrid/cubrid
    sudo apt-get update
    
  3. Now install the driver.

    sudo apt-get install php5-cubrid
    

    To install earlier versions, indicate the version as:

    sudo apt-get install php5-cubrid-8.3.1
    

    This will copy the cubrid.so driver to /usr/lib/php5/2009* and add the following configuration lines to /etc/php5/apache2/php.ini.

    [PHP_CUBRID]
    extension=cubrid.so
    
  4. Restart the web server so that PHP can read the module.

    service apache2 restart
    

Installing using Yum on Fedora/CentOS

  1. To install CUBRID PHP driver using yum command, we need to tell Yum where to look for CUBRID package. First, visit one of the following links depending on your operating system.

  2. Choose CUBRID version. You will be given a list of links for your particular version. For example, the following link is provided for Fedora 16 where fc16 means this operating system version.

    rpm -i http://yumrepository.cubrid.org/cubrid_repo_settings/9.0.0/cubridrepo-9.0.0-1.fc16.noarch.rpm
    

    For CentOS, el6.2 means CentOS version 6.2.

    rpm -i http://yumrepository.cubrid.org/cubrid_repo_settings/9.0.0/cubridrepo-9.0.0-1.el6.2.noarch.rpm
    

    Executing this command will tell Yum where to look for CUBRID package.

  3. Execute the command below to install CUBRID PHP driver.

    yum install php-cubrid
    
  4. Restart the web server.

    service httpd restart
    
For Windows

Requirements

Using CUBRID PHP Driver Installer

The CUBRID PHP API Installer is a Windows installer which automatically detects the CUBRID and PHP version and installs the proper driver for you by copying it to the default PHP extensions directory and adding the extension load directives to the php.ini file. In this section, we will explain how to use the CUBRID PHP API Installer to install the CUBRID PHP extension on Windows.

In case you want to remove the CUBRID PHP driver, you just have to run the CUBRID PHP API Installer again in uninstall mode (like any other un-installer on Windows) and it will reset all the changes made during installation.

Before you install CUBRID PHP driver, make sure that paths of PHP and CUBRID are added in the system variable, Path.

  1. Download the CUBRID PHP API installer for Windows from the link below. The current installer includes the drivers for all CUBRID versions.

    http://www.cubrid.org/?mid=downloads&item=php_driver&os=windows

  2. To install the PHP extension, run the installer. Once the installer starts, click the [Next] button.

  3. Agree with the BSD license terms and click the [Next] button.

  4. Choose where you would like to install this CUBRID PHP API Installer and click the [Next] button. You should choose a new folder for this installer like C:\Program Files\CUBRID PHP API.

  5. Give a folder name and click the [Install] button. If you fail installation, you should probably receive an error message. In this case, see "Configuring the environment" below.

  6. If no error message is displayed, this should install the CUBRID PHP extension and update your php.ini file. Click [Finish] to close the installer.

  7. For changes to take place, restart your web server and execute the phpinfo() to confirm CUBRID has successfully been installed.

    _images/image56.png

Configuring the environment

If you have received an error messages, follow the steps below; if you can see CUBRID in phpinfo(), you do not need to look further. By default, when you install CUBRID, it automatically adds its installation directory to the Path system environment variable. To verify the variable have been correctly configured, launch the command prompt ([Start] > [Programs] > [Accessories] > [Command Prompt]) and enter the following commands one by one.

  1. Enter command below in the command prompt as follows.

    php --version
    

    You can see the PHP version like below if it is properly configured.

    C:\Users\Administrator>php --version
    PHP 5.2.9 <cli> <built: Feb 25 2009 15:52:24>
    
  2. Enter command as follows.

    php --version
    

    You can see the CUBRID version like below if it is properly configured.

    C:\Users\Administrator>cubrid --version
    cubrid <cubrid utilities> R2.1
    

If you cannot get the result like above, it is highly likely that your PHP and CUBRID installations went wrong. Try to reinstall them and recheck again. If the path is not automatically specified even after you complete reinstallation, you can do it manually.

  1. Right-click [My Computer] and select [Properties]. The [System Properties] dialog box will appear.
  2. Go to [Advanced] tab and click on [Environment Variables].
  3. Select the variable called Path in the [System variables] box and click [Edit] button. You will notice that the value of that variable contains system paths separated by semi-colon.
  4. Add the paths for CUBRID and PHP in that variable. For example, if PHP is installed in C:\Program Files\PHP and also CUBRID in C:\CUBRID\bin, you will have to append (do not overwrite, just append) these values to the path like C:\CUBRID\bin;C:\Program Files\PHP.
  5. Click [OK] to save and close the dialog box.
  6. To confirm you have done everything correct, check the variable presence in the command prompt.

Downloading and Installing Compiled CUBRID PHP Driver

First, download CUBRID PHP/PDO driver of which versions match the versions of your operating system and PHP installed from http://www.cubrid.org/?mid=downloads&item=php_driver&os=windows&php=detect&driver=detect .

After you download the driver, you will see the php_cubrid.dll file for CUBRID PHP driver or the php_pdo_cubrid.dll file for CUBRID PDO driver. Follow the steps below to install it.

  1. Copy this driver to the default PHP extensions directory (usually located at C:\Program Files\PHP\ext).

  2. Set your system environment. Check if the environment variable PHPRC is C:\Program Files\PHP and system variable path is added with %PHPRC% and %PHPRC\ext.

  3. Edit php.ini (C:\Program Files\PHP\php.ini) and add the following two command lines at the end of the php.ini file.

    [PHP_CUBRID]
    extension=php_cubrid.dll
    

    For CUBRID PDO driver, add command lines below.

    [PHP_PDO_CUBRID]
    extension = php_pdo_cubrid.dll
    
  4. Restart your web server to apply changes.

Building CUBRID PHP Driver from Source Code
For Linux

In this section, we will introduce the way of building CUBRID PHP driver for Linux.

Configuring the environment

  • CUBRID: Install CUBRID. Make sure the environment variable %CUBRID% is defined in your system.
  • PHP 5.3 source code: You can download PHP source code from http://php.net/downloads.php .
  • Apache 2: It can be used to test PHP.
  • CUBRID PHP driver source code: You can download the source code from http://www.cubrid.org/?mid=downloads&item=php_driver . Make sure that the version you download is the same as the version of CUBRID which has been installed on your system.

Compiling CUBRID PHP driver

  1. Download the CUBRID PHP driver, extract it, and enter the directory.

    $> tar zxvf php-<version>.tar.gz (or tar jxvf php-<version>.tar.bz2)
    $> cd php-<version>/ext
    
  2. Run phpize. For more information about getting phpize, see Remark.

    cubrid-php> /usr/bin/phpize
    
  3. Configure the project. It is recommended to execute ./configure -h so that you can check the configuration options (we assume that Apache 2 has been installed in /usr/local).

    cubrid-php>./configure --with-cubrid --with-php-config=/usr/local/bin/php-config
    
    • --with-cubrid=shared: Includes CUBRID support.
    • --with-php-config=PATH: Enters an absolute path of php-config including the file name.
  4. Build the project. If it is successfully compiled, the cubrid.so file will be created in the /modules directory.

  5. Copy the cubrid.so to the /usr/local/php/lib/php/extensions directory; the /usr/local/php is a PHP root directory.

    cubrid-php> mkdir /usr/local/php/lib/php/extensions
    cubrid-php> cp modules/cubrid.so /usr/local/php/lib/php/extensions
    
  6. In the php.ini file, set the extension_dir variable and add the CUBRID PHP driver to the extension variable as shown below.

    extension_dir = "/usr/local/php/lib/php/extension/no-debug-zts-xxx"
    extension = cubrid.so
    

Testing CUBRID PHP driver installation

  1. Create a test.php file as follows:

    <?php phpinfo(); ?>
    
  2. Use web browser to visit http://localhost/test.php. If you can see the following result, it means that installation is successfully completed.

    CUBRID Value
    Version 9.0.0.XXXX

Remark

phpize is a shell script to prepare the PHP extension for compiling. You can get it when you install PHP because it is automatically installed with PHP installation, in general. If it you do not have phpize installed on your system, you can get it by following the steps below.

  1. Download the PHP source code. Make sure that the PHP version works with the PHP extension that you want to use. Extract PHP source code and enter its root directory.

    $> tar zxvf php-<version>.tar.gz (or tar jxvf php-<version>.tar.bz2)
    $> cd php-<version>
    
  2. Configure the project, build, and install it. You can specify the directory you want install PHP by using the option, --prefix.

    php-root> ./configure --prefix=prefix_dir; make; make install
    
  3. You can find phpize in the prefix_dir/bin directory.

For Windows

In this section, we will introduce three ways of building CUBRID PHP driver for Windows. If you have no idea which version you choose, read the following contents first.

  • If you are using PHP with Apache 1 or Apache 2, you should use the VC6 versions of PHP.
  • If you are using PHP with IIS, you should use the VC9 versions of PHP.

VC6 versions are compiled with the legacy Visual Studio 6 compiler; VC9 versions are compiled with the Visual Studio 2008 compiler. The VC9 versions have more improvements in performance and stability.

The VC9 versions require you to have the Microsoft 2008 C++ Runtime (x86) or the Microsoft 2008 C++ Runtime (x64) installed. Do not use VC9 versions with binaries provided by the Apache Software Foundation ( http://www.apache.org/ ).

Building CUBRID PHP Driver with VC9 for PHP 5.3

Configuring the environment

  • CUBRID: Install CUBRID. Make sure the environment variable %CUBRID% is defined in your system.

  • Visual Studio 2008: You can alternately use the free Visual C++ Express Edition or the Visual C++ 9 compiler included in the Windows SDK v6.1 if you are familiar with a makefile. Make sure that you have the Microsoft Visual C++ Redistributable Package installed on your system to use CUBRID PHP VC9 driver.

  • PHP 5.3 binaries: You can install VC9 x86 Non Thread Safe or VC9 x86 Thread Safe. Make sure that the %PHPRC% system environment variable is correctly set. In the [Property Pages] dialog box, select [General] under the [Linker] tree node. You can see $(PHPRC) in [Additional Library Directories].

    _images/image57.jpg
  • PHP 5.3 source code: Remember to get the source code that matches your binary version. After you extract the PHP 5.3 source code, add the %PHP5_SRC% system environment variable and set its value to the path of PHP 5.3 source code. In the [Property Pages] dialog box, select [General] under the [C/C++] tree node. You can see $(PHP5_SRC) in [Additional Include Directories].

    _images/image58.jpg
  • CUBRID PHP driver source code: You can download CUBRID PHP driver source code of which the version is the same as the version of CUBRID that have been installed on your system. You can get it from http://www.cubrid.org/?mid=downloads&item=php_driver .

Note

You do not need to build PHP 5.3 from source code but configuring a project is required. If you do not make configuration settings, you will get the message that a header file (config.w32.h) cannot be found. Read https://wiki.php.net/internals/windows/stepbystepbuild to get more detailed information.

Building CUBRID PHP driver with VC9 for PHP 5.3

  1. Open the php_cubrid.vcproj file under the \win directory. In the [Solution Explorer] pane, right-click on the php_cubrid (project name) and select [Properties].

    _images/image59.jpg
  2. In the [Property Page] dialog box, click the [Configuration Manager] button. Select one of four values among Release_TS, Release_NTS, Debug_TS, and Debug_NTS in [Configuration] of [Project contexts] and click the [Close] button.

    _images/image60.jpg
  3. After you complete the properties modification, click the [OK] button and press the <F7> key to compile the driver. Then, we have the php_cubrid.dll file built.

  4. You need to make PHP recognize the php_cubrid.dll file as an extension. To do this:

    • Create a new folder named cubrid where PHP has been installed and copy the php_cubrid.dll file to the cubrid folder. You can also put the php_cubrid.dll file in %PHPRC%\ext if this directory exists.
    • In the php.ini file, enter the path of the php_cubrid.dll file as an extension_dir variable value and enter php_cubrid.dll as an extension value.

Building CUBRID PHP Driver with VC6 for PHP 5.2/5.3

Configuring the environment

  • CUBRID: Install CUBRID. Make sure that the environment variable %CUBRID% is defined in your system.

  • Visual C++ 6.0 SP6

  • Windows Server Feb. 2003 SDK: It is recommended to use Windows Server Feb. 2008 SDK because every official release and snapshot are compiled with Visual C++ 6.0 SP6 and Windows Server Feb. 2003 SDK. You can configure the default settings without using this SDK; however, there is possibility that an error would occur while building the driver. In this case, you should fix the error yourself.

  • PHP 5.3/5.2 binaries: You can install VC6 x86 Non Thread Safe or VC6 x86 Thread Safe. Make sure that the value of the %PHPRC% system environment variable is correctly set. In the [Project Settings] dialog box, you can find $(PHPRC) in [Additional library path] of the [Link] tab.

    _images/image61.jpg
  • PHP 5.2/5.3 source code: Remember to get the source that matches your binary version. After you extract the PHP 5.3 source code, add the %PHP5_SRC% system environment variable and set its value to the path of PHP 5.3 source code. In the [Project Settings] dialog box of VC6 project, you can find $(PHP5_SRC) in [Additional include directories] of the [C/C++] tab.

    _images/image62.jpg
  • CUBRID PHP driver source code: You can download CUBRID PHP driver source code of which the version is the same as the version of CUBRID that has been installed on your system. You can get it from http://www.cubrid.org/?mid=downloads&item=php_driver .

Note

If you build CUBRID PHP driver with PHP 5.3 source code, you need to make some configuration settings for PHP 5.3 on Windows. If you do not make these settings, you will get the message that a header file (config.w32.h) cannot be found. Read https://wiki.php.net/internals/windows/stepbystepbuild to get more detailed information.

Building CUBRID PHP driver

  1. Open the project in the [Build] menu and then select [Set Active Configuration].

    _images/image63.jpg
  2. There are four types of configuration settings (Win32 Release_TS, Win32 Release, Win32 Debug_TS, and Win32 Debug). Select one of them depending on your system and then click the [OK] button.

    _images/image64.jpg
  3. After you complete the properties modification, click the [OK] button and press the <F7> key to compile the driver. Then you have the php_cubrid.dll file built.

  4. You need to make PHP recognize the php_cubrid.dll file as an extension. To do this:

    • Create a new folder named cubrid where PHP is installed and copy php_cubrid.dll to the cubrid folder. You can also put php_cubrid.dll in %PHPRC%\ext if this directory exists.
    • Set the extension_dir variable and add CUBRID PHP driver to extension variable in the php.ini file.

Building CUBRID PHP Driver for 64-bit Windows

PHP for 64-bit Windows

We do not provide 64-bit Windows CUBRID PHP driver, mainly because there is no official 64-bit Windows PHP at windows.php.net (only x86 versions are available). But sometimes you need 64-bit Windows binaries for PHP. In that case you can build it from source codes. Best of all, some guys have already done this (see http://www.anindya.com/). Here, we will not describe how to build x64 PHP itself.

You can find the supported compilers to build PHP on Windows at https://wiki.php.net/internals/windows/compiler . You can see that both VC++ 8 (2005) and VC++ 9 (2008 SP1 only) can be used to build 64-bit PHP. Earlier versions of Visual C++ 2005, the Windows Server Fed. 2003 SDK was the only way to build 64-bit Windows applications.

Apache for 64-bit Windows

There is no official Apache for 64-bit Windows either. Instead, you can use IIS as your Windows Web Server on 64-bit Windows. If you really need VC9 x64 versions of Apache, you can find it at http://www.anindya.com/ .

Configuring the environment

  • CUBRID for 64-bit Windows: You can install the latest version of CUBRID for 64-bit Windows. Make sure the environment variable %CUBRID% is defined in your system.
  • Visual Studio 2008: You can alternately use the free Visual C++ Express Edition or the Visual C++ 9 compiler in the Windows SDK v6.1 if you are familiar with a makefile.
  • SDK 6.1: If you are using VC9, you need Microsoft Windows SDK for Windows Server 2008 and .NET Framework 3.5 (also known as the SDK 6.1).
  • PHP 5.3 binaries for 64-bit Windows: You can build your own VC9 x64 PHP with SDK 6.1 or you can get it at http://www.anindya.com . Both VC9 x64 Non Thread Safe and VC9 x64 Thread Safe are available. After you have installed it, check if the value of system environment variable %PHPRC% is correctly set.
  • PHP 5.3 source code: Remember to get the src package that matches your binary version. After you extract the PHP 5.3 src, add system environment variable %PHP5_SRC% and set its value to the path of PHP 5.3 source code. In the VC9 [Property Pages] dialog box, select [General] under the [C/C++] tree node. You can see $(PHP5_SRC) in [Additional Include Directories].
  • CUBRID PHP driver source code: You can download CUBRID PHP driver source code of which the version is the same as the version of CUBRID that is installed on your system. You can get it from http://www.cubrid.org/?mid=downloads&item=php_driver .

Note

You do not need to build PHP 5.3 from source code; however, configuring a project is required. If you do not make configuration settings, you will get the message that a header file (config.w32.h) cannot be found. Read https://wiki.php.net/internals/windows/stepbystepbuild to get more detailed information.

Configuring PHP 5.3

  1. After you have installed SDK 6.1, click the [CMD Shell] shortcut under the [Microsoft Windows SDK v6.1] folder (Windows Start menu).

    _images/image65.png
  2. Run setenv /x64 /release.

    _images/image66.png
  3. Enter PHP 5.3 source code directory in the command prompt and run buildconf to generate the configure.js file.

    _images/image67.png

    Or you can also double-click the buildconf.bat file.

    _images/image68.png
  4. Run the configure command to configure the PHP project.

    _images/image69.png _images/image70.png

Building CUBRID PHP dirver

  1. Open the php_cubrid.vcproj file under the \win directory. In the [Solution Explorer] on the left, right-click on the php_cubrid project name and select [Properties].

  2. On the top right corner of the [Property Pages] dialog box, click [Configuration Manager].

    _images/image71.png
  3. In the [Configuration Manager] dialog box, you can see four types of configurations (Release_TS, Release_NTS, Debug_TS, and Debug_NTS) in the [Active solution configuration] dropdown list. Select New in the dropdown list so that you can create a new one for your x64 build.

    _images/image72.png
  4. In the [New Solution Configuration] dialog box, enter a value in the Name box (e.g., Release_TS_x64). In the [Copy settings from] dropdown list, select the corresponding x86 configuration and click [OK].

    _images/image73.png
  5. In the [Configuration Manager] dialog box, select the value x64 in the [Platform] dropdown list. If it does not exist, select New.

    _images/image74.png
    • In the [New Project Platform] dialog box, select x64 option in the [New platform] dropdown list.
    _images/image75.png
  6. In the [Property Pages] dialog box, select [Preprocessor] under the [C/C++] tree node. In [Preprocessor Definitions], delete _USE_32BIT_TIME_T and click [OK] to close the dialog box.

    _images/image76.png
  7. Press the <F7> key to compile. Now you will get the CUBRID PHP driver for 64-bit Windows.

PHP Programming
Connecting to a Database

The first step of database applications is to use cubrid_connect () or cubrid_connect_with_url () function which provides database connection. Once cubrid_connect () or cubrid_connect_with_url () function is executed successfully, you can use any functions available in the database. It is very important to call the cubrid_disconnect () function before applications are terminated. The cubrid_disconnect () function terminates the current transaction as well as the connection handle and all request handles created by the cubrid_connect () function.

Note

  • The database connection in thread-based programming must be used independently each other.
  • In autocommit mode, the transaction is not committed if all results are not fetched after running the SELECT statement. Therefore, although in autocommit mode, you should end the transaction by executing COMMIT or ROLLBACK if some error occurs during fetching for the resultset.
Transactions and Auto-Commit

CUBRID PHP supports transaction and auto-commit mode. Auto-commit mode means that every query that you run has its own implicit transaction. You can use the cubrid_get_autocommit () function to get the status of current connection auto-commit mode and use the cubrid_set_autocommit () function to enable/disable auto-commit mode of current connection. In auto-commit mode, any transactions being executed are committed regardless of whether it is set to ON or OFF.

The default value of auto-commit mode upon application startup is configured by the CCI_DEFAULT_AUTOCOMMIT (broker parameter). If the broker parameter value is not configured, the default value is set to ON.

If you set auto-commit mode to OFF in the cubrid_set_autocommit () function, you can handle transactions by specifying a proper function; to commit transactions, use the cubrid_commit () function and to roll back transactions, use the cubrid_rollback () function. If you use the cubrid_disconnect () function, transactions will be disconnected and jobs which have not been committed will be rolled back.

Processing Queries

Executing queries

The following are the basic steps to execute queries.

  • Creating a connection handle
  • Creating a request handle for an SQL query request
  • Fetching result
  • Disconnecting the request handle
$con = cubrid_connect("192.168.0.10", 33000, "demodb");
if($con) {
    $req = cubrid_execute($con, "select * from code");
    if($req) {
        while ($row = cubrid_fetch($req)) {
            echo $row["s_name"];
            echo $row["f_name"];
        }
        cubrid_close_request($req);
    }
    cubrid_disconnect($con);
}

Column types and names of the query result

The cubrid_column_types () function is used to get arrays containing column types and the cubrid_column_types () functions is used to get arrays containing colunm names.

$req = cubrid_execute($con, "select host_year, host_city from olympic");
if($req) {
    $col_types = cubrid_column_types($req);
    $col_names = cubrid_column_names($req);

    while (list($key, $col_type) = each($col_types)) {
        echo $col_type;
    }
    while (list($key, $col_name) = each($col_names))
        echo $col_name;
    }
    cubrid_close_request($req);
}

Controlling a cursor

The cubrid_move_cursor () function is used to move a cursor to a specified position from one of three points: beginning of the query result, current cursor position, or end of the query result).

$req = cubrid_execute($con, "select host_year, host_city from olympic order by host_year");
if($req) {
    cubrid_move_cursor($req, 20, CUBRID_CURSOR_CURRENT)
    while ($row = cubrid_fetch($req, CUBRID_ASSOC)) {
        echo $row["host_year"]." ";
        echo $row["host_city"]."\n";
    }
}

Result array types

One of the following three types of arrays is used in the result of the cubrid_fetch () function. The array types can be determined when the cubrid_fetch () function is called. Of array types, the associative array uses string indexes and the numeric array uses number indexes. The last array includes both associative and numeric arrays.

  • Numeric array

    while (list($id, $name) = cubrid_fetch($req, CUBRID_NUM)) {
        echo $id;
        echo $name;
    }
    
  • Associative array

    while ($row = cubrid_fetch($req, CUBRID_ASSOC)) {
        echo $row["id"];
        echo $row["name"];
    }
    

Catalog Operations

The cubrid_schema () function is used to get database schema information such as classes, virtual classes, attributes, methods, triggers, and constraints. The return value of the cubrid_schema () function is a two-dimensional array.

$pk = cubrid_schema($con, CUBRID_SCH_PRIMARY_KEY, "game");
if ($pk) {
    print_r($pk);
}

$fk = cubrid_schema($con, CUBRID_SCH_IMPORTED_KEYS, "game");
if ($fk) {
    print_r($fk);
}

Error Handling

When an error occurs, most of PHP interfaces display error messages and return false or -1. The cubrid_error_msg (), cubrid_error_code () and cubrid_error_code_facility () functions are used to check error messages, error codes, and error facility codes.

The return value of the cubrid_error_code_facility () function is one of the following (CUBRID_FACILITY_DBMS (DBMS error), CUBRID_FACILITY_CAS (CAS server error), CUBRID_FACILITY_CCI (CCI error), or CUBRID_FACILITY_CLIENT (PHP module error).

Using OIDs

The OID value in the currently updated f record by using the cubrid_current_oid function if it is used together with query that can update the CUBRID_INCLUDE_OID option in the cubrid_execute () function.

$req = cubrid_execute($con, "select * from person where id = 1", CUBRID_INCLUDE_OID);
if ($req) {
    while ($row = cubrid_fetch($req)) {
        echo cubrid_current_oid($req);
        echo $row["id"];
        echo $row["name"];
    }
    cubrid_close_request($req);
}

Values in every attribute, specified attributes, or a single attribute of an instance can be obtained by using OIDs.

If any attributes are not specified in the cubrid_get () function, values in every attribute are returned (a). If attributes is specified in the array data type, the array containing the specified attribute value is returned in the associative array (b). If a single attribute it is specified in the string type, a value of the attributed is returned (c).

$attrarray = cubrid_get ($con, $oid); // (a)
$attrarray = cubrid_get ($con, $oid, array("id", "name")); // (b)
$attrarray = cubrid_get ($con, $oid, "id"); // (c)

The attribute values of an instance can be updated by using OIDs. To update a single attribute value, specify attribute name and value in the string type (a). To update multiple attribute values, specify attribute names and values in the associative array (b).

$cubrid_put ($con, $oid, "id", 1); // (a)
$cubrid_put ($con, $oid, array("id"=>1, "name"=>"Tomas")); // (b)

Using Collections

You can use the collection data types through PHP array data types or functions that support array data types. The following example shows how to fetch query result by using the cubrid_fetch () function.

$row = cubrid_fetch ($req);
$col = $row["customer"];
while (list ($key, $cust) = each ($col)) {
   echo $cust;
}

You can get values of collection attributes. The example shows how to get values of collection attributes by using the cubrid_col_get () function.

$tels = cubrid_col_get ($con, $oid, "tels");
while (list ($key, $tel) = each ($tels)) {
   echo $tel."\n";
}

You can directly update values of collection types by using cubrid_set_add() or cubrid_set_drop() function.

$tels = cubrid_col_get ($con, $oid, "tels");
while (list ($key, $tel) = each ($tels)) {
   $res = cubrid_set_drop ($con, $oid, "tel", $tel);
}

cubrid_commit ($con);

Note

If a string longer than defined max length is inserted (INSERT) or updated (UPDATE), the string will be truncated.

PDO Driver

The official CUBRID PHP Data Objects (PDO) driver is available as a PECL package and it implements the PDO interface to enable access from PDO to CUBRID.PDO is available with PHP 5.1. For PHP 5.0, you can use it as a PECL extension. PDO cannot run with earlier versions of PHP 5.0 because it requires the new OO features in the core of PHP 5.0.

PDO provides a data-access abstraction layer, which means that, regardless of which database you are using, you use the same functions to issue queries and fetch data; PDO does not provide a database abstraction. Using PDO as a database interface layer can have important advantages over "direct" PHP database drivers as follows:

  • Portable PHP code between different databases and database abstraction.
  • Supports SQL parameters and bind.
  • Safer SQLs (syntax verification, escaping, it helps protect against SQL injections etc.)
  • Cleaner programming model

In particular, having a CUBRID PDO driver means that any application that uses PDO as a database interface should work with CUBRID.

CUBRID PDO driver is based on CCI API so affected by CCI configurations such as CCI_DEFAULT_AUTOCOMMIT.

To download PDO driver or get the latest information, click http://www.cubrid.org/wiki_apis/entry/cubrid-pdo-driver .

Installing and Configuring PDO
Linux

Requirements

Installing CUBRID PHP Driver using PECL

If PECL package has been installed on your system, the installation of CUBRID PDO driver is straightforward. PECL will download and compile the driver for you. If you do not have PECL installed, follow the instructions at http://www.cubrid.org/wiki_apis/entry/installing-cubrid-php-driver-using-pecl to get it installed.

  1. Enter the following command to install the latest version of CUBRID PDO driver.

    sudo pecl install pdo_cubrid
    

    If you need earlier versions of the driver, you can install exact versions as follows:

    sudo pecl install pdo_cubrid-8.3.1.0003
    

    During the installation, you will be prompted to enter CUBRID base install dir autodetect :. Just to make sure your installation goes smoothly, enter the full path to the directory where you have CUBRID installed. For example, if CUBRID has been installed at /home/cubridtest/CUBRID, then enter /home/cubridtest/CUBRID.

  2. Edit the configuration file.

    • If you are using CentOS 6.0 and later or Fedora 15 and later, create a file named pdo_cubrid.ini, enter a command line extension=pdo_cubrid.so, and store the file in the /etc/php.d directory.

    • If you are using earlier versions of Cent0S or Fedora 15, edit the php.ini file (default location: /etc/php5/apache2 or /etc/) and add the following two command lines at the end of the file.

      [CUBRID]
      extension=pdo_cubrid.so
      
  3. Restart the web server to apply changes.

Windows

Requirements

Downloading and Installing Compiled CUBRID PDO Driver

First, download CUBRID PHP/PDO driver of which versions match the versions of your operating system and PHP installed at http://www.cubrid.org/?mid=downloads&item=php_driver&os=windows&ostype=any&php=any&driver_type=pdo.

After you download the driver, you will see the php_cubrid.dll file for CUBRID PHP driver or the php_pdo_cubrid.dll file for CUBRID PDO driver. Follow the steps below to install it.

  1. Copy this driver to the default PHP extensions directory (usually located at C:\Program Files\PHP\ext).

  2. Set your system environment. Check if the environment variable PHPRC is C:\Program Files\PHP and system variable path is added with %PHPRC% and %PHPRC%\ext.

  3. Edit php.ini (C:\Program Files\PHP\php.ini) and add the following two lines at the end of the php.ini file.

    [PHP_PDO_CUBRID]
    extension=php_pdo_cubrid.dll
    

    For CUBRID PHP driver, add command lines below.

    [PHP_PDO_CUBRID]
    extension = php_pdo_cubrid.dll
    
  4. Restart your web server to apply changes.

PDO Programming
Data Source Name (DSN)

The PDO_CUBRID data source name (DSN) consists of the following elements:

Element Description
DSN prefix The DSN prefix is cubrid.
host The hostname on which the database server resides
port The port number where the database server is listening
dbname The name of the database

Example

"cubrid:host=127.0.0.1;port=33000;dbname=demodb"
Predefined Constants

The constants defined by CUBRID PDO driver are available only when the extension has been either compiled into PHP or dynamically loaded at runtime. In addition, these driver-specific constants should only be used if you are using PDO driver. Using driver-specific attributes with another driver may result in unexpected behavior.

The PDO::getAttribute() function may be used to obtain the PDO_ATTR_DRIVER_NAME attribute value to check the driver if your code can run.

The constants below can be used with the PDO::cubrid_schema function to get schema information.

Constant Type Description
PDO::CUBRID_SCH_TABLE integer Gets name and type of table in CUBRID.
PDO::CUBRID_SCH_VIEW integer Gets name and type of view in CUBRID.
PDO::CUBRID_SCH_QUERY_SPEC integer Get the query definition of view.
PDO::CUBRID_SCH_ATTRIBUTE integer Gets the attributes of table column.
PDO::CUBRID_SCH_TABLE_ATTRIBUTE integer Gets the attributes of table.
PDO::CUBRID_SCH_TABLE_METHOD integer Gets the instance method. The instance method is a method called by a class instance. It is used more often than the class method because most operations are executed in the instance.
PDO::CUBRID_SCH_METHOD_FILE integer Gets the information of the file where the method of the table is defined.
PDO::CUBRID_SCH_SUPER_TABLE integer Gets the name and type of table which table inherits attributes from.
PDO::CUBRID_SCH_SUB_TABLE integer Gets the name and type of table which inherits attributes from this table.
PDO::CUBRID_SCH_CONSTRAINT integer Gets the table constraints.
PDO::CUBRID_SCH_TRIGGER integer Gets the table triggers.
PDO::CUBRID_SCH_TABLE_PRIVILEGE integer Gets the privilege information of table.
PDO::CUBRID_SCH_COL_PRIVILEGE integer Gets the privilege information of column.
PDO::CUBRID_SCH_DIRECT_SUPER_TABLE integer Gets the direct super table of table.
PDO::CUBRID_SCH_DIRECT_PRIMARY_KEY integer Gets the table primary key.
PDO::CUBRID_SCH_IMPORTED_KEYS integer Gets imported keys of table.
PDO::CUBRID_SCH_EXPORTED_KEYS integer Gets exported keys of table.
PDO::CUBRID_SCH_CROSS_REFERENCE integer Gets reference relationship of two tables.
PDO Sample Program
Verifying CUBRID PDO Driver Version

If you want to verify that the CUBRID PDO driver is accessible, you can use the PDO::getAvailableDrivers () function.

<?php
echo'PDO Drivers available:
';
foreach(PDO::getAvailableDrivers()as $driver)
{
if($driver =="cubrid"){
echo" - Driver: <b>".$driver.'</b>
';
}else{
echo" - Driver: ".$driver.'
';
}
}
?>

This script will output all the currently installed PDO drivers:

PDO Drivers available:
- Driver: mysql
- Driver: pgsql
- Driver: sqlite
- Driver: sqlite2
- Driver: cubrid
Connecting to CUBRID

Use the data source name (DSN) to connect to the database server. For details about DSN, see Data Source Name (DSN).

Below is a simple PHP example script which performs a PDO connection to the CUBRID demodb database. You can notice that errors are handling in PDO by using a try-catch mechanism and the connection is closed by assigning NULL to the connection object.

<?php
$database ="demodb";
$host ="localhost";
$port ="30000";//use default value
$username ="dba";
$password ="";

try{
//cubrid:host=localhost;port=33000;dbname=demodb
$conn_str ="cubrid:dbname=".$database.";host=".$host.";port=".$port;
echo"PDO connect string: ".$conn_str."
";
$db =new PDO($conn_str, $username, $password );
echo"PDO connection created ok!"."
";
$db = null;//disconnect
}catch(PDOException $e){
echo"Error: ".$e->getMessage()."
";
}
?>

If connection succeeds, the output of this script is as follows:

PDO connect string: cubrid:dbname=demodb;host=localhost;port=30000
PDO connection created ok!
Executing a SELECT Statement

In PDO, there is more than one way to execute SQL queries.

  • Using the query () function
  • Using prepared statements (see prepare ()/ execute ()) functions)
  • Using the exec () function

The example script below shows the simplest one - using the query () function. You can retrieve the return values from the resultset (a PDOStatement object) by using the column names, like $rs["column_name"].

Note that when you use the query () function, you must ensure that the query code is properly escaped. For information about escaping, see PDO::quote () function.

<?php
include("_db_config.php");
include("_db_connect.php");

$sql ="SELECT * FROM code";
echo"Executing SQL: <b>".$sql.'</b>
';
echo'
';

try{
foreach($db->query($sql)as $row){
echo $row['s_name'].' - '. $row['f_name'].'
';
}
}catch(PDOException $e){
echo $e->getMessage();
}

$db = null;//disconnect
?>

The output of the script is as follows:

Executing SQL: SELECT * FROM code

X - Mixed
W - Woman
M - Man
B - Bronze
S - Silver
G - Gold
Executing an UPDATE Statement

The following example shows how to execute an UPDATE statement by using a prepared statement and parameters. You can use the exec () function as an alternative.

<?php
include("_db_config.php");
include("_db_connect.php");

$s_name ='X';
$f_name ='test';
$sql ="UPDATE code SET f_name=:f_name WHERE s_name=:s_name";

echo"Executing SQL: <b>".$sql.'</b>
';
echo'
';

echo":f_name: <b>".$f_name.'</b>
';
echo'
';
echo":s_name: <b>".$s_name.'</b>
';
echo'
';

$qe = $db->prepare($sql);
$qe->execute(array(':s_name'=>$s_name,':f_name'=>$f_name));

$sql ="SELECT * FROM code";
echo"Executing SQL: <b>".$sql.'</b>
';
echo'
';

try{
foreach($db->query($sql)as $row){
echo $row['s_name'].' - '. $row['f_name'].'
';
}
}catch(PDOException $e){
echo $e->getMessage();
}

$db = null;//disconnect
?>

The output of the script is as follows:

Executing SQL: UPDATE code SET f_name=:f_name WHERE s_name=:s_name

:f_name: test

:s_name: X

Executing SQL: SELECT * FROM code

X - test
W - Woman
M - Man
B - Bronze
S - Silver
G - Gold
Using prepare and bind

Prepared statements are one of the major features offered by PDO and you can take following benefits by using them.

  • SQL prepared statements need to be parsed only once even if they are executed multiple times with different parameter values. Therefore, using a prepared statement minimizes the resources and ,in general, the prepared statements run faster.
  • It helps to prevent SQL injection attacks by eliminating the need to manually quote the parameters; however, if other parts of the SQL query are being built up with unescaped input, SQL injection is still possible.

The example script below shows how to retrieve data by using a prepared statement.

<?php
include("_db_config.php");
include("_db_connect.php");

$sql ="SELECT * FROM code WHERE s_name NOT LIKE :s_name";
echo"Executing SQL: <b>".$sql.'</b>
';

$s_name ='xyz';
echo":s_name: <b>".$s_name.'</b>
';

echo'
';

try{
$stmt = $db->prepare($sql);

$stmt->bindParam(':s_name', $s_name, PDO::PARAM_STR);
$stmt->execute();

$result = $stmt->fetchAll();
foreach($result as $row)
{
echo $row['s_name'].' - '. $row['f_name'].'
';
}
}catch(PDOException $e){
echo $e->getMessage();
}
echo'
';

$sql ="SELECT * FROM code WHERE s_name NOT LIKE :s_name";
echo"Executing SQL: <b>".$sql.'</b>
';

$s_name ='X';
echo":s_name: <b>".$s_name.'</b>
';

echo'
';

try{
$stmt = $db->prepare($sql);

$stmt->bindParam(':s_name', $s_name, PDO::PARAM_STR);
$stmt->execute();

$result = $stmt->fetchAll();
foreach($result as $row)
{
echo $row['s_name'].' - '. $row['f_name'].'
';
}
$stmt->closeCursor();
}catch(PDOException $e){
echo $e->getMessage();
}
echo'
';

$db = null;//disconnect
?>

The output of the script is as follows:

Executing SQL: SELECT * FROM code WHERE s_name NOT LIKE :s_name
:s_name: xyz

X - Mixed
W - Woman
M - Man
B - Bronze
S - Silver
G - Gold

Executing SQL: SELECT * FROM code WHERE s_name NOT LIKE :s_name
:s_name: X

W - Woman
M - Man
B - Bronze
S - Silver
G - Gold
Using the PDO::getAttribute() Function

The PDO::getAttribute () function is very useful to retrieve the database connection attributes. For example,

  • Driver name
  • Database version
  • Auto-commit state
  • Error mode

Note that if you want to set attributes values (assuming that they are writable), you should use the PDO::setAttribute function.

The following example script shows how to retrieve the current versions of client and server by using the PDO::getAttribute () function.

<?php
include("_db_config.php");
include("_db_connect.php");

echo"Driver name: <b>".$db->getAttribute(PDO::ATTR_DRIVER_NAME)."</b>";
echo"
";
echo"Client version: <b>".$db->getAttribute(PDO::ATTR_CLIENT_VERSION)."</b>";
echo"
";
echo"Server version: <b>".$db->getAttribute(PDO::ATTR_SERVER_VERSION)."</b>";
echo"
";

$db = null;//disconnect
?>

The output of the script is as follows:

Driver name: cubrid
Client version: 8.3.0
Server version: 8.3.0.0337
CUBRID PDO Extensions

In CUBRID, the PDO::cubrid_schema() function is offered as an extension; the function is used to retrieve the database schema and metadata information. Below is an example script that returns information about primary key for the nation table by using this function.

<?php
include("_db_config.php");
include("_db_connect.php");
try{
echo"Get PRIMARY KEY for table: <b>nation</b>:

";
$pk_list = $db->cubrid_schema(PDO::CUBRID_SCH_PRIMARY_KEY,"nation");
print_r($pk_list);
}catch(PDOException $e){
echo $e->getMessage();
}

$db = null;//disconnect
?>

The output of the script is as follows:

Get PRIMARY KEY for table: nation:
Array ( [0] => Array ( [CLASS_NAME] => nation [ATTR_NAME] => code [KEY_SEQ] => 1 [KEY_NAME] => pk_nation_code ) )
PDO API

For more information about PHP Data Objects (PDO) API, see http://docs.php.net/manual/en/book.pdo.php. The API provided by CUBRID PDO driver is as follows:

For more information about CUBRID PDO API provides, see http://ftp.cubrid.org/CUBRID_Docs/Drivers/PDO/.

ODBC Driver

CUBRID ODBC driver supports ODBC version 3.52. It also ODBC core and some parts of Level 1 and Level 2 API. Because CUBRID ODBC driver has been developed based on the ODBC Spec 3.x, backward compatibility is not completely ensured for programs written based on the ODBC Spec 2.x.

CUBRID ODBC driver is written based on CCI API, but it's not affected by CCI_DEFAULT_AUTOCOMMIT exceptionally.

Note

ODBC is not affected by CCI_DEFAULT_AUTOCOMMIT is from 9.3 version. In the previous versions, you should set CCI_DEFAULT_AUTOCOMMIT as OFF.

To download ODBC driver or get the latest information, click http://www.cubrid.org/wiki_apis/entry/cubrid-odbc-driver.

Data Type Mapping Between CUBRID and ODBC

The following table shows the data type mapping relationship between CUBRID and ODBC.

CUBRID Data Type ODBC Data Type
CHAR SQL_CHAR
VARCHAR SQL_VARCHAR
STRING SQL_LONGVARCHAR
BIT SQL_BINARY
VARYING BIT SQL_VARBINARY
NUMERIC SQL_NUMERIC
INT SQL_INTEGER
SHORT SQL_SMALLINT
FLOAT SQL_FLOAT
DOUBLE SQL_DOUBLE
BIGINT SQL_BIGINT
DATE SQL_TYPE_DATE
TIME SQL_TYPE_TIME
TIMESTAMP SQL_TYPE_TIMESTAMP
DATETIME SQL_TYPE_TIMESTAMP
OID SQL_CHAR(32)
SET, MULTISET, SEQUENCE SQL_VARCHAR(MAX_STRING_LENGTH)
Configuring and Environment ODBC

Requirements

  • CUBRID 2008 R4.4 (8.4.4) or later (32-bit or 64-bit)

Configuring CUBRID ODBC Driver

CUBRID ODBC driver is automatically installed upon CUBRID installation. You can check whether it is properly installed in the [Control Panel] > [Administrative Tools] > [Data Source (ODBC)] > [Drivers] tab.

_images/image77.png

Choosing 32-bit ODBC driver on 64-bit Windows

To run 32-bit application, 32-bit ODBC driver is required. If you have to choose 32-bit ODBC driver on 64-bit Windows, run C:WINDOWSSysWOW64odbcad32.exe .

Microsoft Windows 64-bit platform support the environment to run 32-bit application on 64-bit environment, which is called WOW64 (Windows-32-on-Windows-64). This environment maintains its own copy of the registry that is only for 32-bit applications.

Configuring DNS

After you check the CUBRID ODBC driver installed, configure DSN as a database where the applications are trying to connect. To configure, click the [Add] button in the ODBC Data Source Administrator dialog box. Then, the following dialog box will appear. Select "CUBRID Driver" and then click the [Finish] button.

_images/image78.png

In the [Config CUBRID Data Sources] dialog box, enter information as follows:

_images/image79.png
  • DSN : The name of a source data
  • DB Name : The name of a database to be connected
  • DB User : The name of a database user
  • Password : The password of a database user
  • Server Address : The host address of a database. The value should be either localhost or the IP address of other server.
  • Server Port : The number of a broker port. You can check the CUBRID broker port number in the cubrid_broker.conf file. The default value is 33,000. To verify the port number, check the BROKER_PORT value in the cubrid_broker.conf file or enter the cubrid service status in the command prompt. The result will be displayed as follows:
_images/image80.png
  • FETCH_SIZE : A value configures the number of records fetched from server whenever the cci_fetch () function of CCI library (which CUBRID ODBC driver internally uses) is called.

After you filled out every field, click the [OK] button. You will notice that data source is added in the [User Data Sources] as shown below.

_images/image81.png

Connecting to a Database Directly without DSN

It is also possible to connect to a CUBRID database directly in the application source code by using the connecting string. Below shows the example of connection string.

conn = "driver={CUBRID Driver};server=localhost;port=33000;uid=dba;pwd=;db_name=demodb;"

Note

Make sure that your database is running before you try to connect to a CUBRID database. Otherwise, you will receive an error indicating that ODBC call has failed. To start the database called demodb, enter cubrid server start demodb in the command prompt.

ODBC Programming
Configuring Connection String

When you are programming CUBRID ODBC, write the connection strings as follows:

Category Example Description
Driver CUBRID Driver Unicode Driver name
UID PUBLIC User ID
PWD xxx Password
FETCH_SIZE 100 Fetch size
PORT 33000 The broker port number
SERVER 127.0.0.1 The IP address or the host name of a CUBRID broker server
DB_NAME demodb Database name
DESCRIPTION cubrid_test Description
CHARSET utf-8 Character set

The following shows the result of using connection strings above.

"DRIVER={CUBRID Driver Unicode};UID=PUBLIC;PWD=xxx;FETCH_SIZE=100;PORT=33000;SERVER=127.0.0.1;DB_NAME=demodb;DESCRIPTION=cubrid_test;CHARSET=utf-8"

If you use UTF-8 unicode, install a driver for unicode and input the driver name in the connection string as "Driver={CUBRID Driver Unicode}". Unicode is only supported in 9.3.0.0002 or higher version of CUBRID ODBC driver.

Note

  • Because a semi-colon (;) is used as a separator in URL string, it is not allowed to use a semi-colon as parts of a password (PWD) when specifying the password in connection strings.
  • The database connection in thread-based programming must be used independently each other.
  • In autocommit mode, the transaction is not committed if all results are not fetched after running the SELECT statement. Therefore, although in autocommit mode, you should end the transaction by executing COMMIT or ROLLBACK if some error occurs during fetching for the resultset.
ASP Sample Program

In the virtual directory where the ASP sample program runs, right-click "Default Web Site" and click [Properties].

_images/image82.png

In the picture above, if you select (All Unassigned) from the [IP Address] dropdown list under [Web Site Identification], it is recognized as localhost. If you want to see the sample program through a specific IP address, make an IP address recognize a directory as a virtual directory and register the IP address in the registration information.

Create the below code as cubrid.asp and store it in a virtual directory.

<HTML>
    <HEAD>
     <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
       <title>CUBRID Query Test Page</title>
  </HEAD>

 <BODY topmargin="0" leftmargin="0">

 <table border="0" width="748" cellspacing="0" cellpadding="0">
   <tr>
     <td width="200"></td>
     <td width="287">
       <p align="center"><font size="3" face="Times New Roman"><b><font color="#FF0000">CUBRID</font>Query Test</b></font></td>
     <td width="200"></td>
   </tr>
 </table>

 <form action="cubrid.asp" method="post" >
 <table border="1" width="700" cellspacing="0" cellpadding="0" height="45">
   <tr>
     <td width="113" valign="bottom" height="16" bgcolor="#DBD7BD" bordercolorlight="#FFFFCC"><font size="2">SERVER IP</font></td>
     <td width="78"  valign="bottom" height="16" bgcolor="#DBD7BD" bordercolorlight="#FFFFCC"><font size="2">Broker PORT</font></td>
     <td width="148" valign="bottom" height="16" bgcolor="#DBD7BD" bordercolorlight="#FFFFCC"><font size="2">DB NAME</font></td>
     <td width="113" valign="bottom" height="16" bgcolor="#DBD7BD" bordercolorlight="#FFFFCC"><font size="2">DB USER</font></td>
     <td width="113" valign="bottom" height="16" bgcolor="#DBD7BD" bordercolorlight="#FFFFCC"><font size="2">DB PASS</font></td>
     <td width="80" height="37" rowspan="4" bordercolorlight="#FFFFCC" bgcolor="#F5F5ED">
       <p><input type="submit" value="Run" name="B1" tabindex="7"></p></td>
   </tr>
   <tr>
     <td width="113" height="1" bordercolorlight="#FFFFCC" bgcolor="#F5F5ED"><font size="2"><input type="text" name="server_ip" size="20" tabindex="1" maxlength="15" value="<%=Request("server_ip")%>"></font></td>
     <td width="78"  height="1" bordercolorlight="#FFFFCC" bgcolor="#F5F5ED"><font size="2"><input type="text" name="cas_port" size="15" tabindex="2" maxlength="6" value="<%=Request("cas_port")%>"></font></td>
     <td width="148" height="1" bordercolorlight="#FFFFCC" bgcolor="#F5F5ED"><font size="2"><input type="text" name="db_name" size="20" tabindex="3" maxlength="20" value="<%=Request("db_name")%>"></font></td>
     <td width="113" height="1" bordercolorlight="#FFFFCC" bgcolor="#F5F5ED"><font size="2"><input type="text" name="db_user" size="15" tabindex="4" value="<%=Request("db_user")%>"></font></td>
     <td width="113" height="1" bordercolorlight="#FFFFCC" bgcolor="#F5F5ED"><font size="2"><input type="password" name="db_pass" size="15" tabindex="5" value="<%=Request("db_pass")%>"></font></td>
   </tr>
   <tr>
     <td width="573" colspan="5" valign="bottom" height="18" bordercolorlight="#FFFFCC" bgcolor="#DBD7BD"><font size="2">QUERY</font></td>
   </tr>
   <tr>
     <td width="573" colspan="5" height="25" bordercolorlight="#FFFFCC" bgcolor="#F5F5ED"><textarea rows="3" name="query" cols="92" tabindex="6"><%=Request("query")%></textarea></td>
   </tr>
 </table>
 </form>
 <hr>

</BODY>
</HTML>

<%
    ' get DSN and SQL statement.
    strIP = Request( "server_ip" )
    strPort = Request( "cas_port" )
    strUser = Request( "db_user" )
    strPass = Request( "db_pass" )
    strName = Request( "db_name" )
    strQuery = Request( "query" )

if strIP = "" then
   Response.Write "Input SERVER_IP."
        Response.End ' exit if no SERVER_IP's input.
    end if
    if strPort = "" then
       Response.Write "Input port number."
        Response.End ' exit if no Port's input.
    end if
    if strUser = "" then
       Response.Write "Input DB_USER."
        Response.End ' exit if no DB_User's input.
    end if
    if strName = "" then
       Response.Write "Input DB_NAME"
        Response.End ' exit if no DB_NAME's input.
    end if
    if strQuery = "" then
       Response.Write "Input the query you want"
        Response.End ' exit if no query's input.
    end if
 ' create connection object.
  strDsn = "driver={CUBRID Driver};server=" & strIP & ";port=" & strPort & ";uid=" & strUser & ";pwd=" & strPass & ";db_name=" & strName & ";"
' DB connection.
Set DBConn = Server.CreateObject("ADODB.Connection")
       DBConn.Open strDsn
    ' run SQL.
    Set rs = DBConn.Execute( strQuery )
    ' show the message by SQL.
    if InStr(Ucase(strQuery),"INSERT")>0 then
        Response.Write "A record is added."
        Response.End
    end if

    if InStr(Ucase(strQuery),"DELETE")>0  then
        Response.Write "A record is deleted."
        Response.End
    end if

    if InStr(Ucase(strQuery),"UPDATE")>0  then
        Response.Write "A record is updated."
        Response.End
    end if
%>
<table>
<%
    ' show the field name.
    Response.Write "<tr bgColor=#f3f3f3>"
    For index =0 to ( rs.fields.count-1 )
        Response.Write "<td><b>" & rs.fields(index).name & "</b></td>"
    Next
    Response.Write "</tr>"
    ' show the field value
    Do While Not rs.EOF
        Response.Write "<tr bgColor=#f3f3f3>"
        For index =0 to ( rs.fields.count-1 )
            Response.Write "<td>" & rs(index) & "</td>"
        Next
        Response.Write "</tr>"

        rs.MoveNext
    Loop
%>
<%
    set  rs = nothing
%>
</table>

You can check the result of the sample program by connecting to http://localhost/cubrid.asp. When you execute the ASP sample code above, you will get the following output. Enter an appropriate value in each field, enter the query statement in the Query field, and click [Run]. The query result will be displayed at the lower part of the page.

_images/image83.png
ODBC API

For ODBC API, see ODBC API Reference ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms714562%28v=vs.85%29.aspx ) on the MSDN page. See the table below to get information about the list of functions, ODBC Spec version, and compatibility that CUBRID supports.

API Version Introduced Standards Compliance Support
SQLAllocHandle 3.0 ISO 92 YES
SQLBindCol 1.0 ISO 92 YES
SQLBindParameter 2.0 ODBC YES
SQLBrowseConnect 1.0 ODBC NO
SQLBulkOperations 3.0 ODBC YES
SQLCancel 1.0 ISO 92 YES
SQLCloseCursor 3.0 ISO 92 YES
SQLColAttribute 3.0 ISO 92 YES
SQLColumnPrivileges 1.0 ODBC NO
SQLColumns 1.0 X/Open YES
SQLConnect 1.0 ISO 92 YES
SQLCopyDesc 3.0 ISO 92 YES
SQLDescribeCol 1.0 ISO 92 YES
SQLDescribeParam 1.0 ODBC NO
SQLDisconnect 1.0 ISO 92 YES
SQLDriverConnect 1.0 ODBC YES
SQLEndTran 3.0 ISO 92 YES
SQLExecDirect 1.0 ISO 92 YES
SQLExecute 1.0 ISO 92 YES
SQLFetch 1.0 ISO 92 YES
SQLFetchScroll 3.0 ISO 92 YES
SQLForeignKeys 1.0 ODBC YES (2008 R3.1 or later)
SQLFreeHandle 3.0 ISO 92 YES
SQLFreeStmt 1.0 ISO 92 YES
SQLGetConnectAttr 3.0 ISO 92 YES
SQLGetCursorName 1.0 ISO 92 YES
SQLGetData 1.0 ISO 92 YES
SQLGetDescField 3.0 ISO 92 YES
SQLGetDescRec 3.0 ISO 92 YES
SQLGetDiagField 3.0 ISO 92 YES
SQLGetDiagRec 3.0 ISO 92 YES
SQLGetEnvAttr 3.0 ISO 92 YES
SQLGetFunctions 1.0 ISO 92 YES
SQLGetInfo 1.0 ISO 92 YES
SQLGetStmtAttr 3.0 ISO 92 YES
SQLGetTypeInfo 1.0 ISO 92 YES
SQLMoreResults 1.0 ODBC YES
SQLNativeSql 1.0 ODBC YES
SQLNumParams 1.0 ISO 92 YES
SQLNumResultCols 1.0 ISO 92 YES
SQLParamData 1.0 ISO 92 YES
SQLPrepare 1.0 ISO 92 YES
SQLPrimaryKeys 1.0 ODBC YES (2008 R3.1 or later)
SQLProcedureColumns 1.0 ODBC YES (2008 R3.1 or later)
SQLProcedures 1.0 ODBC YES (2008 R3.1 or later)
SQLPutData 1.0 ISO 92 YES
SQLRowCount 1.0 ISO 92 YES
SQLSetConnectAttr 3.0 ISO 92 YES
SQLSetCursorName 1.0 ISO 92 YES
SQLSetDescField 3.0 ISO 92 YES
SQLSetDescRec 3.0 ISO 92 YES
SQLSetEnvAttr 3.0 ISO 92 NO
SQLSetPos 1.0 ODBC YES
SQLSetStmtAttr 3.0 ISO 92 YES
SQLSpecialColumns 1.0 X/Open YES
SQLStatistics 1.0 ISO 92 YES
SQLTablePrivileges 1.0 ODBC YES (2008 R3.1 or later)
SQLTables 1.0 X/Open YES

Backward compatibility is not supported for some CUBRID functions. Refer to information in the mapping table below to change unsupported functions into appropriate ones.

ODBC 2.x Functions ODBC 3.x Functions
SQLAllocConnect SQLAllocHandle
SQLAllocEnv SQLAllocHandle
SQLAllocStmt SQLAllocHandle
SQLBindParam SQLBindParameter
SQLColAttributes SQLColAttribute
SQLError SQLGetDiagRec
SQLFreeConnect SQLFreeHandle
SQLFreeEnv SQLFreeHandle
SQLFreeStmt with SQL_DROP SQLFreeHandle
SQLGetConnectOption SQLGetConnectAttr
SQLGetStmtOption SQLGetStmtAttr
SQLParamOptions SQLSetStmtAttr
SQLSetConnectOption SQLSetConnectAttr
SQLSetParam SQLBindParameter
SQLSetScrollOption SQLSetStmtAttr
SQLSetStmtOption SQLSetStmtAttr
SQLTransact SQLEndTran

OLE DB Driver

OLE DB (Object Linking and Embedding, Database) is an API designed by Microsoft for accessing data from a variety of sources in a uniform manner so it can be used by all Microsoft platforms. It is a set of interfaces implemented using the Component Object Model (COM).

.NET Framework is a software framework for Microsoft Windows operating systems. It includes a large library and it supports several programming languages which allows language interoperability (each language can utilize code written in other languages). The .NET library is available to all programming languages that .NET supports. A data provider in the .NET Framework serves as a bridge between an application and a data source; a data provider is used to retrieve data from a data source and to reconcile changes to that data back to the data source.

CUBRID OLE DB driver is written based on CCI API so affected by CCI configurations such as CCI_DEFAULT_AUTOCOMMIT.

To download OLD DB driver or get the latest information, click http://www.cubrid.org/wiki_apis/entry/cubrid-oledb-driver .

Note

  • If your CUBRID OLEDB driver version is 9.1.0.p1 or later, only one installation package is needed for both Windows 32 bit and 64 bit. Our new OLEDB installer supports CUBRID DB engine 8.4.1 or later.
  • If your CUBRID OLEDB Driver version is 9.1.0 or older, it may have a problem on 64 bit operating system. Please see our installation tutorial for an old version: http://www.cubrid.org/wiki_apis/entry/cubrid-oledb-driver-installation-instructions-old
Installing and Configuring OLE DB

CUBRID OLE DB Provider

Before you start developing applications with CUBRID, you will need the Provider driver (CUBRIDProvider.dll). You have two options to get the driver.

  • Installing the driver: Download the CUBRID OLE DB driver's .exe file at the location http://ftp.cubrid.org/CUBRID_Drivers/OLEDB_Driver/ or http://www.cubrid.org/?mid=downloads&item=oledb_driver. From OLE DB driver 9.1.0.p1 version(available from CUBRID server 2008 R4.1), both of 32 bit and 64 bit driver are installed on one installation.

    _images/oledb_install.jpg
    • There are below files in the installed directory.
      • CUBRIDProvider32.dll
      • CUBRIDProvider64.dll
      • README.txt
      • uninstall.exe
  • Building from source code: If you want to change CUBRID OLED DB Data Provider Installer, you can build it for yourself by compiling the source code. For details, see below:

    http://www.cubrid.org/wiki_apis/entry/compiling-the-cubrid-ole-db-installer

    If you do not use the CUBRID OLED DB Provider installer, you should execute the command below to register the driver. The version of the driver should match the version of your operating system. For 32 bit, the regsvr32 command should be executed in the C:Windowssystem32 directory; for 64 bit, the regsvr32 command should be executed in the C:WindowsSysWOW64 directory.

    regsvr32 CUBRIDProvider.dll
    
OLE DB Programming
Configuring Connection String

When you do programming with the CUBRID OLE DB Provider, you should write connection string as follows:

Item Example Description
Provider CUBRIDProvider Provider name
Data Source demodb Database name
Location 127.0.0.1 The IP address or host name of the CUBRID broker server
User ID PUBLIC User ID
Password xxx Password
Port 33000 The broker port number
Fetch Size 100 Fetch size
Charset utf-8 Character set
Autocommit Isolation Levels 4096 isolation level

A connection string using the example above is as follows:

"Provider=CUBRIDProvider;Data Source=demodb;Location=127.0.0.1;User ID=PUBLIC;Password=xxx;Port= 33000;Fetch Size=100;Charset=utf-8;Autocommit Isolation Levels=256;"

Note

  • Because a semi-colon (;) is used as a separator in URL string, it is not allowed to use a semi-colon as parts of a password (PWD) when specifying the password in connection string.
  • If a string longer than defined max length is inserted (INSERT) or updated (UPDATE), the string will be truncated.
  • The database connection in thread-based programming must be used independently each other.
  • In autocommit mode, the transaction is not committed if all results are not fetched after running the SELECT statement. Therefore, although in autocommit mode, you should end the transaction by executing COMMIT or ROLLBACK if some error occurs during fetching for the resultset.
Multi-Threaded Programming in .NET Environment

Additional considerations when you do programming with the CUBRID OLE DB Provider in the Microsoft .NET environment are as follows:

If you do multi-threaded programming using ADO.NET in the management environment, you need to change the value of the ApartmentState attribute of the Thread object to a ApartmentState.STA value because the CUBRID OLE DB Provider supports the Single Threaded Apartment (STA) attribute only.

Without any changes of given values, the default value of the attribute in the Thread object returns Unknown value, causing it to malfunction during multi-threaded programming.

Warning

All OLE DB objects are the Component Object Model. Of COM threading model, the CUBRID OLE DB Provider currently supports the apartment threading model only, which is available in every multi-threaded environment as well as .NET environment.

OLE DB API

For more information about OLE DB API, see Micorosoft OLE DB documentation at http://msdn.microsoft.com/en-us/library/ms722784%28vs.85%29.aspx .

For more information about CUBRID OLE DB, see http://ftp.cubrid.org/CUBRID_Docs/Drivers/OLEDB/.

ADO.NET Driver

ADO.NET is a set of classes that expose data access services to the .NET programmer. ADO.NET provides a rich set of components for creating distributed, data-sharing applications. It is an integral part of the .NET Framework, providing access to relational, XML, and application data. ADO.NET supports a variety of development needs, including the creation of front-end database clients and middle-tier business objects used by applications, tools, languages, or Internet browsers.

To download ADO.NET driver or get the latest information, click http://www.cubrid.org/wiki_apis/entry/cubrid-ado-net-driver.

Installing and Configuring ADO.NET

Requirements

Installing and Configuring CUBRID ADO.NET Driver

Before you start developing .NET applications with CUBRID, you will need the CUBRID ADO.NET Data Provider library (Cubrid.Data.dll). You have the options to:

The CUBRID .NET Data Provider is 100% full-managed .NET code and it does not rely on any CUBRID library files. This means that the usage of the driver does not require any kind of CUBRID installation or files on the local machine.

The easiest way to install CUBRID ADO.NET Data Provider is to use the official installer. If you choose to install using the default option (x86), the driver will be installed in the Program Files\CUBRID\CUBRID ADO.NET Data Provider 8.4.1 directory.

You can also choose to install the driver in GAC ( http://en.wikipedia.org/wiki/Global_Assembly_Cache ). The best way to install the driver is to use the tlbimp ( http://msdn.microsoft.com/en-us/library/tt0cf3sx%28v=vs.80%29.aspx ) tool. See the below to import the required namespaces.

_images/image88.png
ADO.NET Programming
A Simple Query/Retrieve Code

Let's take a look at a simple code which retrieves value from a CUBRID database table. Assume that the connection is already established.

String sql = "select * from nation order by `code` asc";

using (CUBRIDCommand cmd = new CUBRIDCommand(sql, conn))
{
    using (DbDataReader reader = cmd.ExecuteReader())
    {
        reader.Read();
        //(read the values using: reader.Get...() methods)
    }
}

Once you have created the DbDataReader object, all you have to do is to use the Get...() method to retrieve any column data. CUBRID ADO.NET driver implements all methods required to read any CUBRID data types.

reader.GetString(3)
reader.GetDecimal(1)

The Get...() method will use as an input parameter the 0-based index position of the retrieved column.

To retrieve specific CUBRID data types, you need to use CUBRIDDataReader, instead of the DbDataReader interface.

using (CUBRIDCommand cmd = new CUBRIDCommand("select * from t", conn))
{
    CUBRIDDataReader reader = (CUBRIDDataReader)cmd.ExecuteReader();

    reader.Read();
    Debug.Assert(reader.GetDateTime(0) == newDateTime(2008, 10, 31, 10, 20, 30, 040));
    Debug.Assert(reader.GetDate(0) == "2008-10-31");
    Debug.Assert(reader.GetDate(0, "yy/MM/dd") == "08-10-31");
    Debug.Assert(reader.GetTime(0) == "10:20:30");
    Debug.Assert(reader.GetTime(0, "HH") == "10");
    Debug.Assert(reader.GetTimestamp(0) == "2008-10-31 10:20:30.040");
    Debug.Assert(reader.GetTimestamp(0, "yyyy HH") == "2008 10");
}
batch Commands

When using CUBRID ADO.NET Data Provider library, you can execute more than one query against the data service in a single batch. For more information, see http://msdn.microsoft.com/en-us/library/dd744839%28v=vs.90%29.aspx .

For example, in CUBRID, you can write the code like:

string[] sql_arr = newstring3;
sql_arr0 = "insert into t values(1)";
sql_arr1 = "insert into t values(2)";
sql_arr2 = "insert into t values(3)";
conn.BatchExecute(sql_arr);

or you can write as follows:

string[] sqls = newstring3;
sqls0 = "create table t(id int)";
sqls1 = "insert into t values(1)";
sqls2 = "insert into t values(2)";

conn.BatchExecuteNoQuery(sqls);
Connection String

In order to establish a connection from .NET application to CUBRID, you must build the database connection string as the following format:

ConnectionString = "server=<server address>;database=<database name>;port=<port number to use for connection to broker>;user=<user name>;password=<user password>;"

All parameters are mandatory except for port. If you do not specify the broker port number, the default value is 30,000.

The examples of connection string with different options are as follows:

  • Connect to a local server, using the default demodb database.

    ConnectionString = "server=127.0.0.1;database=demodb;port=30000;user=public;password="
    
  • Connect to a remote server, using the default demodb database, as user dba.

    ConnectionString = "server=10.50.88.1;database=demodb;user=dba;password="
    
  • Connect to a remote server, using the default demodb database, as user dba, using password secret.

    ConnectionString = "server=10.50.99.1;database=demodb;port=30000;user=dba;password=secret"
    

As an alternative, you can use the CUBRIDConnectionStringBuilder class to build easily a connection string in the correct format.

CUBRIDConnectionStringBuilder sb = new CUBRIDConnectionStringBuilder(localhost,"33000","demodb","public","");
using (CUBRIDConnection conn = new CUBRIDConnection(sb.GetConnectionString()))
{
    conn.Open();
}

or you can write as follows:

sb = new CUBRIDConnectionStringBuilder();
sb.User = "public" ;
sb.Database = "demodb";
sb.Port = "33000";
sb.Server = "localhost";
using (CUBRIDConnection conn = new CUBRIDConnection(sb.GetConnectionString()))
{
    conn.Open();
}

Note

The database connection in thread-based programming must be used independently each other.

CUBRID Collections

Collections are specific CUBRID data type. If you are not familiar with them, you can read information in Collection Types. Because collections are not common to any database, the support for them is implemented in some specific CUBRID collection method.

public void AddElementToSet(CUBRIDOid oid, String attributeName, Object value)
public void DropElementInSet(CUBRIDOid oid, String attributeName, Object value)
public void UpdateElementInSequence(CUBRIDOid oid, String attributeName, int index, Object value)
public void InsertElementInSequence(CUBRIDOid oid, String attributeName, int index, Object value)
public void DropElementInSequence(CUBRIDOid oid, String attributeName, int index)
public int GetCollectionSize(CUBRIDOid oid, String attributeName)

Here below are two examples of using these CUBRID extensions.

Reading values from a Collection data type:

using (CUBRIDCommand cmd = new CUBRIDCommand("SELECT * FROM t", conn))
{
    using (DbDataReader reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            object[] o = (object[])reader0;
            for (int i = 0; i <SeqSize; i++)
            {
                //...
            }
        }
    }
}

Updating a Collection data type:

conn.InsertElementInSequence(oid, attributeName, 5, value);
SeqSize = conn.GetCollectionSize(oid, attributeName);
using (CUBRIDCommand cmd = new CUBRIDCommand("SELECT * FROM t", conn))
{
    using (DbDataReader reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            int[] expected = { 7, 1, 2, 3, 7, 4, 5, 6 };
            object[] o = (object[])reader0;
        }
    }
}
conn.DropElementInSequence(oid, attributeName, 5);
SeqSize = conn.GetCollectionSize(oid, attributeName);
CUBRID BLOB/CLOB

Starting from CUBRID 2008 R4.0 (8.4.0), CUBRID deprecated the GLO data type and added support for LOB (BLOB, CLOB) data types. These data types are specific CUBRID data types so you need to use methods offered by CUBRID ADO.NET Data Provider.

Here are some basic source code examples.

Reading BLOB data:

CUBRIDCommand cmd = new CUBRIDCommand(sql, conn);
DbDataReader reader = cmd.ExecuteReader();

while (reader.Read())
{
    CUBRIDBlob bImage = (CUBRIDBlob)reader0;
    byte[] bytes = newbyte(int)bImage.BlobLength;
    bytes = bImage.getBytes(1, (int)bImage.BlobLength);
    //...
}

Updating CLOB data:

string sql = "UPDATE t SET c = ?";
CUBRIDCommand cmd = new CUBRIDCommand(sql, conn);

CUBRIDClobClob = new CUBRIDClob(conn);
str = conn.ConnectionString; //Use the ConnectionString for testing

Clob.setString(1, str);

CUBRIDParameter param = new CUBRIDParameter();

param.ParameterName = "?";
param.CUBRIDDataType = CUBRIDDataType.CCI_U_TYPE_CLOB;
param.Value = Clob;

cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
CUBRID Metadata Support

CUBRID ADO.NET Data Provider supports for database metadata. Most of these methods are implemented in the CUBRIDSchemaProvider class.

public DataTable GetDatabases(string[] filters)
public DataTable GetTables(string[] filters)
public DataTable GetViews(string[] filters)
public DataTable GetColumns(string[] filters)
public DataTable GetIndexes(string[] filters)
public DataTable GetIndexColumns(string[] filters)
public DataTable GetExportedKeys(string[] filters)
public DataTable GetCrossReferenceKeys(string[] filters)
public DataTable GetForeignKeys(string[] filters)
public DataTable GetUsers(string[] filters)
public DataTable GetProcedures(string[] filters)
public static DataTable GetDataTypes()
public static DataTable GetReservedWords()
public static String[] GetNumericFunctions()
public static String[] GetStringFunctions()
public DataTable GetSchema(string collection, string[] filters)

The example below shows how to get the list of tables in the current CUBRID database.

CUBRIDSchemaProvider schema = new CUBRIDSchemaProvider(conn);
DataTable dt = schema.GetTables(newstring[] { "%" });

Debug.Assert(dt.Columns.Count == 3);
Debug.Assert(dt.Rows.Count == 10);

Debug.Assert(dt.Rows00.ToString() == "demodb");
Debug.Assert(dt.Rows01.ToString() == "demodb");
Debug.Assert(dt.Rows02.ToString() == "stadium");

Get the list of Foreign Keys in a table:

CUBRIDSchemaProvider schema = new CUBRIDSchemaProvider(conn);
DataTable dt = schema.GetForeignKeys(newstring[] { "game" });

Debug.Assert(dt.Columns.Count == 9);
Debug.Assert(dt.Rows.Count == 2);

Debug.Assert(dt.Rows00.ToString() == "athlete");
Debug.Assert(dt.Rows01.ToString() == "code");
Debug.Assert(dt.Rows02.ToString() == "game");
Debug.Assert(dt.Rows03.ToString() == "athlete_code");
Debug.Assert(dt.Rows04.ToString() == "1");
Debug.Assert(dt.Rows05.ToString() == "1");
Debug.Assert(dt.Rows06.ToString() == "1");
Debug.Assert(dt.Rows07.ToString() == "fk_game_athlete_code");
Debug.Assert(dt.Rows08.ToString() == "pk_athlete_code");

The example below shows how to get the list of indexes in a table.

CUBRIDSchemaProvider schema = new CUBRIDSchemaProvider(conn);
DataTable dt = schema.GetIndexes(newstring[] { "game" });

Debug.Assert(dt.Columns.Count == 9);
Debug.Assert(dt.Rows.Count == 5);

Debug.Assert(dt.Rows32.ToString() == "pk_game_host_year_event_code_athlete_code"); //Index name
Debug.Assert(dt.Rows34.ToString() == "True"); //Is it a PK?
DataTable Support

The DataTable is a central object in the ADO.NET library and CUBRID ADO.NET Data Provider support the following features.

  • DataTable populate
  • Built-in commands: INSERT, UPDATE, and DELETE
  • Column metadata/attributes
  • DataSet, DataView inter-connection

The following example shows how to get columns attributes.

String sql = "select * from nation";
CUBRIDDataAdapter da = new CUBRIDDataAdapter();
da.SelectCommand = new CUBRIDCommand(sql, conn);
DataTable dt = newDataTable("nation");
da.FillSchema(dt, SchemaType.Source);//To retrieve all the column properties you have to use the FillSchema() method

Debug.Assert(dt.Columns0.ColumnName == "code");
Debug.Assert(dt.Columns0.AllowDBNull == false);
Debug.Assert(dt.Columns0.DefaultValue.ToString() == "");
Debug.Assert(dt.Columns0.Unique == true);
Debug.Assert(dt.Columns0.DataType == typeof(System.String));
Debug.Assert(dt.Columns0.Ordinal == 0);
Debug.Assert(dt.Columns0.Table == dt);

The following example shows how to insert values into a table by using the INSERT statement.

String sql = " select * from nation order by `code` asc";
using (CUBRIDDataAdapter da = new CUBRIDDataAdapter(sql, conn))
{
    using (CUBRIDDataAdapter daCmd = new CUBRIDDataAdapter(sql, conn))
    {
        CUBRIDCommandBuildercmdBuilder = new CUBRIDCommandBuilder(daCmd);
        da.InsertCommand = cmdBuilder.GetInsertCommand();
    }

    DataTable dt = newDataTable("nation");
    da.Fill(dt);

    DataRow newRow = dt.NewRow();

    newRow"code" = "ZZZ";
    newRow"name" = "ABCDEF";
    newRow"capital" = "MyXYZ";
    newRow"continent" = "QWERTY";

    dt.Rows.Add(newRow);
    da.Update(dt);
}
Transactions

CUBRID ADO.NET Data Provider implements support for transactions in a similar way with direct-SQL transactions support. Here is a code example showing how to use transactions.

conn.BeginTransaction();

string sql = "create table t(idx integer)";
using (CUBRIDCommand command = new CUBRIDCommand(sql, conn))
{
    command.ExecuteNonQuery();
}

conn.Rollback();

conn.BeginTransaction();

sql = "create table t(idx integer)";
using (CUBRIDCommand command = new CUBRIDCommand(sql, conn))
{
    command.ExecuteNonQuery();
}

conn.Commit();
Working with Parameters

In CUBRID, there is no support for named parameters, but only for position-based parameters. Therefore, CUBRID ADO.NET Data Provider provides support for using position-based parameters. You can use any name you want as long as parameters are prefixed with the character a question mark (?). Remember that you must declare and initialize them in the correct order.

The example below shows how to execute SQL statements by using the parameters. The most important thing is the order in which the Add () methods are called.

using (CUBRIDCommand cmd = new CUBRIDCommand("insert into t values(?, ?)", conn))
{
    CUBRIDParameter p1 = new CUBRIDParameter("?p1", CUBRIDDataType.CCI_U_TYPE_INT);
    p1.Value = 1;
    cmd.Parameters.Add(p1);

    CUBRIDParameter p2 = new CUBRIDParameter("?p2", CUBRIDDataType.CCI_U_TYPE_STRING);
    p2.Value = "abc";
    cmd.Parameters.Add(p2);

    cmd.ExecuteNonQuery();
}
Error Codes and Messages

The following list displays the error code and messages shown up when using CUBRID ADO.NET Data Provider.

Code Number Error Code Error Message
0 ER_NO_ERROR "No Error"
1 ER_NOT_OBJECT "Index's Column is Not Object"
2 ER_DBMS "Server error"
3 ER_COMMUNICATION "Cannot communicate with the broker"
4 ER_NO_MORE_DATA "Invalid dataReader position"
5 ER_TYPE_CONVERSION "DataType conversion error"
6 ER_BIND_INDEX "Missing or invalid position of the bind variable provided"
7 ER_NOT_BIND "Attempt to execute the query when not all the parameters are binded"
8 ER_WAS_NULL "Internal Error: NULL value"
9 ER_COLUMN_INDEX "Column index is out of range"
10 ER_TRUNCATE "Data is truncated because receive buffer is too small"
11 ER_SCHEMA_TYPE "Internal error: Illegal schema paramCUBRIDDataType"
12 ER_FILE "File access failed"
13 ER_CONNECTION "Cannot connect to a broker"
14 ER_ISO_TYPE "Unknown transaction isolation level"
15 ER_ILLEGAL_REQUEST "Internal error: The requested information is not available"
16 ER_INVALID_ARGUMENT "The argument is invalid"
17 ER_IS_CLOSED "Connection or Statement might be closed"
18 ER_ILLEGAL_FLAG "Internal error: Invalid argument"
19 ER_ILLEGAL_DATA_SIZE "Cannot communicate with the broker or received invalid packet"
20 ER_NO_MORE_RESULT "No More Result"
21 ER_OID_IS_NOT_INCLUDED "This ResultSet do not include the OID"
22 ER_CMD_IS_NOT_INSERT "Command is not insert"
23 ER_UNKNOWN "Error"
NHibernate

CUBRID will be accessed from NHibernate using CUBRID ADO.NET Data Provider. For more information, see http://www.cubrid.org/wiki_apis/entry/cubrid-nhibernate-support.

Java Stored Procedure

For how to call Java stored procedure in .NET, see http://www.cubrid.org/wiki_apis/entry/how-to-calling-java-stored-functionprocedurec.

Perl Driver

DBD::cubrid is a CUBRID Perl driver that implements Perl5 Database Interface (DBI) to enable access to CUBRID database server. It provides full API support.

CUBRID Perl driver is written based on CCI API so affected by CCI configurations such as CCI_DEFAULT_AUTOCOMMIT.

To download Perl driver or get the latest information, click http://www.cubrid.org/wiki_apis/entry/cubrid-perl-driver .

Note

  • The database connection in thread-based programming must be used independently each other.
  • In autocommit mode, the transaction is not committed if all results are not fetched after running the SELECT statement. Therefore, although in autocommit mode, you should end the transaction by executing COMMIT or ROLLBACK if some error occurs during fetching for the resultset.
Installing and Configuring Perl

Requirements

  • Perl: It is recommended to use an appropriate version of Perl based on your system environment. For example, all Linux and FreeBSD distributions come with Perl. For Windows, ActivePerl is recommended. For details, see http://www.activestate.com/activeperl .
  • CUBRID: To build CUBRID Perl driver, you need to get the CCI driver. You can get it from installing CUBRID. You can download the CUBRID Perl driver's source code from http://www.cubrid.org/downloads .
  • DBI: http://code.activestate.com/ppm/DBI/ .
  • C compiler: In most cases, there are binary distributions of DBD::cubrid ( http://www.cubrid.org/?mid=downloads&item=perl_driver ) available. However, if you want to build the driver from source code, a C compiler is required. Make sure to use the same C compiler that was used for compiling Perl and CUBRID. Otherwise, you will encounter problems because of differences in the underlying C runtime libraries.

Comprehensive Perl Archive Network (CPAN) Installation

You can automatically install the driver from source code by using the CPAN module.

cpan
install DBD::cubrid

If you are using the CPAN module for the first time, it is recommended to accept default settings.

If you are using an older version, you might enter the command line below, instead of command line above.

perl -MCPAN -e shell
install DBD::cubrid

Manual Installation

If you cannot get the CPAN module, you should download the DBD::cubrid source code. The latest version is always available below:

http://www.cubrid.org/?mid=downloads&item=perl_driver

The file name is typically something like this: DBD-cubrid-X.X.X.tar.gz. After extracting the archive, enter the command line below under the DBD-cubrid-X.X.X directory. (On Windows, you may need to replace make with nmake or dmake.)

Perl Makefile.PL
make
make test

If test seems to look fine, execute the command to build a driver.

make install
Perl API

Currently, CUBRID Perl driver provides only basic features and does not support LOB type and column information verification.

If you want to get details about CUBRID Perl driver API, see http://ftp.cubrid.org/CUBRID_Docs/Drivers/Perl/.

Python Driver

CUBRIDdb is a Python extension package that implements Python Database API 2.0 compliant support for CUBRID. In additional to the minimal feature set of the standard Python DB API, CUBRID Python API also exposes nearly the entire native client API of the database engine in _cubrid.

CUBRID Python driver is written based on CCI API so affected by CCI configurations such as CCI_DEFAULT_AUTOCOMMIT.

If you want to download Python driver or get the latest information, click http://www.cubrid.org/wiki_apis/entry/cubrid-python-driver .

Installing and Configuring Python
Linux/UNIX

There are three ways to install CUBRID Python driver on Linux, UNIX, and UNIX-like operating systems. You can find instructions for each of them below.

Requirements

Installing CUBRID Python Driver using Yum (Fedora or CentOS)

  1. To install CUBRID Python driver by using the yum command, you need to tell Yum where to look for CUBRID package. First, visit one of the following links depending on your operating system.

    For the example to install CUBRID 9.0 on Fedora 17 is as follows: (fc17 means this operating system version).

    rpm -i http://yumrepository.cubrid.org/cubrid_repo_settings/9.0.0/cubridrepo-9.0.0-1.fc17.noarch.rpm
    
  2. Enter the command below to install CUBRID Python driver.

    yum install python-cubrid
    

Building CUBRID Python Driver from Source Code (Linux)

To install CUBRID Python driver by compiling source code, you should have Python Development Package installed on your system. If you do not have the package, follow the instructions stated at http://www.cubrid.org/wiki_apis/entry/install-python-development-package .

  1. Download the source code from http://www.cubrid.org/?mid=downloads&item=python_driver.

  2. Extract the archive to the desired location.

    tar xvfz cubrid-python-src-8.4.0.0001.tar.gz
    
  3. Navigate to the directory where you have extracted the source code.

    cd cubrid-python-src
    
  4. Build the driver. At this and next step, make sure you are still under the root user.

    python setup.py build
    
  5. Install the driver. Here you also need root privileges.

    python setup.py install
    

Using a Package Manager (EasyInstall) of CUBRID Python Driver (Linux)

EasyInstall is a Python module (easy_install) bundled with setuptools that lets you automatically download, build, install, and manage Python packages. It gives you a quick way to install packages remotely by connecting to other websites via HTTP as well as connecting to the Package Index. It is somewhat analogous to the CPAN and PEAR tools for Perl and PHP, respectively. For more information about EasyInstall, see http://packages.python.org/distribute/easy_install.html.

Enter the command below to install CUBRID Python driver by using EasyInstall.

easy_install CUBRID-Python
Windows

To install CUBRID Python driver on Windows, first download CUBRID Python driver as follows:

  • Visit the website below to download the driver. You will be given to select your operating system and Python version installed on your system.

    http://www.cubrid.org/?mid=downloads&item=python_driver&os=windows&python=detect

  • Extract the archive you downloaded. You should see a folder and two files in the folder. Copy these files to the Lib folder where your Python has been installed; by default, it is C:\Program Files\Python\Lib.

Python Programming

The CUBRIDdb package is supposed to have the following constants according to Python Database API 2.0.

Name Value
threadsafety 2
apilevel 2.0
paramstyle qmark
Python Sample Program

This sample program will show steps that you need to perform in order to connect to the CUBRID database and run SQL statements from Python programming language. Enter the command line below to create a new table in your database.

csql -u dba -c "CREATE TABLE posts( id integer, title varchar(255), body string, last_updated timestamp );" demodb

Connecting to demodb from Python

  1. Open a new Python console and enter the command line below to import CUBRID Python driver.

    import CUBRIDdb
    
  2. Establish a connection to the demodb database located on localhost.

    conn = CUBRIDdb.connect('CUBRID:localhost:30000:dba::')
    

For the demodb database, it is not required to enter any password. In a real-world scenario, you will have to provide the password to successfully connect. The syntax to use the connect () function is as follows:

connect (url[,user[password]])

If the database has not started and you try to connect to it, you will receive an error such as this:

Traceback (most recent call last):
  File "tutorial.py", line 3, in <module>
    conn = CUBRIDdb.connect('CUBRID:localhost:30000:dba::')
  File "/usr/local/lib/python2.6/site-packages/CUBRIDdb/__init__.py", line 48, in Connect
    return Connection(*args, **kwargs)
  File "/usr/local/lib/python2.6/site-packages/CUBRIDdb/connections.py", line 19, in __init__
    self._db = _cubrid.connect(*args, **kwargs)
_cubrid.Error: (-1, 'ERROR: DBMS, 0, Unknown DBMS Error')

If you provide wrong credentials, you will receive an error such as this:

Traceback (most recent call last):
  File "tutorial.py", line 3, in <module>
    con = CUBRIDdb.connect('CUBRID:localhost:33000:demodb','a','b')
  File "/usr/local/lib/python2.6/site-packages/CUBRIDdb/__init__.py", line 48, in Connect
    return Connection(*args, **kwargs)
  File "/usr/local/lib/python2.6/site-packages/CUBRIDdb/connections.py", line 19, in __init__
    self._db = _cubrid.connect(*args, **kwargs)
_cubrid.Error: (-1, 'ERROR: DBMS, 0, Unknown DBMS Error')

Executing an INSERT Statement

Now that the table is empty, insert data for the test. First, you have to obtain a cursor and then execute the INSERT statement.

cur = conn.cursor()
cur.execute("INSERT INTO posts (id, title, body, last_updated) VALUES (1, 'Title 1', 'Test body #1', CURRENT_TIMESTAMP)")
conn.commit()

The auto-commit in CUBRID Python driver is disabled by default. Therefore, you have to manually perform commit by using the commit () function after executing any SQL statement. This is equivalent to executing cur.execute("COMMIT") . The opposite to executing commit() is executing rollback (), which aborts the current transaction.

Another way to insert data is to use prepared statements. You can safely insert data into the database by defining a row that contains the parameters and passing it to the execute () function.

args = (2, 'Title 2', 'Test body #2')
cur.execute("INSERT INTO posts (id, title, body, last_updated) VALUES (?, ?, ?, CURRENT_TIMESTAMP)", args)

The entire script up to now looks like this:

import CUBRIDdb
conn = CUBRIDdb.connect('CUBRID:localhost:33000:demodb', 'public', '')
cur = conn.cursor()

# Plain insert statement
cur.execute("INSERT INTO posts (id, title, body, last_updated) VALUES (1, 'Title 1', 'Test body #1', CURRENT_TIMESTAMP)")

# Parameterized insert statement
args = (2, 'Title 2', 'Test body #2')
cur.execute("INSERT INTO posts (id, title, body, last_updated) VALUES (?, ?, ?, CURRENT_TIMESTAMP)", args)

conn.commit()

Fetching all records at a time

You can fetch entire records at a time by using the fetchall () function.

cur.execute("SELECT * FROM posts ORDER BY last_updated")
rows = cur.fetchall()
for row in rows:
    print row

This will return the two rows inserted earlier in the following form:

[1, 'Title 1', 'Test body #1', '2011-4-7 14:34:46']
[2, 'Title 2', 'Test body #2', '2010-4-7 14:34:46']

Fetching a single record at a time

In a scenario where a lot of data must be returned into the cursor, you can fetch only one row at a time by using the fetchone () function.

cur.execute("SELECT * FROM posts")
row = cur.fetchone()
while row:
    print row
    row = cur.fetchone()

Fetching as many as records desired at a time

You can fetch a specified number of records at a time by using the fetchmany () function.

cur.execute("SELECT * FROM posts")
rows = cur.fetchmany(3)
for row in rows:
    print row

Accessing Metadata on the Returned Data

If it is necessary to get information about column attributes of the obtained records, you should call the description method.

for description in cur.description:
    print description

The output of the script is as follows:

('id', 8, 0, 0, 0, 0, 0)
('title', 2, 0, 0, 255, 0, 0)
('body', 2, 0, 0, 1073741823, 0, 0)
('last_updated', 15, 0, 0, 0, 0, 0)

Each of row has the following information.

(column_name, data_type, display_size, internal_size, precision, scale, nullable)

For more information about numbers representing data types, see http://packages.python.org/CUBRID-Python/toc-CUBRIDdb.FIELD_TYPE-module.html .

Releasing Resource

After you have done using any cursor or connection to the database, you must release the resource by calling both object's close () function.

cur.close()
conn.close()
Python API

Python Database API is composed of connect() module class, Connection object, Cursor object, and many other auxiliary functions. For more information, see Python DB API 2.0 Official Documentation at http://www.python.org/dev/peps/pep-0249/.

You can find the information about CUBRID Python API at http://ftp.cubrid.org/CUBRID_Docs/Drivers/Python/.

Ruby Driver

CUBRID Ruby driver implements the interface to enable access from applications in Ruby to CUBRID database server and official one is available as a RubyGem package.

CUBRID Ruby driver is written based on CCI API so affected by CCI configurations such as CCI_DEFAULT_AUTOCOMMIT.

To download Ruby driver or get the latest information, click http://www.cubrid.org/wiki_apis/entry/cubrid-ruby-driver.

Installing and Configuring Ruby

Requirements

  • Ruby 1.8.7 or later
  • CUBRID gem
  • ActiveRecord gem

Linux

You can install the CUBRID Connector through gem. Make sure that you add the -E option so that the environment path where CUBRID has been installed cannot be reset by the sudo command.

sudo -E gem install cubrid

Windows

Enter the command line below to install the latest version of CUBRID Ruby driver.

gem install cubrid
Ruby Sample Program

This section will explain how to use Ruby ActiveRecord adapter to work with CUBRID database. Create tables by executing the following SQL script.

CREATE TABLE countries(
    id integer AUTO_INCREMENT,
    code character varying(3) NOT NULL UNIQUE,
    name character varying(40) NOT NULL UNIQUE,
    record_date datetime DEFAULT sysdatetime NOT NULL,
    CONSTRAINT pk_countries_id PRIMARY KEY(id)
);

CREATE TABLE cities(
    id integer AUTO_INCREMENT NOT NULL UNIQUE,
    name character varying(40) NOT NULL,
    country_id integer NOT NULL,
    record_date datetime DEFAULT sysdatetime NOT NULL,
    FOREIGN KEY (country_id) REFERENCES countries(id) ON DELETE RESTRICT ON UPDATE RESTRICT,
    CONSTRAINT pk_cities_id PRIMARY KEY(id)
);

Loading Library

Create a new file named tutorial.rb and add basic configuration.

require 'rubygems'
require 'active_record'
require 'pp'

Establishing Database Connection

Define the connection parameters as follows:

ActiveRecord::Base.establish_connection(
 :adapter => "cubrid",
 :host => "localhost",
 :database => "demodb" ,
 :user => "dba"
)

Inserting Objects into a Database

Before starting to operate on tables, you must declare the two tables' mapping in the database as ActiveRecord classes.

class Country < ActiveRecord::Base
end

class City < ActiveRecord::Base
end

Country.create(:code => 'ROU', :name => 'Romania')
Country.create(:code => 'HUN', :name => 'Hungary')
Country.create(:code => 'DEU', :name => 'Germany')
Country.create(:code => 'FRA', :name => 'France')
Country.create(:code => 'ITA', :name => 'Italy', :record_date => Time.now)
Country.create(:code => 'SPN', :name => 'Spain')

Selecting Records from a Database

Select records from a database as follows:

romania = Country.find(1)
pp(romania)

romania = Country.where(:code => 'ROU')
pp(romania)

Country.find_each do |country|
 pp(country)
end

Updating Database Records

Change the Spain code from 'SPN' to 'ESP'.

Country.transaction do
 spain = Country.where(:code => 'SPN')[0]
 spain.code = 'ESP'
 spain.save
end

Deleting Database Records

Delete records from a database as follows:

Country.transaction do
 spain = Country.where(:code => 'ESP')[0]
 spain.destroy
end

Working with Associations

One method to add cities to a country would be to select the Country and assign the country code to a new City object.

romania = Country.where(:code => 'ROU')[0]
City.create(:country_id => romania.id, :name => 'Bucharest');

A more elegant solution would be to let ActiveRecord know about this relationship and declare it in the Country class.

class Country < ActiveRecord::Base
 has_many :cities, :dependent => :destroy
end

class City < ActiveRecord::Base
end

In the code above, it is declared that one country can have many cities. Now it will be very easy to add new city to a country.

italy = Country.where(:code => 'ITA')[0]
italy.cities.create(:name => 'Milano');
italy.cities.create(:name => 'Napoli');

pp (romania.cities)
pp (italy.cities)

This would be very helpful because when we access cities we get all the cities recorded for the referenced country. Another use is that when you delete the country, all its cities are removed. All is done in one statement.

romania.destroy

ActiveRecord also supports other relationship including one-to-one, many-to-many, etc.

Working with Metadata

ActiveRecord enables the code to work with on different database backends without modifying the code.

Defining a database structure

A new table can be defined using ActiveRecord::Schema.define. Let's create two tables: books and authors with a one-to-many relationship between authors and books (one-to-many).

ActiveRecord::Schema.define do
 create_table :books do |table|
  table.column :title, :string, :null => false
  table.column :price, :float, :null => false
  table.column :author_id, :integer, :null => false
 end

 create_table :authors do |table|
  table.column :name, :string, :null => false
  table.column :address, :string
  table.column :phone, :string
 end

 add_index :books, :author_id
end

CUBRID-supported column types are :string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :boolean, :bit, :smallint, :bigint, and :char. Currently, :binary is not supported.

Managing table columns

You can add, update, delete columns by using features from ActiveRecord::Migration.

ActiveRecord::Schema.define do
 create_table :todos do |table|
  table.column :title, :string
  table.column :description, :string
 end

 change_column :todos, :description, :string, :null => false
 add_column :todos, :created, :datetime, :default => Time.now
 rename_column :todos, :created, :record_date
 remove_column :todos, :record_date

end

Dumping database schema

You can use ActiveRecord::SchemaDumper.dump to dump information for currently used schema. This is done into a platform independent format that is understood by Ruby ActiveRecord.

Note that if you are using custom column types database specific (:bigint, :bit), this may not work.

Obtaining Server Capabilities

You can get database information extracted from the current connections as in the example below:

puts "Maximum column length        : " + ActiveRecord::Base.connection.column_name_length.to_s
puts "SQL statement maximum length : " + ActiveRecord::Base.connection.sql_query_length.to_s
puts "Quoting : '''test'''         : " + ActiveRecord::Base.connection.quote("'''test'''")

Creating a schema

Due to the way CUBRID is functioning, you cannot programmatically create a schema as in the following example:

ActiveRecord::Schema.define do
 create_database('not_supported')
end

Node.js Driver

CUBRID Node.js driver is developed in 100% JavaScript and does not require specific platform compilation

Node.js is a platform built on Chrome's JavaScript runtime.

Node.js has the following specifics.

  • Event-driven, server-side JavaScript.
  • Good at handling lots of different kinds of I/O at the same time.
  • Non-blocking I/O model that makes it lightweight and efficient.

For more details, see http://nodejs.org/.

If you want to download CUBRRID Node.js driver or find the recent information, see the following sites:

Installing Node.js

Requirements

  • CUBRID 8.4.1 Patch 2 or higher
  • Node.js

Installation

You can install CUBRID Node.js driver with "npm(Node Packaged Modules) install" command, but firstly you need to install node.js on http://nodejs.org/download/.

npm install node-cubrid

If you uninstall CUBRID Node.js driver, do the following command.

npm uninstall node-cubrid

If you want to get the latest information about CUBRID-supported drivers, see http://www.cubrid.org/wiki_apis/entry/cubrid-apis-wiki.

Release Notes

10.0 Release Notes

Contents

Release Notes Information

This document includes information on CUBRID 10.0(Build No., 10.0.0.1376). CUBRID 10.0 includes all of the fixed errors and improved features that were detected in the CUBRID 9.3 and were applied to the previous versions.

For details on CUBRID 9.3 or earlier, see http://www.cubrid.org/manual/93/en/release_note/index.html.

For details on CUBRID 2008 R4.3 or less, see http://release.cubrid.org/en.

Overview

CUBRID 10.0 is the major upgrade version of CUBRID 9.3.

CUBRID 10.0

  • provides snapshot isolations based on MVCC protocol
  • significantly improves performance and scalability
  • supports TIMEZONE data types and functions
  • supports BINARY charset for string types
  • includes many SQL extensions and functions/operators
  • fixes a large number of critical bugs

The database volume of CUBRID 10.0 is not compatible with that of CUBRID 9.x and earlier versions. Therefore, if you use CUBRID 9.3 or earlier, you must migrate your databases. Regarding this, see Upgrade.

Driver Compatibility
  • The JDBC and CCI driver of CUBRID 10.0 are compatible with the DB server of CUBRID 9.1, 9.2, 2008 R4.1, R4.3 or R4.4.
  • To upgrade drivers are highly recommended.

We strongly recommend to also upgrade your drivers to use CUBRID 10.0. Some new features, especially for TIMEZONE data types are only supported with 10.0 drivers.

For more details on changes, see the following. Users of previous versions should check the Behavior Changes and New Cautions sections.

New Features
  • added charset and collation to system catalogs. (added _db_charset and db_charset. db_collation, db_class and db_attribute are modified) (CUBRIDSUS-10948)
  • added checksumdb utility to check a replication inconsistency (CUBRIDSUS-6214)
  • added CRC32 function (CUBRIDSUS-15470)
  • added JDBC constructor(CUBRIDTimestamptz) and setter(setTimestamptz) (CUBRIDSUS-15407)
  • added KILL statement (CUBRIDSUS-13845)
  • added PERCENTILE_DISC and PERCENTILE_CONT function which can be used as an aggregate or analytic function (CUBRIDSUS-11089)(CUBRIDSUS-11088)
  • added restoreslave utility (CUBRIDSUS-10843)
  • added several options to checkdb utility (CUBRIDSUS-11292)
  • added SHOW CRITICAL SECTION statement (CUBRIDSUS-14037)
  • added SHOW JOB QUEUE statement (CUBRIDSUS-14036)
  • added SHOW THREADS statement (CUBRIDSUS-14038)
  • added SHOW TIMEZONES statement (CUBRIDSUS-14186)
  • added SHOW TRANSACTION TABLES statement (CUBRIDSUS-14039)
  • added SLEEP function (CUBRIDSUS-14217)
  • added SYS_GUID function (CUBRIDSUS-6555)
  • added vacuumdb utility and check for not vacuumed records completely lost to checkdb utility (CUBRIDSUS-14751)
  • adopt MVCC(Multi-Version Concurreny Control) protocol and provides snapshot isolation(CUBRIDSUS-14097)
  • DEFAULT keyword for SET SYSTEM PARAMETERS statement resets to the default value of system parameter (CUBRIDSUS-15529)
  • improved ha_make_slavedb script to use it with ease (CUBRIDSUS-10842)
  • introduced BINARY charset for string (CHAR, VARCHAR, ENUM) types (CUBRIDSUS-16066)
  • supports COMMENT for schema objects such as table, column, view, index, JSP, trigger, serial and user. system catalogs were modified to show its comment (CUBRIDSUS-12367)
  • supports NATURAL JOIN (CUBRIDSUS-12401)
  • supports systemtap for dynamic tracing and performance analysis (CUBRIDSUS-11626)
  • supports TIMEZONE data types and functions (CUBRIDSUS-5765)
  • supports CREATE OR REPLACE PROCEDURE/FUNCTION (CUBRIDSUS-6542)
  • supports CASCADE CONSTRAINTS for DROP TABLE statement (CUBRIDSUS-9830)
  • supports CREATE TABLE IF NOT EXISTS statement (CUBRIDSUS-12366)
Behavior Changes
  • a subquery is not allowed in ORDER BY FOR clause (CUBRIDSUS-13210)
  • changed 64bit as the default build target (CUBRIDSUS-16770)
  • changed 64bit as the default build target of make_locale.sh (CUBRIDSUS-17755)
  • changed 64bit as the default build target of make_tz.sh (CUBRIDSUS-15812)
  • changed ALTER INDEX and DROP INDEX statement require table name to which the index belongs (CUBRIDSUS-11308)
  • changed a partitioning key must be part of the primary key's and the all the unique indexes' definition (CUBRIDSUS-13412)
  • changed behavior of preparedStatement.setBoolean method (CUBRIDSUS-14857)
  • changed clients not to read cubrid.conf file in the current working directory (CUBRIDSUS-10929)
  • changed not to allow altering an ordinary column to a shared and vice versa (CUBRIDSUS-11135)
  • changed REPLACE and GROUP_CONCAT functions to regard an empty parameter as an empty string rather than NULL even if oracle_style_empty_string system parameter is on (CUBRIDSUS-9864)
  • changed server will not be started when java_stored_procedure = on and $CUBRID/java/jspserver.jar is missing (CUBRIDSUS-9846)
  • changed to sort the result sets of SHOW INDEX by (key_name, seq_in_index) (CUBRIDSUS-12021)
  • changed type of DEFAULT column for CCI_SCH_ATTRIBUTE of cci_schema_info function as string (CUBRIDSUS-13898)
  • CURDATE(), CURRENT_DATE, CURRENT_DATE(), CURRENT_DATETIME, CURRENT_DATETIME(), NOW(), CURTIME(), CURRENT_TIME, CURRENT_TIME(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, LOCALTIMESTAMP() now refer to session time and date (CUBRIDSUS-17377)(CUBRIDSUS-17343)(CUBRIDSUS-17337)(CUBRIDSUS-16222)
  • database volume of 10.0 is not compatible with that of 9.x and earlier versions (CUBRIDSUS-11317)
  • fixed cci_get_data function to set the returned value as NULL when the value is NULL and type is CCI_A_TYPE_STR, CCI_A_TYPE_SET, CCI_A_TYPE_BLOB or CCI_A_TYPE_CLOB (CUBRIDSUS-8104)
  • fixed CCI_GET_RESULT_INFO_IS_NON_NULL to return 0 when an argument is not a column (CUBRIDSUS-8106)
  • fixed Connection.connect and cci_connect_with_url distinguish the user name and its password is omitted from an empty string(u2018u2019) (CUBRIDSUS-11383)
  • fixed ha_copy_log_timeout system parameter only works win SYNC log copy mode (CUBRIDSUS-16990)
  • fixed not to allow a serial for an auto increment to be cached (CUBRIDSUS-16264)
  • fixed not to allow dropping an user account when there is an active user (CUBRIDSUS-16937)
  • fixed ResultSet.findColumn to return the value of the first matching column when several columns have the same name (CUBRIDSUS-7374)
  • fixed to force strict increasing order of each partition for a range partition (CUBRIDSUS-15360)
  • fixed to ignore cubrid_broker.conf in the current working directory where broker starts (CUBRIDSUS-14207)
  • fixed to return an error when an out-of-range value is given as default value for float, double, monetary type column (CUBRIDSUS-7720)
  • fixed UPDATE STATISTICS statement to be propagated to slave and replica nodes (CUBRIDSUS-12550)
  • changed the default isolation as "READ COMMITTED"
  • removed 3 isolation levels such as "REPEATABLE READ SCHEMA, READ UNCOMMITTED INSTANCES", "READ COMMITTED SCHEMA, READ UNCOMMITTED INSTANCES" and "READ COMMITTED SCHEMA, READ UNCOMMITTED INSTANCES" (CUBRIDSUS-14377)
  • restrict the limit for the length of partition expression as 1K (CUBRIDSUS-17772)
  • restrict the max value of max_clients parameter as 2000 (CUBRIDSUS-14894)
  • UPDATE STATISTICS now works with sampling based. WITH FULLSCAN clause computes statistics with the entire records. (CUBRIDSUS-11962)
  • supports for using attribute references in UPDATE statement. The behavior can be changed with update_use_attribute_references parameter (CUBRIDSUS-8202)
Improvements and Bug fixes
  • fixed to reduce failover time (CUBRIDSUS-16045)
  • performance enhancement of replication (CUBRIDSUS-6162)
  • added additional warnings regarding connection status into cas sql log for troubleshooting (CUBRIDSUS-12212)
  • a query has a statement set operator whose subquery includes false where clause incorrectly returned a semantic error (CUBRIDSUS-12326)
  • binary values from database are displayed in JDBC as hex (CUBRIDSUS-18057)
  • cci_schema_info function call follows a CREATE TABLE statement may fail to browse the schema information (CUBRIDSUS-13617)
  • changed policy selecting a deadlock victim to choose a transaction did less amount of work (CUBRIDSUS-14790)
  • changed the separator of LOB paths for Windows as u2018\u2019 (CUBRIDSUS-11391)
  • changed to restrict the range of a port to unsigned short (CUBRIDSUS-8539)
  • cubrid heartbeat utility now allows to execute copylogdb, applylogdb and status command to a remote host (CUBRIDSUS-14318)
  • DEFAULT value of u2018u2019 was shown as NULL from db_attribute.default_value (CUBRIDSUS-12406)
  • extend statistics and statdump to track time (CUBRIDSUS-17445)
  • fixed a build issue of dbi.h for gcc under cygwin (CUBRIDSUS-12329)
  • fixed a build issue of Windows regarding a reference to cci_get_cas_info function (CUBRIDSUS-14000)
  • fixed ACCESS_LOG_MAX_SIZE parameter of cubrid_broker.conf to work on Windows (CUBRIDSUS-14232)
  • fixed a client crash of INSERT ODKU statement (CUBRIDSUS-16648)
  • fixed a client crash regarding an unexpected error like interrupt during query parsing (CUBRIDSUS-14509)
  • fixed a client crash when an invalid index is given as input to CREATE/ALTER INDEX (CUBRIDSUS-13899)
  • fixed a client crash when SHOW CREATE VIEW refers a view which includes a base table dropped (CUBRIDSUS-11618)
  • fixed a client crash while executing a query including a method or a JSP (CUBRIDSUS-15037)
  • fixed a client crash while restarting a connection (CUBRIDSUS-15165)
  • fixed a crash of Windows version (CUBRIDSUS-15133)
  • fixed a crash recovery failure when a crash happens during a volume is added (CUBRIDSUS-18118)
  • fixed adddate and subdate function to consider leap years (CUBRIDSUS-18104)
  • fixed a false detection of unique constraint violation for a partition table (CUBRIDSUS-14134)
  • fixed a loose index scan issue (CUBRIDSUS-13812)
  • fixed ALTER INDEX REBUILD statement to ignore the given properties and re-create the index as it is (CUBRIDSUS-12624)
  • fixed ALTER TABLE ADD SUPERCLASS statement with INHERIT clause failed to be replicated (CUBRIDSUS-11409)
  • fixed ALTER TABLE to understand PRIMARY KEY and NOT NULL constraint are given together (CUBRIDSUS-13234)
  • fixed a memory leak on CCI driver and an issue on cci_datasource_borrow function (CUBRIDSUS-17300)
  • fixed an error case that system thread to copy log read a log record that was not written yet while the master node terminates (CUBRIDSUS-15755)
  • fixed an error message of STR_TO_DATE function when a parameter of the function is omitted (CUBRIDSUS-9798)
  • fixed an incorrect view transformation when a view includes a statement set operator and LIMIT clause (CUBRIDSUS-10265)
  • fixed an issue applylogdb skipped to replicate logs when either db_ha_apply_info.committed_rep_pageid or committed_rep_offset is null (CUBRIDSUS-16288)
  • fixed an issue of a statement set query with overflow records (CUBRIDSUS-17841)
  • fixed an issue of cub_master for Windows cannot successfully start (CUBRIDSUS-14421)
  • fixed an issue of MERGE statement which includes DELETE clause (CUBRIDSUS-16658)
  • fixed an issue of non-atomic deallocation of volume pages. The volume header and the page bitmaps might not match. (CUBRIDSUS-18027)
  • fixed an issue regarding a series of partial rollback to the multiple nested savepoints (CUBRIDSUS-7908)
  • fixed an issue to insert or update an updatable view which includes LIMIT clause (CUBRIDSUS-10853)
  • fixed an issue to return incorrect result for an outer join or hierarchical query includes a JSP (CUBRIDSUS-14073)
  • fixed an unbounded wait which lead to time out to get a connection via cci_datasource_borrow() function (CUBRIDSUS-14064)
  • fixed an union compatibility issue regarding set data types (CUBRIDSUS-11790)
  • fixed a parsing error of an invalid query which includes an aggregation or analytic function in WHERE clause (CUBRIDSUS-14905)
  • fixed a parsing error of u201cSELECT * FROM (t1 JOIN t2)u201d style query (CUBRIDSUS-6045)
  • fixed a parsing error when a string typed argument is given as TO_CHAR function which is a partition key expression (CUBRIDSUS-15112)
  • fixed applylogdb to also show server error message when it fails schema replication (CUBRIDSUS-11426)
  • fixed a query has a statement set operator whose subquery includes false where clause was incorrectly folded. ORDER BY and LIMIT clause of a subquery for a statement set query were ignored for some cases (CUBRIDSUS-12326)
  • fixed a query parsing error where a query includes a JAVA stored procedure or a method and GROUP BY clause (CUBRIDSUS-12856)
  • fixed a race condition of server regarding an invalid session state (CUBRIDSUS-15223)
  • fixed a race condition of server when multiple clients are simultaneously executing DDLs (CUBRIDSUS-15026)
  • fixed a reserved word to be used as an alias without quoting (CUBRIDSUS-8909)
  • fixed a server crash when an interrupt happens (CUBRIDSUS-13886)
  • fixed a stand-alone mode of client crash when a method or a JSP is nested in a query (CUBRIDSUS-15590)
  • fixed a transactional inconsistency when a long committing transaction is followed by a short transaction and a crash happens before the former commits (CUBRIDSUS-17881)
  • fixed cci_get_class_num_objs function to also work for a view (CUBRIDSUS-7734)
  • fixed checkdb to consider a record that does not satisfy a filter index predicate (CUBRIDSUS-13686)
  • fixed CHR function with binary charset (CUBRIDSUS-17783)
  • fixed collation in domain of an host variable which was set to default one, disregarding the collation of actual value or collation inferred (CUBRIDSUS-14787)
  • fixed collation setting in ENUM type (CUBRIDSUS-16702)
  • fixed deadlock between DDLs by acquiring SCH_M_LOCK from beginning when executes ALTER, DROP table (CUBRIDSUS-13540)
  • fixed incorrect error message when a copylogdb starts twice (CUBRIDSUS-12043)
  • fixed incorrect handling of a drive name of lob-base-path for Windows createdb (CUBRIDSUS-10590)
  • fixed incorrect management of transaction status when a CAS is changed to another right after connected to an application and has a request that does not transit its status (CUBRIDSUS-13265)
  • fixed incorrect range merging optimizations (CUBRIDSUS-17449)
  • fixed INSERT ODKU into a partition table to detect duplicated values to be inserted/updated (CUBRIDSUS-16067)
  • fixed installdb utility to add default lob path to the directory file(databases.txt) (CUBRIDSUS-14816)
  • fixed issues some DDLs were not replicated to slave (CUBRIDSUS-16827)(CUBRIDSUS-11430)
  • fixed JDBC and CCI drivers to create log directories when a logging parameter is set (CUBRIDSUS-11320)
  • fixed kill session statement of CSQL interpreter to show the number of transactions terminated (CUBRIDSUS-14288)
  • fixed loaddb to accept an exported schema definition which is longer than 8K (CUBRIDSUS-7890)
  • fixed loaddb to show an additional error message when an error occurred during object loading (CUBRIDSUS-7905)
  • fixed MEDIAN function returned an incorrect result when the argument includes CAST operator (CUBRIDSUS-13916)
  • fixed memory leak of SA mode (CUBRIDSUS-14141)
  • fixed MERGE statement which includes DELETE clause in UPDATE clause suffered a run-time error (CUBRIDSUS-15691)
  • fixed not to add a new volume if there is a volume has enough pages (CUBRIDSUS-16219)
  • fixed not to allow SET DEFAULT NULL to a column which has NOT NULL constraint (CUBRIDSUS-8035)
  • fixed not to block a SELECT operation during the entire period of creating an index (CUBRIDSUS-9576)
  • fixed not to print -970 error which is a notification of HA mode change when ha_mode is off (CUBRIDSUS-12336)
  • fixed not to raise an additional fatal error when creating a database fails (CUBRIDSUS-14647)
  • fixed not to refer an obsoleted cache entry to a view or trigger in clients to execute a prepared query (CUBRIDSUS-14856)
  • fixed NullpointerException of XAConnection (contributed by Marcus Haarmann) (CUBRIDSUS-14678)
  • fixed partition whose key is an expression to correctly infer its data type (CUBRIDSUS-15106)
  • fixed race conditions of server when simultaneous update statistics requests are executing (CUBRIDSUS-13718) (CUBRIDSUS-16773) (CUBRIDSUS-17000)
  • fixed rpm package regarding the default user account (CUBRIDSUS-13842)
  • fixed several anomalies regarding referential integrity (CUBRIDSUS-12781) (CUBRIDSUS-12782) (CUBRIDSUS-12783) (CUBRIDSUS-12784)
  • fixed several deadlock chances (CUBRIDSUS-10332)(CUBRIDSUS-5084)(CUBRIDSUS-5011)(CUBRIDSUS-5008)(CUBRIDSUS-5004)(CUBRIDSUS-9469)
  • fixed several race conditions and crashes due to concurrent UPDATE STATISTICS operations (CUBRIDSUS-16773)
  • fixed several recovery issues on a volume header and system page regarding page allocation and deallocation (CUBRIDSUS-17835)
  • fixed temp_volume_path system parameter works (CUBRIDSUS-9484)
  • fixed the owner of a partitioned table also owns partitions even if DBA changes a table as a partitioned (CUBRIDSUS-11407)
  • fixed to abort installation of 64bit build on 32bit Windows (CUBRIDSUS-13822)
  • fixed to add extra checking of connection properties (CUBRIDSUS-7581)
  • fixed to allow a quoted reserved word in GROUP BY clause (CUBRIDSUS-13468)
  • fixed to allow conversion of string in scientific notation to BIGINT type (CUBRIDSUS-14254)
  • fixed to allow dropping an unique index without mentioning UNIQUE (CUBRIDSUS-9352)
  • fixed TO_CHAR and TO_NUMBER function to understand the EUCKR padding (CUBRIDSUS-17953)
  • fixed to close scans when an hierarchical query suffers an error during execution (CUBRIDSUS-17951)
  • fixed to consider codeset for monetary symbols (CUBRIDSUS-17942)
  • fixed to consume permanent temp volumes and then add a temporary temp volume (CUBRIDSUS-17989)
  • fixed to correctly handle the maximum value of timestamp on Windows 32bit build (CUBRIDSUS-9398)
  • fixed to create, alter and drop an index of a table to update the statistics of the entire indexes of the table (CUBRIDSUS-12053)
  • fixed to detect an incorrect combination of multiple levels of backup volumes are given to restoredb (CUBRIDSUS-13646)
  • fixed to fire UPDATE triggers instead of DELETE triggers when UPDATE statement moves a record from a partition to another (CUBRIDSUS-12472)
  • fixed to omit ON clause for explicit inner join (CUBRIDSUS-8714)
  • fixed to raise a proper error for an invalid query refers INST_NUM or ORDERBY_NUM (CUBRIDSUS-12843)
  • fixed to re-cache view definition when a base table or a nested view of the view suffers a change (CUBRIDSUS-17971)
  • fixed to recover replication failure by unexpected deletion of db_ha_apply_info catalog table (CUBRIDSUS-12065)
  • fixed to reduce the memory usage of restoredb with multiple levels of backups (CUBRIDSUS-11868)
  • fixed to return an error when an invalid argument of CONV function is given (CUBRIDSUS-9434)
  • fixed to return an error when return_null_on_errors=no and plus or minus operator is used with zero date (CUBRIDSUS-9449)
  • fixed to show index name when violates an unique constraint (CUBRIDSUS-14946)
  • fixed to show the detailed error message when service parameter of cubrid.conf is invalid (CUBRIDSUS-9256)
  • fixed to show the name of the index where an unique constraint is violated while loading it (CUBRIDSUS-11739)
  • fixed to trim a trailing blank of session commands for CSQL interpreter (CUBRIDSUS-13266)
  • fixed to update max_val of auto increment column when the type of column changes (CUBRIDSUS-13154)
  • fixed UTC_TIME function considers daylight saving time (CUBRIDSUS-9328)
  • introduced -t and -N option of csql (CUBRIDSUS-14406)
  • LIMIT, ORDER BY clause were ignored during view transformation when a view includes UNION ALL as well as them (CUBRIDSUS-8059)
  • multiple DDL statements that are not separated by a semicolon were not replicated to slave (CUBRIDSUS-16954)
  • on-line backup occasionally failed due to a concurrent DDL (CUBRIDSUS-7335)
  • revised SHOW INDEX HEADER statement (CUBRIDSUS-13637)
  • revised the error message when the given address or the name of server for cci_connect functions is invalid (CUBRIDSUS-11253)
  • SHOW CREATE TABLE now shows the reference column name of a foreign key (CUBRIDSUS-12184)
  • SHOW LOG HEADER statement shows MVCC-related information (CUBRIDSUS-14709)
  • SHOW SLOTTED PAGER HEADER statement shows MVCC-related information (CUBRIDSUS-14780)
  • unloaddb missed to export a reverse index of a table which also has an unique index (CUBRIDSUS-12476)
  • UPDATE, DELETE and MERGE statements will no longer claim aggregate functions from subqueries. SELECT statements will no longer claim aggregate functions from subqueries found in the WHERE clause. (CUBRIDSUS-11685)
  • UPDATE is now allowed on updatable views that contain joins, given that the user updates only one of the tables joined in the view (CUBRIDSUS-8110)
  • UTC_DATE function now considers daylight saving time (CUBRIDSUS-14774)
Cautions
Existing Cautions
Locale(language and charset) is specified when creating DB

It is changed as locale is specified when creating DB.

CUBRID_CHAERSET environment variable is removed

As locale(language and charset) is specified when creating DB from 9.2 version, CUBRID_CHARSET is not used anymore.

[JDBC] Change zero date of TIMESTAMP into '1970-01-01 00:00:00'(GST) from '0001-01-01 00:00:00' when the value of zeroDateTimeBehavior in the connection URL is "round"(CUBRIDSUS-11612)

From 2008 R4.4, when the value of the property "zeroDateTimeBehavior" in the connection URL is "round", the zero date value of TIMESTAMP is changed into '1970-01-01 00:00:00'(GST) from '0001-01-01 00:00:00'. You should be cautious when using zero date in your application.

Recommendation for installing CUBRID SH package in AIX(CUBRIDSUS-12251)

If you install CUBRID SH package by using ksh in AIX OS, it fails with the following error.

0403-065 An incomplete or invalid multibyte character encountered.

Therefore, it is recommended to use ksh93 or bash instead of ksh.

$ ksh93 ./CUBRID-9.2.0.0146-AIX-ppc64.sh
$ bash ./CUBRID-9.2.0.0146-AIX-ppc64.sh
CUBRID_LANG is removed, CUBRID_MSG_LANG is added

From version 9.1, CUBRID_LANG environment variable is no longer used. To output the utility message and the error message, the CUBRID_MSG_LANG environment variable is used.

Modify how to process an error for the array of the result of executing several queries at once in the CCI application(CUBRIDSUS-9364)

When executing several queries at once in the CCI application, if an error has occurs from at least one query among the results of executing queries by using the cci_execute_array function, the cci_execute_batch function, the error code of the corresponding query was returned from 2008 R3.0 to 2008 R4.1. This problem has been fixed to return the number of the entire queries and check the error of each query by using the CCI_QUERY_RESULT_* macros from 2008 R4.3 and 9.1.

In earlier versions of this modification, there is no way to know whether each query in the array is success or failure when an error occurs; therefore, it it requires certain conditions.

...
char *query = "INSERT INTO test_data (id, ndata, cdata, sdata, ldata) VALUES (?, ?, 'A', 'ABCD', 1234)";
...
req = cci_prepare (con, query, 0, &cci_error);
...
error = cci_bind_param_array_size (req, 3);
...
error = cci_bind_param_array (req, 1, CCI_A_TYPE_INT, co_ex, null_ind, CCI_U_TYPE_INT);
...
n_executed = cci_execute_array (req, &result, &cci_error);

if (n_executed < 0)
  {
    printf ("execute error: %d, %s\n", cci_error.err_code, cci_error.err_msg);

    for (i = 1; i <= 3; i++)
      {
        printf ("query %d\n", i);
        printf ("result count = %d\n", CCI_QUERY_RESULT_RESULT (result, i));
        printf ("error message = %s\n", CCI_QUERY_RESULT_ERR_MSG (result, i));
        printf ("statement type = %d\n", CCI_QUERY_RESULT_STMT_TYPE (result, i));
      }
  }
...

From the modified version, entire queries are regarded as failure if an error occurs. In case that no error occurred, it is determined whether each query in the array succeeds or not.

...
char *query = "INSERT INTO test_data (id, ndata, cdata, sdata, ldata) VALUES (?, ?, 'A', 'ABCD', 1234)";
...
req = cci_prepare (con, query, 0, &cci_error);
...
error = cci_bind_param_array_size (req, 3);
...
error = cci_bind_param_array (req, 1, CCI_A_TYPE_INT, co_ex, null_ind, CCI_U_TYPE_INT);
...
n_executed = cci_execute_array (req, &result, &cci_error);
if (n_executed < 0)
  {
    printf ("execute error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
  }
else
  {
    for (i = 1; i <= 3; i++)
      {
        printf ("query %d\n", i);
        printf ("result count = %d\n", CCI_QUERY_RESULT_RESULT (result, i));
        printf ("error message = %s\n", CCI_QUERY_RESULT_ERR_MSG (result, i));
        printf ("statement type = %d\n", CCI_QUERY_RESULT_STMT_TYPE (result, i));
      }
  }
...
In java.sql.XAConnection interface, HOLD_CURSORS_OVER_COMMIT is not supported(CUBRIDSUS-10800)

Current CUBRID does not support ResultSet.HOLD_CURSORS_OVER_COMMIT in java.sql.XAConnection interface.

From 9.0, STRCMP behaves case-sensitively

Until the previous version of 9.0, STRCMP did not distinguish an uppercase and a lowercase. From 9.0, it compares the strings case-sensitively. To make STRCMP case-insensitive, you should use case-insensitive collation(e.g.: utf8_en_ci).

-- In previous version of 9.0 STRCMP works case-insensitively
SELECT STRCMP ('ABC','abc');
0

-- From 9.0 version, STRCMP distinguish the uppercase and the lowercase when the collation is case-sensitive.
export CUBRID_CHARSET=en_US.iso88591

SELECT STRCMP ('ABC','abc');
-1

-- If the collation is case-insensitive, it distinguish the uppercase and the lowercase.
export CUBRID_CHARSET=en_US.iso88591

SELECT STRCMP ('ABC' COLLATE utf8_en_ci ,'abc' COLLATE utf8_en_ci);
0
Since the 2008 R4.1 version, the Default value of CCI_DEFAULT_AUTOCOMMIT has been ON(CUBRIDSUS-5879)

The default value for the CCI_DEFAULT_AUTOCOMMIT broker parameter, which affects the auto commit mode for applications developed with CCI interface, has been changed to ON since CUBRID 2008 R4.1. As a result of this change, CCI and CCI-based interface (PHP, ODBC, OLE DB etc.) users should check whether or not the application's auto commit mode is suitable for this.

From the 2008 R4.0 version, the options and parameters that use the unit of pages were changed to use the unit of volume size(CUBRIDSUS-5136)

The options (-p, -l, -s), which use page units to specify the database volume size and log volume size of the cubrid createdb utility, will be removed. Instead, the new options, added after 2008 R4.0 Beta (--db-volume-size, --log-volume-size, --db-page-size, --log-page-size), are used.

To specify the database volume size of the cubrid addvoldb utility, use the newly-added option (--db-volume-size) after 2008 R4.0 Beta instead of using the page unit. It is recommended to use the new system parameters in bytes because the page-unit system parameters will be removed. For details on the related system parameters, see the below.

Be cautious when setting db volume size if you are a user of a version before 2008 R4.0 Beta(CUBRIDSUS-4222)

From the 2008 R4.0 Beta version, the default value of data page size and log page size in creating the database was changed from 4 KB to 16 KB. If you specify the database volume to the page count, the byte size of the volume may differ from your expectations. If you did not set any options, 100MB-database volume with 4KB-page size was created in the previous version. However, starting from the 2008 R4.0, 512MB-database volume with 16KB-page size is created.

In addition, the minimum size of the available database volume is limited to 20 MB. Therefore, a database volume less than this size cannot be created.

The change of the default value of some system parameters of the versions before 2008 R4.0(CUBRIDSUS-4095)

Starting from 2008 R4.0, the default values of some system parameters have been changed.

Now, the default value of max_clients, which specifies the number of concurrent connections allowed by a DB server, and the default value of index_unfill_factor that specifies the ratio of reserved space for future updates while creating an index page, have been changed. Furthermore, the default values of the system parameters in bytes now use more memory when they exceed the default values of the previous system parameters per page.

Previous System Parameter Added System Parameter Previous Default Value Changed Default Value (unit: byte)
max_clients None 50 100
index_unfill_factor None 0.2 0.05
data_buffer_pages data_buffer_size 100M(page size=4K) 512M
log_buffer_pages log_buffer_size 200K(page size=4K) 4M
sort_buffer_pages sort_buffer_size 64K(page size=4K) 2M
index_scan_oid_buffer_pages index_scan_oid_buffer_size 16K(page size=4K) 64K

In addition, when a database is created using cubrid createdb, the minimum value of the data page size and the log page size has been changed from 1K to 4K.

Changed so that database services, utilities, and applications cannot be executed when the system parameter is incorrectly configured(CUBRIDSUS-5375)

It has been changed so that now the related database services, utilities, and applications are not executed when configuring system parameters that are not defined in cubrid.conf or cubrid_ha.conf, when the value of system parameters exceed the threshold, or when the system parameters per page and the system parameters in bytes are used simultaneously.

Database fails to start if the data_buffer_size is configured with a value that exceeds 2G in CUBRID 32-bit version(CUBRIDSUS-5349)

In the CUBRID 32-bit version, if the value of data_buffer_size exceeds 2G, the running database fails. Note that the configuration value cannot exceed 2G in the 32-bit version because of the OS limit.

Recommendations for controlling services with the CUBRID Utility in Windows Vista and higher(CUBRIDSUS-4186)

To control services using cubrid utility from Windows Vista and higher, it is recommended to start the command prompt window with administrative privileges.

If you don't start the command prompt window with administrative privileges and use the cubrid utility, you can still execute it with administrative privileges through the User Account Control (UAC) dialog box, but you will not be able to verify the resulting messages.

The procedures for starting the command prompt window as an administrator in Windows Vista and higher are as follows:

  • Right-click [Start > All Programs > Accessories > Command Prompt].
  • When [Execute as an administrator (A)] is selected, a dialog box to verify the privilege escalation is activated. Click “YES" to start with administrative privileges.
GLO class which is used in 2008 r3.0 or before is not supported any longer(CUBRIDSUS-3826)

CUBRID 2008 R3.0 and earlier versions processed Large Objects with the Generalized Large Object glo class, but the glo class has been removed from CUBRID 2008 R3.1 and later versions. Instead, they support BLOB and CLOB (LOB from this point forward) data types. (See BLOB/CLOB Data Types for more information about LOB data types).

glo class users are recommended to carry out tasks as follows:

  • After saving GLO data as a file, modify to not use GLO in any application and DB schema.
  • Implement DB migration by using the unloaddb and loaddb utilities.
  • Perform tasks to load files into LOB data according to the modified application.
  • Verify the application that you modified operates normally.

For reference, if the cubrid loaddb utility loads a table that inherits the GLO class or has the GLO class type, it stops the data from loading by displaying an error message, "Error occurred during schema loading."

With the discontinued support of GLO class, the deleted functions for each interface are as follows:

Interface Deleted Functions
CCI

cci_glo_append_data

cci_glo_compress_data

cci_glo_data_size

cci_glo_delete_data

cci_glo_destroy_data

cci_glo_insert_data

cci_glo_load

cci_glo_new

cci_glo_read_data

cci_glo_save

cci_glo_truncate_data

cci_glo_write_data

JDBC

CUBRIDConnection.getNewGLO

CUBRIDOID.loadGLO

CUBRIDOID.saveGLO

PHP

cubrid_new_glo

cubrid_save_to_glo

cubrid_load_from_glo

cubrid_send_glo

Port configuration is required if the protocol between the master and server processes is changed, or if two versions are running at the same time(CUBRIDSUS-3564)

Because the communication protocol between a master process (cub_master) and a server process (cub_server) has been changed, the master process of CUBRID 2008 R3.0 or later cannot communicate with the server process of a lower version, and the master process of a lower version cannot communicate with a server process of 2008 R3.0 version or later. Therefore, if you run two versions of CUBRID at the same time by adding a new version in an environment where a lower version has already been installed, you should modify the cubrid_port_id system parameter of cubrid.conf so that different ports are used by the different versions.

Specifying a question mark when entering connection information as a URL string in JDBC(CUBRIDSUS-3217)

When entering connection information as a URL string in JDBC, property information was applied even if you did not enter a question mark (?) in the earlier version. However, you must specify a question mark depending on syntax in this CUBRID 2008 R3.0 version. If not, an error is displayed. In addition, you must specify colon (:) even if there is no username or password in the connection information.

URL=jdbc:CUBRID:127.0.0.1:31000:db1:::altHosts=127.0.0.2:31000,127.0.0.3:31000 -- Error
URL=jdbc:CUBRID:127.0.0.1:31000:db1:::?altHosts=127.0.0.2:31000,127.0.0.3:31000 -- Normal
Not allowed to include @ in a database name(CUBRIDSUS-2828)

If @ is included in a database name, it can be interpreted that a host name has been specified. To prevent this, a revision has been made so that @ cannot be included in a database name when running cubrid createdb, cubrid renamedb and cubrid copydb utilities.

General Information

Revision history
Revision Date Description
Feb. 2016 CUBRID 10.0 Release (10.0.0.1376)
Bug Reports and User Feedback

CUBRID welcomes your active participation in bug reporting and looks forward to your feedback. You can register your bug reports and feedback on the following Websites:

Document Description
Bug Report CUBRID Bug Bash: http://jira.cubrid.org
User Feedback

CUBRID Open Source Project: http://www.cubrid.org/forum

CUBRID Website: http://www.cubrid.org/

License

The GNU GPL v2 license or later applies to the CUBRID server engine, and the BSD license applies to CUBRID MANAGER and interfaces (APIs). For more information, see the License Policy on http://www.cubrid.org/license.

Additional Information

Regarding CUBRID upgrade and migration, see Upgrade.

Regarding CUBRID Tool, see http://www.cubrid.org/wiki_tools.

Regarding CUBRID Drivers, see http://www.cubrid.org/wiki_apis.

Regarding the recent CUBRID sources, see http://svn.cubrid.org/.

Note on Drivers

Currently, CUBRID supports the following drivers: JDBC, CCI(CUBRID C API), Node.js, PHP, PDO, Python, Perl, Ruby, ADO.NET, ODBC, OLE DB. These drivers except JDBC, Node.js and ADO.NET are developed on top of CCI. Therefore, CCI changes can affect CCI-based drivers.

Index