SQL and Scan Queries

❗️

This is a legacy Apache Ignite documentation

The new documentation is hosted here: https://ignite.apache.org/docs/latest/

Operation codes

Upon a successful handshake with an Ignite server node, a client can start performing various SQL and scan queries by sending a request (see request/response structure below) with a specific operation code:

OperationOP_CODE
OP_QUERY_SQL2002
OP_QUERY_SQL_CURSOR_GET_PAGE2003
OP_QUERY_SQL_FIELDS2004
OP_QUERY_SQL_FIELDS_CURSOR_GET_PAGE2005
OP_QUERY_SCAN2000
OP_QUERY_SCAN_CURSOR_GET_PAGE2001
OP_RESOURCE_CLOSE0

Note that the above mentioned op_codes are part of the request header, as explained here.

👍

Customs Methods Used in Sample Code Snippets Implementation

Some of the code snippets below use readDataObject(...) introduced in this section and little-endian versions of methods for reading and writing multiple-byte values that are covered in this example.

OP_QUERY_SQL

Executes an SQL query over data stored in the cluster. The query returns the whole record (key and value).

Request TypeDescription
HeaderRequest header.
intCache ID: Java-style hash code of the cache name
byteUse 0. This field is deprecated and will be removed in the future.
StringName of a type or SQL table.
StringSQL query string.
intQuery argument count.
Data Object

Query argument.

Repeat for as many times as the query argument count that is passed in the previous parameter.

boolDistributed joins.
boolLocal query.
boolReplicated only - Whether query contains only replicated tables or not.
intCursor page size.
long

Timeout (miliseconds).

Timeout value should be non-negative. Zero value disables timeout.

Response includes the first page of the result.

Response TypeDescription
HeaderResponse header.
longCursor id. Can be closed with OP_RESOURSE_CLOSE.
intRow count for the first page.
Key Data Object + Value Data Object

Records in the form of key-value pairs.

Repeat for as many times as the row count obtained in the previous parameter.

boolIndicates whether more results are available to be fetched with OP_QUERY_SQL_CURSOR_GET_PAGE.
When true, query cursor is closed automatically.
String entityName = "Person";
int entityNameLength = getStrLen(entityName); // UTF-8 bytes

String sql = "Select * from Person";
int sqlLength = getStrLen(sql);

DataOutputStream out = new DataOutputStream(socket.getOutputStream());

// Request header
writeRequestHeader(34 + entityNameLength + sqlLength, OP_QUERY_SQL, 1, out);

// Cache id
String queryCacheName = "personCache";
writeIntLittleEndian(queryCacheName.hashCode(), out);

// Flag = none
writeByteLittleEndian(0, out);

// Query Entity
writeString(entityName, out);

// SQL query
writeString(sql, out);

// Argument count
writeIntLittleEndian(0, out);

// Joins
out.writeBoolean(false);

// Local query
out.writeBoolean(false);

// Replicated
out.writeBoolean(false);

// cursor page size
writeIntLittleEndian(1, out);

// Timeout
writeLongLittleEndian(5000, out);
// Read result
DataInputStream in = new DataInputStream(socket.getInputStream());

// Response header
readResponseHeader(in);

long cursorId = readLongLittleEndian(in);

int rowCount = readIntLittleEndian(in);

// Read entries (as user objects)
for (int i = 0; i < rowCount; i++) {
  Object key = readDataObject(in);
  Object val = readDataObject(in);

  System.out.println("CacheEntry: " + key + ", " + val);
}

boolean moreResults = readBooleanLittleEndian(in);

OP_QUERY_SQL_CURSOR_GET_PAGE

Retrieves the next SQL query cursor page by cursor id from OP_QUERY_SQL.

Request TypeDescription
HeaderRequest header.
longCursor id.

Response format looks as follows:

Response TypeDescription
HeaderResponse header.
longCursor id.
intRow count.
Key Data Object + Value Data Object

Records in the form of key-value pairs.

Repeat for as many times as the row count obtained in the previous parameter.

boolIndicates whether more results are available to be fetched with OP_QUERY_SQL_CURSOR_GET_PAGE.
When true, query cursor is closed automatically.
DataOutputStream out = new DataOutputStream(socket.getOutputStream());

