Open Source RDBMS - Seamless, Scalable, Stable and Free

한국어 | Login |Register

Data Flows And Code Snipplets


We have documented the CUBRID TCP/IP communication protocol here.

You can download the full document here.

In this document, we will take a look at:

  • Some typical data flow structures for a client application
  • Some code examples/snippets, to give you a quick insight on how to use the protocol in your own CUBRID client applications.

Table of Contents

 

Communication data flows

 

Basic data flow structure for a CUBRID client

 

The basic data flow structure of a CUBRID client application contains the following main components:

  1. Connect to the broker
  2. Open a database connection
  3. Execute client request and process CUBRID responses
  4. Disconnect

Of course, handling errors must be handled for each operation that can end up with an error/exception.

diagram1.png

For simplicity, in the next sections, we will refer at the 2 connection-related components:

·         Connect to the broker

·         Open a database connection

as a single logical operation – “Open database successfully.

 

Connection to the database

 

This data flow structure contains the following main components:

  1. Open TCP/IP connection to the CUBRID Broker port
  2. Interpret response and reconnect to a different port, if needed
  3. Open connection to the CUBRID database
  4. Interpret response
  5. …proceed with further operations…

diagram2.png

Connect, Execute non-query statements, Disconnect

 

The data flow structure contains the following main components:

  1. Open database successfully
  2. Do EXECUTE BATCH STATEMENTS sequence:
    • Prepare “local” data (= statements to execute)
    • Send data (=Request)
    • Receive data (=Response)
    • Process received data (=organize, display etc.)
  3. (Repeat 2.)
  4. Disconnect

diagram3.png

Connect, Execute query, Show immediate results, Fetch and show more results, Disconnect

 

The data flow structure contains the following main components:

  1. Open database successfully
  2. Do PREPARE AND EXECUTE QUERY sequence:
    • Prepare “local” data (= single query to execute)
    • Send data (=Request)
    • Receive data (=Response)
    • Process received data (=organize, display etc.)
  3. Do FETCH more data:
    • Receive data (=Response)
    • Process received data (=organize, display etc.)
  4. Repeat 3, if needed
  5. Repeat 2, if needed
  6. Disconnect

diagram4.png

Code snippets

 

In this section we will show you some code snippets which implements the CUBRID Communication protocol.

Most of the code originates from the CUBRD drivers – see Resources for the locations where you can get access to the full source code.

For variety, we will feature code snippets which use C#, Java, Python and Node.js.

 

Connecting to a CUBRID Broker

 

Language: C#

Connect(server, port);

// Send driver information and get (new) port 
int newPort = SendDriverInfo();
 
if (newPort < 0)
{
    throw new CUBRIDException(Utils.GetStr(MsgId.InvalidConnectionPort));
}
 
if (newPort > 0)
{
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, 1));
    socket.Close();
    Connect(server, newPort);
}

 

Open a database connection

 

Language: Python

"""
  Send request to the database engine
"""

logging.debug('Send database connection request...')

database = self._database.ljust(32, chr(0))
user = self._user.ljust(32, chr(0))
password = self._password.ljust(32, chr(0))
url = ''.ljust(512, chr(0))
filler = ''.ljust(20, chr(0))
send_buffer = '%s%s%s%s%s' % (database, user, password, url, filler)
 
try:
    self._sock.sendall(send_buffer)
except:
    raise Exception(get_error_message(self.locale, ERROR_ID.ERROR_SENDING_DATA))

# Parse response data
self._CAS_INFO = helpers.get_bytes_array_from_string(response, 0, SOCKET.CAS_INFO_SIZEOF):
self._response_code = conversion.signed_int(conversion.chr_array_to_num(response, 4, DATA_TYPES.INT_SIZEOF))

if self._response_code < 0:
    self._error_code = conversion.signed_int(conversion.chr_array_to_num(response, 8, DATA_TYPES.INT_SIZEOF))
    self._error_msg = response12: 12 + expectedResponseLength - 3 * DATA_TYPES.INT_SIZEOF - 1
    logging.error('Error: %s' % self._error_msg)
    raise Exception('%d: %s' % (self._error_code, self._error_msg))
else:
    self._BROKER_INFO = helpers.get_bytes_array_from_string(response, 8, SOCKET.BROKER_INFO_SIZEOF):
    self._session_id = conversion.chr_array_to_num(response, 16, DATA_TYPES.INT_SIZEOF)
