SQL-запросы и Scan Queries#
Коды операций#
После успешного подтверждения подключения к узлу сервера DataGrid клиент может выполнять различные SQL-запросы и запросы сканирования. Клиент отправляет запрос (подробнее о структуре запросов и ответов написано в разделах ниже) с конкретным кодом операции:
Операция |
Код операции |
|---|---|
|
2002 |
|
2003 |
|
2004 |
|
2005 |
|
2000 |
|
2001 |
|
0 |
Указанные выше коды операций являются частью заголовка запроса — подробнее написано в подразделе «Стандартный заголовок сообщения» раздела «Обзор бинарного протокола клиента».
Пользовательские методы, которые используются при реализации примеров фрагментов кода ниже
В некоторых примерах кода ниже используются:
метод
readDataObject(), который описан в подразделе «Объекты данных» раздела «Обзор бинарного протокола клиента»;методы, которые используют порядок байтов little-endian для чтения и записи значений, состоящих из нескольких байтов — они включены в раздел «Формат данных».
OP_QUERY_SQL#
Выполняет SQL-запрос к данным, которые хранятся в кластере. Запрос возвращает запись целиком (ключ и значение).
Тип поля запроса |
Описание |
|---|---|
|
Заголовок запроса |
|
Идентификатор кеша; хеш-код имени кеша в Java-стиле |
|
Используйте |
|
Название типа или SQL-таблицы |
|
Строка SQL-запроса |
|
Количество аргументов запроса |
|
Аргумент запроса. |
|
Распределенные присоединения |
|
Локальный запрос |
|
Только реплицированный: содержит ли запрос только реплицированные таблицы или нет |
|
Размер страницы курсора |
|
Тайм-аут в миллисекундах. |
Ответ включает первую страницу результатов:
Тип поля ответа |
Описание |
|---|---|
|
Заголовок ответа |
|
Идентификатор курсора. Можно закрыть с помощью |
|
Количество строк на первой странице |
|
Записи в формате пар «ключ-значение». |
|
Указывает, доступны ли дополнительные результаты для извлечения с помощью |
Пример запроса:
String entityName = "Person";
int entityNameLength = getStrLen(entityName); // Байты в кодировке UTF-8.
String sql = "Select * from Person";
int sqlLength = getStrLen(sql);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// Заголовок запроса.
writeRequestHeader(34 + entityNameLength + sqlLength, OP_QUERY_SQL, 1, out);
// Идентификатор кеша.
String queryCacheName = "personCache";
writeIntLittleEndian(queryCacheName.hashCode(), out);
// Нет флагов.
writeByteLittleEndian(0, out);
// Query Entity.
writeString(entityName, out);
// SQL-запрос.
writeString(sql, out);
// Количество аргументов.
writeIntLittleEndian(0, out);
// Присоединения.
out.writeBoolean(false);
// Локальный запрос.
out.writeBoolean(false);
// Реплицированный.
out.writeBoolean(false);
// Размер страницы курсора.
writeIntLittleEndian(1, out);
// Тайм-аут.
writeLongLittleEndian(5000, out);
Пример ответа:
// Прочитать результат.
DataInputStream in = new DataInputStream(socket.getInputStream());
// Заголовок ответа.
readResponseHeader(in);
long cursorId = readLongLittleEndian(in);
int rowCount = readIntLittleEndian(in);
// Прочитать записи как пользовательские объекты.
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#
Извлекает следующую страницу курсора SQL-запроса по идентификатору курсора из OP_QUERY_SQL.
Тип поля запроса |
Описание |
|---|---|
|
Заголовок запроса |
|
Идентификатор курсора |
Формат ответа выглядит так:
Тип поля ответа |
Описание |
|---|---|
|
Заголовок ответа |
|
Идентификатор курсора |
|
Количество строк |
|
Записи в формате пар «ключ-значение». |
|
Указывает, доступны ли дополнительные результаты для извлечения с помощью |
Пример запроса:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// Заголовок запроса.
writeRequestHeader(8, OP_QUERY_SQL_CURSOR_GET_PAGE, 1, out);
// Идентификатор курсора (получен из операции SQL-запроса).
writeLongLittleEndian(cursorId, out);
Пример ответа:
// Прочитать результат.
DataInputStream in = new DataInputStream(socket.getInputStream());
// Заголовок ответа.
readResponseHeader(in);
int rowCount = readIntLittleEndian(in);
// Прочитать записи как пользовательские объекты.
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#
Выполняет SQL-запрос по полям.
Тип поля запроса |
Описание |
|---|---|
|
Заголовок запроса |
|
Идентификатор кеша; хеш-код имени кеша в Java-стиле |
|
Используйте |
|
Схема для запроса; может принимать значение |
|
Размер страницы курсора запроса |
|
Максимальное количество строк |
|
SQL-запрос |
|
Количество аргументов |
|
Аргумент запроса. |
|
Тип запроса: |
|
Распределенные присоединения |
|
Локальный запрос |
|
Только реплицированный: содержит ли запрос только реплицированные таблицы или нет |
|
Обеспечивает соблюдение порядка присоединения |
|
Коллоцированный: коллоцированы данные или нет |
|
Ленивое (lazy) выполнение запроса |
|
Тайм-аут в миллисекундах |
|
Включает названия полей |
Тип поля ответа |
Описание |
|---|---|
|
Заголовок ответа |
|
Идентификатор курсора. Можно закрыть с помощью |
|
Количество полей (столбцов) |
|
Требуется, только если в запросе для параметра |
|
Количество строк на первой странице. Значение столбца (поля) объекта данных. Повторяется столько раз, сколько полей указано. |
|
Указывает, доступны ли дополнительные результаты для извлечения с помощью |
Пример запроса:
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());
// Заголовок запроса.
writeRequestHeader(43 + sqlLength + sqlSchemaLength, OP_QUERY_SQL_FIELDS, 1, out);
// Идентификатор кеша.
String queryCacheName = "personCache";
int cacheId = queryCacheName.hashCode();
writeIntLittleEndian(cacheId, out);
// Нет флагов.
writeByteLittleEndian(0, out);
// Схема.
writeByteLittleEndian(9, out);
writeIntLittleEndian(sqlSchemaLength, out);
out.writeBytes(sqlSchema); //`sqlSchemaLength`.
// Размер страницы курсора.
writeIntLittleEndian(2, out);
// Максимальное количество строк.
writeIntLittleEndian(5, out);
// SQL-запрос.
writeByteLittleEndian(9, out);
writeIntLittleEndian(sqlLength, out);
out.writeBytes(sql);//`sqlLength`.
// Количество аргументов.
writeIntLittleEndian(0, out);
// Тип запроса.
writeByteLittleEndian(1, out);
// Присоединения.
out.writeBoolean(false);
// Локальный запрос.
out.writeBoolean(false);
// Реплицированный.
out.writeBoolean(false);
// Обеспечивает соблюдение порядка присоединения.
out.writeBoolean(false);
// Коллоцированный.
out.writeBoolean(false);
// Ленивое (lazy) выполнение запроса.
out.writeBoolean(false);
// Тайм-аут.
writeLongLittleEndian(5000, out);
// Реплицированный.
out.writeBoolean(false);
Пример ответа:
// Прочитать результат.
DataInputStream in = new DataInputStream(socket.getInputStream());
// Заголовок ответа.
readResponseHeader(in);
long cursorId = readLongLittleEndian(in);
int colCount = readIntLittleEndian(in);
int rowCount = readIntLittleEndian(in);
// Прочитать записи.
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#
Извлекает следующую страницу результатов запроса по идентификатору курсора из OP_QUERY_SQL_FIELDS.
Тип поля запроса |
Описание |
|---|---|
|
Заголовок запроса |
|
Идентификатор курсора, который получен из |
Тип поля ответа |
Описание |
|---|---|
|
Заголовок ответа |
|
Количество строк |
|
Значение столбца (поля). Повторяется столько раз, сколько полей указано. |
|
Указывает, доступны ли дополнительные результаты для извлечения с помощью |
Пример запроса:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// Заголовок запроса.
writeRequestHeader(8, QUERY_SQL_FIELDS_CURSOR_GET_PAGE, 1, out);
// Идентификатор курсора.
writeLongLittleEndian(1, out);
Пример ответа:
// Прочитать результаты.
DataInputStream in = new DataInputStream(socket.getInputStream());
// Заголовок ответа.
readResponseHeader(in);
int rowCount = readIntLittleEndian(in);
// Прочитать записи как пользовательские объекты.
for (int i = 0; i < rowCount; i++){
// Прочитать произведение объектов и столбцов.
}
boolean moreResults = readBooleanLittleEndian(in);
OP_QUERY_SCAN#
Выполняет scan queries (запросы сканирования).
Тип поля запроса |
Описание |
|---|---|
|
Заголовок запроса |
|
Идентификатор кеша; хеш-код имени кеша в Java-стиле |
|
Флаг. Передайте |
|
Объект фильтра. Если не нужно фильтровать данные в кластере, установите значение |
|
Платформа фильтра: |
|
Размер страницы курсора |
|
Количество запрашиваемых партиций (если значение отрицательное, выполнится запрос всего кеша) |
|
Локальный флаг: должен ли этот запрос выполняться только на локальном узле |
Тип поля ответа |
Описание |
|---|---|
|
Заголовок ответа |
|
Идентификатор курсора |
|
Количество строк |
|
Записи в формате пар «ключ-значение». |
|
Указывает, доступны ли дополнительные результаты для извлечения с помощью |
Пример запроса:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// Заголовок запроса.
writeRequestHeader(15, OP_QUERY_SCAN, 1, out);
// Идентификатор кеша.
String queryCacheName = "personCache";
writeIntLittleEndian(queryCacheName.hashCode(), out);
// Флаги.
writeByteLittleEndian(0, out);
// Объект фильтра.
writeByteLittleEndian(101, out); // `NULL`.
// Размер страницы курсора.
writeIntLittleEndian(1, out);
// Количество запрашиваемых партиций.
writeIntLittleEndian(-1, out);
// Локальный флаг.
out.writeBoolean(false);
Пример ответа:
// Прочитать результат.
DataInputStream in = new DataInputStream(socket.getInputStream());
// Заголовок ответа.
readResponseHeader(in);
// Идентификатор курсора.
long cursorId = readLongLittleEndian(in);
int rowCount = readIntLittleEndian(in);
// Прочитать записи как пользовательские объекты.
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#
Получает следующую страницу курсора SQL-запроса по идентификатору курсора, который получен из OP_QUERY_SCAN.
Тип поля запроса |
Описание |
|---|---|
|
Заголовок запроса |
|
Идентификатор курсора |
Тип поля ответа |
Описание |
|---|---|
|
Заголовок ответа |
|
Идентификатор курсора |
|
Количество строк |
|
Записи в формате пар «ключ-значение». |
|
Указывает, доступны ли дополнительные результаты для извлечения с помощью |
OP_RESOURCE_CLOSE#
Закрывает ресурс, например курсор запроса.
Тип поля запроса |
Описание |
|---|---|
|
Заголовок запроса |
|
Идентификатор ресурса |
Тип поля ответа |
Описание |
|---|---|
|
Заголовок ответа |
Пример запроса:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// Заголовок запроса.
writeRequestHeader(8, OP_RESOURCE_CLOSE, 1, out);
// Идентификатор ресурса.
long cursorId = 1;
writeLongLittleEndian(cursorId, out);
Пример ответа:
// Прочитать результат.
DataInputStream in = new DataInputStream(socket.getInputStream());
// Заголовок ответа.
readResponseHeader(in);