// Request header
writeRequestHeader(8, OP_QUERY_SQL_CURSOR_GET_PAGE, 1, out);

// Cursor Id (received from Sql query operation)
writeLongLittleEndian(cursorId, out);
// Read result
DataInputStream in = new DataInputStream(socket.getInputStream());

// Response header
readResponseHeader(in);

int rowCount = readIntLittleEndian(in);

// Read entries (as user objects)
for (int i = 0; i < rowCount; i++){
  Object key = readDataObject(in);
  Object val = readDataObject(in);

  System.out.println("CacheEntry: " + key + ", " + val);
}

boolean moreResults = readBooleanLittleEndian(in);

OP_QUERY_SQL_FIELDS

Performs SQL fields query.

Request TypeDescription
HeaderRequest header.
intCache ID: Java-style hash code of the cache name.
byteUse 0. This field is deprecated and will be removed in the future.
StringSchema for the query; can be null, in which case default PUBLIC schema will be used.
intQuery cursor page size.
intMax rows.
StringSQL
intArgument count.
Data Object

Query argument.

Repeat for as many times as the query argument count that is passed in the previous parameter.

byteStatement type.
ANY = 0
SELECT = 1
UPDATE = 2
boolDistributed joins
boolLocal query.
boolReplicated only - Whether query contains only replicated tables or not.
boolEnforce join order.
boolCollocated - Whether your data is co-located or not.
boolLazy query execution.
longTimeout (milliseconds).
boolInclude field names.
Response TypeDescription
HeaderResponse header.
longCursor id. Can be closed with OP_RESOURCE_CLOSE.
intField (column) count.
String (optional)

Needed only whenIncludeFieldNames is true in the request.

Column name.

Repeat for as many times as the field count that is retrieved in the previous parameter.

intFirst page row count.
Data Object

Column (field) value. Repeat for as many times as the field count.

Repeat for as many times as the row count that is retrieved in the previous parameter.

boolIndicates whether more results are available to be retrieved with OP_QUERY_SQL_FIELDS_CURSOR_GET_PAGE.
String sql = "Select id, salary from Person";
int sqlLength = sql.getBytes("UTF-8").length;

String sqlSchema = "PUBLIC";
int sqlSchemaLength = sqlSchema.getBytes("UTF-8").length;

DataOutputStream out = new DataOutputStream(socket.getOutputStream());

// Request header
writeRequestHeader(43 + sqlLength + sqlSchemaLength, OP_QUERY_SQL_FIELDS, 1, out);

// Cache id
String queryCacheName = "personCache";
int cacheId = queryCacheName.hashCode();
writeIntLittleEndian(cacheId, out);

// Flag = none
writeByteLittleEndian(0, out);

// Schema
writeByteLittleEndian(9, out);
writeIntLittleEndian(sqlSchemaLength, out);
out.writeBytes(sqlSchema); //sqlSchemaLength

// cursor page size
writeIntLittleEndian(2, out);

// Max Rows
writeIntLittleEndian(5, out);

// SQL query
writeByteLittleEndian(9, out);
writeIntLittleEndian(sqlLength, out);
out.writeBytes(sql);//sqlLength

// Argument count
writeIntLittleEndian(0, out);

// Statement type
writeByteLittleEndian(1, out);

// Joins
out.writeBoolean(false);

// Local query
out.writeBoolean(false);

// Replicated
out.writeBoolean(false);

// Enforce join order
out.writeBoolean(false);

// collocated
out.writeBoolean(false);

// Lazy
out.writeBoolean(false);

// Timeout
writeLongLittleEndian(5000, out);

// Replicated
out.writeBoolean(false);
// Read result
DataInputStream in = new DataInputStream(socket.getInputStream());

// Response header
readResponseHeader(in);

long cursorId = readLongLittleEndian(in);

int colCount = readIntLittleEndian(in);

int rowCount = readIntLittleEndian(in);

// Read entries
for (int i = 0; i < rowCount; i++) {
  long id = (long) readDataObject(in);
  int salary = (int) readDataObject(in);

  System.out.println("Person id: " + id + "; Person Salary: " + salary);
}

boolean moreResults = readBooleanLittleEndian(in);

OP_QUERY_SQL_FIELDS_CURSOR_GET_PAGE

Retrieves the next query result page by cursor id from OP_QUERY_SQL_FIELDS .