logging.debug('Session id: %d.' % self._session_id)
logging.debug('Connected.')

 

Close database connection

 

Language: C#

stream.WriteCommand(CASFunctionCode.CAS_FC_CON_CLOSE);
WriteIntOverwrite(writtenLength - (DATA_LENGTH_SIZEOF + CAS_INFO_SIZE), 0, 0);
//Write CAS info
WriteBytesOverwrite(casInfo, 0, CAS_INFO_SIZE);
for (int i = 0; i < requestBufferCursor; i++)
{
    baseStream.Write(requestBufferi, 0, requestBufferi.Length);
}
if (writeCursor > 0)
{
    baseStream.Write(requestBufferrequestBufferCursor, 0, writeCursor);
}
baseStream.Flush();

 

Retrieve the database version

 

Language: Node.js

writer._writeInt(bufferLength - DATA_TYPES.DATA_LENGTH_SIZEOF - DATA_TYPES.CAS_INFO_SIZE);
writer._writeBytes(DATA_TYPES.CAS_INFO_SIZE, this.casInfo);
writer._writeByte(CAS.CASFunctionCode.CAS_FC_GET_DB_VERSION);
writer._writeInt(DATA_TYPES.BYTE_SIZEOF);
writer._writeByte(1);

...

this.engineVersion = parser._parseNullTerminatedString(reponseLength - DATA_TYPES.INT_SIZEOF);

 

Execute non-query SQL statements

 

Language: Java

outBuffer.newRequest(output, UFunctionCode.EXECUTE_BATCH_STATEMENT);
outBuffer.addByte(getAutoCommit() ? (byte) 1 : (byte) 0);
 
for (int i = 0; i <batchSqlStmt.length; i++) {
    if (batchSqlStmti != null)
        outBuffer.addStringWithNull(batchSqlStmti);
    else
        outBuffer.addNull();
}
 
UInputBufferinBuffer;
inBuffer = send_recv_msg();
int result;
UBatchResultbatchResult = new UBatchResult(inBuffer.readInt());
for (int i = 0; i <batchResult.getResultNumber(); i++) {
    batchResult.setStatementType(i, inBuffer.readByte());
    result = inBuffer.readInt();
    if (result < 0)
        batchResult.setResultError(i, result, inBuffer.readString(
    inBuffer.readInt(), UJCIManager.sysCharsetName));
    else {
        batchResult.setResult(i, result);
        // jci 3.0
        inBuffer.readInt();
        inBuffer.readShort();
        inBuffer.readShort();
    }
}
transactionList.add(null);
update_executed = true;

return batchResult;

 

Commit transaction

 

Language: Java

if (UJCIUtil.isConsoleDebug()) {
    if (!lastAutoCommit || isAutoCommitBySelf || type == false) {
        // this is ok
    } else {
        throw new Exception(…)
    }
}

outBuffer.newRequest(output, UFunctionCode.END_TRANSACTION);
outBuffer.addByte((type == true) ? END_TRAN_COMMIT : END_TRAN_ROLLBACK);

send_recv_msg();
if (lastAutoCommit) {
    turnOffAutoCommitBySelf();
}

 

Notes

Please note that the CUBRID Communication protocol contains more sequences that we have documented so far.

What we have targeted for now are the most important/relevant protocol components – the ones which are most likely to be used by every CUBRID client application.

We will continue to document the protocol to include what was left outside for now, to give you a full insight into this side of CUBRID client programming.

 

Resources

Resource

Link/Location

CUBRID ADO.NET driver code

http://svn.cubrid.org/cubridapis/adodotnet/branches/RB-8.4.1/Data/Source/

CUBRID JDBC driver code

http://www.cubrid.org/wiki_apis/entry/cubrid-jdbc-driver

CUBRID Node.js driver code

https://github.com/CUBRID/node-cubrid

CUBRID CCI API code

http://svn.cubrid.org/websvn/listing.php?repname=cubridengine&path=%2Fbranches%2FRB-9.1.0%2Fsrc%2Fcci%2F&#a7b3a61dca0ea840ba62fed6f828eca0e

comments powered by Disqus
Page info
viewed 792 times
translations en
Author
posted 9 months ago by
CUBRID
Contributors
updated 9 months ago by
View revisions
Share this article