Request TypeDescription
HeaderRequest header.
longCursor id received from OP_QUERY_SQL_FIELDS
Response TypeDescription
HeaderResponse header.
intRow count.
Data Object

Column (field) value. Repeat for as many times as the field count.

Repeat for as many times as the row count that is retrieved in the previous parameter.

boolIndicates whether more results are available to be retrieved with OP_QUERY_SQL_FIELDS_CURSOR_GET_PAGE
DataOutputStream out = new DataOutputStream(socket.getOutputStream());

// Request header
writeRequestHeader(8, QUERY_SQL_FIELDS_CURSOR_GET_PAGE, 1, out);

// Cursor Id
writeLongLittleEndian(1, out);
// Read result
DataInputStream in = new DataInputStream(socket.getInputStream());

// Response header
readResponseHeader(in);

int rowCount = readIntLittleEndian(in);

// Read entries (as user objects)
for (int i = 0; i < rowCount; i++){
   // read data objects * column count.
}

boolean moreResults = readBooleanLittleEndian(in);

OP_QUERY_SCAN

Performs scan query.

Request TypeDescription
HeaderRequest header.
intCache ID: Java-style hash code of the cache name.
byteFlag. Pass 0 for default, or 1 to keep the value in binary form.
Data ObjectFilter object. Can be null if you are not going to filter data on the cluster. The filter class has to be added to the classpath of the server nodes.
byte

Filter platform:
JAVA = 1
DOTNET = 2
CPP = 3

Pass this parameter only if filter object is not null.

intCursor page size.
intNumber of partitions to query (negative to query entire cache).
boolLocal flag - whether this query should be executed on local node only.
Response TypeDescription
HeaderResponse header.
longCursor id.
intRow count.
Key Data Object + Value Data Object

Records in the form of key-value pairs.

Repeat for as many times as the row count obtained in the previous parameter.

boolIndicates whether more results are available to be fetched with OP_QUERY_SCAN_CURSOR_GET_PAGE.
When true, query cursor is closed automatically.
DataOutputStream out = new DataOutputStream(socket.getOutputStream());

// Request header
writeRequestHeader(15, OP_QUERY_SCAN, 1, out);

// Cache id
String queryCacheName = "personCache";
writeIntLittleEndian(queryCacheName.hashCode(), out);

// flags
writeByteLittleEndian(0, out);

// Filter Object
writeByteLittleEndian(101, out); // null

// Cursor page size
writeIntLittleEndian(1, out);

// Partition to query
writeIntLittleEndian(-1, out);

// local flag
out.writeBoolean(false);
// Read result
DataInputStream in = new DataInputStream(socket.getInputStream());

//Response header
readResponseHeader(in);

// Cursor id
long cursorId = readLongLittleEndian(in);

int rowCount = readIntLittleEndian(in);

// Read entries (as user objects)
for (int i = 0; i < rowCount; i++) {
  Object key = readDataObject(in);
  Object val = readDataObject(in);

  System.out.println("CacheEntry: " + key + ", " + val);
}

boolean moreResults = readBooleanLittleEndian(in);

OP_QUERY_SCAN_CURSOR_GET_PAGE

Fetches the next SQL query cursor page by cursor id that is obtained from OP_QUERY_SCAN.

Request TypeDescription
HeaderRequest header.
longCursor id.
Response TypeDescription
HeaderResponse header.
longCursor id.
longRow count.
Key Data Object + Value Data Object

Records in the form of key-value pairs.

Repeat for as many times as the row count obtained in the previous parameter.

boolIndicates whether more results are available to be fetched with OP_QUERY_SCAN_CURSOR_GET_PAGE.
When true, query cursor is closed automatically.

OP_RESOURCE_CLOSE

Closes a resource, such as query cursor.

Request TypeDescription
HeaderRequest header.
longResource id.
Response TypeDescription
HeaderResponse header
DataOutputStream out = new DataOutputStream(socket.getOutputStream());

// Request header
writeRequestHeader(8, OP_RESOURCE_CLOSE, 1, out);

// Resource id
long cursorId = 1;
writeLongLittleEndian(cursorId, out);
// Read result
DataInputStream in = new DataInputStream(socket.getInputStream());

// Response header
readResponseHeader(in);