c/driver/common/utils.c (791 lines of code) (raw):
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "utils.h"
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
static size_t kErrorBufferSize = 256;
static void ReleaseError(struct AdbcError* error) {
free(error->message);
error->message = NULL;
error->release = NULL;
}
void SetError(struct AdbcError* error, const char* format, ...) {
if (!error) return;
if (error->release) {
// TODO: combine the errors if possible
error->release(error);
}
error->message = malloc(kErrorBufferSize);
if (!error->message) return;
error->release = &ReleaseError;
va_list args;
va_start(args, format);
vsnprintf(error->message, kErrorBufferSize, format, args);
va_end(args);
}
struct SingleBatchArrayStream {
struct ArrowSchema schema;
struct ArrowArray batch;
};
static const char* SingleBatchArrayStreamGetLastError(struct ArrowArrayStream* stream) {
return NULL;
}
static int SingleBatchArrayStreamGetNext(struct ArrowArrayStream* stream,
struct ArrowArray* batch) {
if (!stream || !stream->private_data) return EINVAL;
struct SingleBatchArrayStream* impl =
(struct SingleBatchArrayStream*)stream->private_data;
memcpy(batch, &impl->batch, sizeof(*batch));
memset(&impl->batch, 0, sizeof(*batch));
return 0;
}
static int SingleBatchArrayStreamGetSchema(struct ArrowArrayStream* stream,
struct ArrowSchema* schema) {
if (!stream || !stream->private_data) return EINVAL;
struct SingleBatchArrayStream* impl =
(struct SingleBatchArrayStream*)stream->private_data;
return ArrowSchemaDeepCopy(&impl->schema, schema);
}
static void SingleBatchArrayStreamRelease(struct ArrowArrayStream* stream) {
if (!stream || !stream->private_data) return;
struct SingleBatchArrayStream* impl =
(struct SingleBatchArrayStream*)stream->private_data;
impl->schema.release(&impl->schema);
if (impl->batch.release) impl->batch.release(&impl->batch);
free(impl);
memset(stream, 0, sizeof(*stream));
}
AdbcStatusCode BatchToArrayStream(struct ArrowArray* values, struct ArrowSchema* schema,
struct ArrowArrayStream* stream,
struct AdbcError* error) {
if (!values->release) {
SetError(error, "ArrowArray is not initialized");
return ADBC_STATUS_INTERNAL;
} else if (!schema->release) {
SetError(error, "ArrowSchema is not initialized");
return ADBC_STATUS_INTERNAL;
} else if (stream->release) {
SetError(error, "ArrowArrayStream is already initialized");
return ADBC_STATUS_INTERNAL;
}
struct SingleBatchArrayStream* impl =
(struct SingleBatchArrayStream*)malloc(sizeof(*impl));
memcpy(&impl->schema, schema, sizeof(*schema));
memcpy(&impl->batch, values, sizeof(*values));
memset(schema, 0, sizeof(*schema));
memset(values, 0, sizeof(*values));
stream->private_data = impl;
stream->get_last_error = SingleBatchArrayStreamGetLastError;
stream->get_next = SingleBatchArrayStreamGetNext;
stream->get_schema = SingleBatchArrayStreamGetSchema;
stream->release = SingleBatchArrayStreamRelease;
return ADBC_STATUS_OK;
}
int StringBuilderInit(struct StringBuilder* builder, size_t initial_size) {
builder->buffer = (char*)malloc(initial_size);
if (builder->buffer == NULL) return errno;
builder->size = 0;
builder->capacity = initial_size;
return 0;
}
int StringBuilderAppend(struct StringBuilder* builder, const char* fmt, ...) {
va_list argptr;
int bytes_available = builder->capacity - builder->size;
va_start(argptr, fmt);
int n = vsnprintf(builder->buffer + builder->size, bytes_available, fmt, argptr);
va_end(argptr);
if (n < 0) {
return errno;
} else if (n >= bytes_available) { // output was truncated
int bytes_needed = n - bytes_available + 1;
builder->buffer = (char*)realloc(builder->buffer, builder->capacity + bytes_needed);
if (builder->buffer == NULL) return errno;
builder->capacity += bytes_needed;
va_start(argptr, fmt);
int ret = vsnprintf(builder->buffer + builder->size, n + 1, fmt, argptr);
if (ret < 0) {
va_end(argptr);
return errno;
}
va_end(argptr);
}
builder->size += n;
return 0;
}
void StringBuilderReset(struct StringBuilder* builder) {
if (builder->buffer) {
free(builder->buffer);
}
memset(builder, 0, sizeof(*builder));
}
AdbcStatusCode AdbcInitConnectionGetInfoSchema(const uint32_t* info_codes,
size_t info_codes_length,
struct ArrowSchema* schema,
struct ArrowArray* array,
struct AdbcError* error) {
// TODO: use C equivalent of UniqueSchema to avoid incomplete schema
// on error
ArrowSchemaInit(schema);
CHECK_NA(INTERNAL, ArrowSchemaSetTypeStruct(schema, /*num_columns=*/2), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(schema->children[0], NANOARROW_TYPE_UINT32),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(schema->children[0], "info_name"), error);
schema->children[0]->flags &= ~ARROW_FLAG_NULLABLE;
struct ArrowSchema* info_value = schema->children[1];
CHECK_NA(INTERNAL, ArrowSchemaSetTypeUnion(info_value, NANOARROW_TYPE_DENSE_UNION, 6),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(info_value, "info_value"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(info_value->children[0], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(info_value->children[0], "string_value"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(info_value->children[1], NANOARROW_TYPE_BOOL),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(info_value->children[1], "bool_value"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(info_value->children[2], NANOARROW_TYPE_INT64),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(info_value->children[2], "int64_value"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(info_value->children[3], NANOARROW_TYPE_INT32),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(info_value->children[3], "int32_bitmask"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(info_value->children[4], NANOARROW_TYPE_LIST),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(info_value->children[4], "string_list"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(info_value->children[5], NANOARROW_TYPE_MAP),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(info_value->children[5], "int32_to_int32_list_map"), error);
CHECK_NA(
INTERNAL,
ArrowSchemaSetType(info_value->children[4]->children[0], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(info_value->children[5]->children[0]->children[0],
NANOARROW_TYPE_INT32),
error);
info_value->children[5]->children[0]->children[0]->flags &= ~ARROW_FLAG_NULLABLE;
CHECK_NA(INTERNAL,
ArrowSchemaSetType(info_value->children[5]->children[0]->children[1],
NANOARROW_TYPE_LIST),
error);
CHECK_NA(
INTERNAL,
ArrowSchemaSetType(info_value->children[5]->children[0]->children[1]->children[0],
NANOARROW_TYPE_INT32),
error);
struct ArrowError na_error = {0};
CHECK_NA_DETAIL(INTERNAL, ArrowArrayInitFromSchema(array, schema, &na_error), &na_error,
error);
CHECK_NA(INTERNAL, ArrowArrayStartAppending(array), error);
return ADBC_STATUS_OK;
} // NOLINT(whitespace/indent)
AdbcStatusCode AdbcConnectionGetInfoAppendString(struct ArrowArray* array,
uint32_t info_code,
const char* info_value,
struct AdbcError* error) {
CHECK_NA(INTERNAL, ArrowArrayAppendUInt(array->children[0], info_code), error);
// Append to type variant
struct ArrowStringView value = ArrowCharView(info_value);
CHECK_NA(INTERNAL, ArrowArrayAppendString(array->children[1]->children[0], value),
error);
// Append type code/offset
CHECK_NA(INTERNAL, ArrowArrayFinishUnionElement(array->children[1], /*type_id=*/0),
error);
return ADBC_STATUS_OK;
}
AdbcStatusCode AdbcInitConnectionObjectsSchema(struct ArrowSchema* schema,
struct AdbcError* error) {
ArrowSchemaInit(schema);
CHECK_NA(INTERNAL, ArrowSchemaSetTypeStruct(schema, /*num_columns=*/2), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(schema->children[0], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(schema->children[0], "catalog_name"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(schema->children[1], NANOARROW_TYPE_LIST), error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(schema->children[1], "catalog_db_schemas"),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetTypeStruct(schema->children[1]->children[0], 2),
error);
struct ArrowSchema* db_schema_schema = schema->children[1]->children[0];
CHECK_NA(INTERNAL,
ArrowSchemaSetType(db_schema_schema->children[0], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(db_schema_schema->children[0], "db_schema_name"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(db_schema_schema->children[1], NANOARROW_TYPE_LIST), error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(db_schema_schema->children[1], "db_schema_tables"), error);
CHECK_NA(INTERNAL,
ArrowSchemaSetTypeStruct(db_schema_schema->children[1]->children[0], 4),
error);
struct ArrowSchema* table_schema = db_schema_schema->children[1]->children[0];
CHECK_NA(INTERNAL, ArrowSchemaSetType(table_schema->children[0], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(table_schema->children[0], "table_name"), error);
table_schema->children[0]->flags &= ~ARROW_FLAG_NULLABLE;
CHECK_NA(INTERNAL, ArrowSchemaSetType(table_schema->children[1], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(table_schema->children[1], "table_type"), error);
table_schema->children[1]->flags &= ~ARROW_FLAG_NULLABLE;
CHECK_NA(INTERNAL, ArrowSchemaSetType(table_schema->children[2], NANOARROW_TYPE_LIST),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(table_schema->children[2], "table_columns"),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetTypeStruct(table_schema->children[2]->children[0], 19),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(table_schema->children[3], NANOARROW_TYPE_LIST),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(table_schema->children[3], "table_constraints"),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetTypeStruct(table_schema->children[3]->children[0], 4),
error);
struct ArrowSchema* column_schema = table_schema->children[2]->children[0];
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[0], NANOARROW_TYPE_STRING), error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[0], "column_name"),
error);
column_schema->children[0]->flags &= ~ARROW_FLAG_NULLABLE;
CHECK_NA(INTERNAL, ArrowSchemaSetType(column_schema->children[1], NANOARROW_TYPE_INT32),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[1], "ordinal_position"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[2], NANOARROW_TYPE_STRING), error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[2], "remarks"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(column_schema->children[3], NANOARROW_TYPE_INT16),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[3], "xdbc_data_type"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[4], NANOARROW_TYPE_STRING), error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[4], "xdbc_type_name"),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(column_schema->children[5], NANOARROW_TYPE_INT32),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[5], "xdbc_column_size"),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(column_schema->children[6], NANOARROW_TYPE_INT16),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(column_schema->children[6], "xdbc_decimal_digits"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(column_schema->children[7], NANOARROW_TYPE_INT16),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(column_schema->children[7], "xdbc_num_prec_radix"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(column_schema->children[8], NANOARROW_TYPE_INT16),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[8], "xdbc_nullable"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[9], NANOARROW_TYPE_STRING), error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[9], "xdbc_column_def"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[10], NANOARROW_TYPE_INT16), error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(column_schema->children[10], "xdbc_sql_data_type"), error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[11], NANOARROW_TYPE_INT16), error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[11], "xdbc_datetime_sub"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[12], NANOARROW_TYPE_INT32), error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(column_schema->children[12], "xdbc_char_octet_length"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[13], NANOARROW_TYPE_STRING), error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[13], "xdbc_is_nullable"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[14], NANOARROW_TYPE_STRING), error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(column_schema->children[14], "xdbc_scope_catalog"), error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[15], NANOARROW_TYPE_STRING), error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[15], "xdbc_scope_schema"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(column_schema->children[16], NANOARROW_TYPE_STRING), error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(column_schema->children[16], "xdbc_scope_table"),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(column_schema->children[17], NANOARROW_TYPE_BOOL),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(column_schema->children[17], "xdbc_is_autoincrement"),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(column_schema->children[18], NANOARROW_TYPE_BOOL),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(column_schema->children[18], "xdbc_is_generatedcolumn"),
error);
struct ArrowSchema* constraint_schema = table_schema->children[3]->children[0];
CHECK_NA(INTERNAL,
ArrowSchemaSetType(constraint_schema->children[0], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(constraint_schema->children[0], "constraint_name"), error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(constraint_schema->children[1], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(constraint_schema->children[1], "constraint_type"), error);
constraint_schema->children[1]->flags &= ~ARROW_FLAG_NULLABLE;
CHECK_NA(INTERNAL,
ArrowSchemaSetType(constraint_schema->children[2], NANOARROW_TYPE_LIST),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(constraint_schema->children[2], "constraint_column_names"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetType(constraint_schema->children[2]->children[0],
NANOARROW_TYPE_STRING),
error);
constraint_schema->children[2]->flags &= ~ARROW_FLAG_NULLABLE;
CHECK_NA(INTERNAL,
ArrowSchemaSetType(constraint_schema->children[3], NANOARROW_TYPE_LIST),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetName(constraint_schema->children[3], "constraint_column_usage"),
error);
CHECK_NA(INTERNAL,
ArrowSchemaSetTypeStruct(constraint_schema->children[3]->children[0], 4),
error);
struct ArrowSchema* usage_schema = constraint_schema->children[3]->children[0];
CHECK_NA(INTERNAL, ArrowSchemaSetType(usage_schema->children[0], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(usage_schema->children[0], "fk_catalog"), error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(usage_schema->children[1], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(usage_schema->children[1], "fk_db_schema"),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetType(usage_schema->children[2], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(usage_schema->children[2], "fk_table"), error);
usage_schema->children[2]->flags &= ~ARROW_FLAG_NULLABLE;
CHECK_NA(INTERNAL, ArrowSchemaSetType(usage_schema->children[3], NANOARROW_TYPE_STRING),
error);
CHECK_NA(INTERNAL, ArrowSchemaSetName(usage_schema->children[3], "fk_column_name"),
error);
usage_schema->children[3]->flags &= ~ARROW_FLAG_NULLABLE;
return ADBC_STATUS_OK;
}
struct AdbcGetObjectsData* AdbcGetObjectsDataInit(struct ArrowArrayView* array_view) {
struct AdbcGetObjectsData* get_objects_data =
(struct AdbcGetObjectsData*)calloc(1, sizeof(struct AdbcGetObjectsData));
if (get_objects_data == NULL) {
return NULL;
}
get_objects_data->catalog_name_array = array_view->children[0];
get_objects_data->catalog_schemas_array = array_view->children[1];
get_objects_data->n_catalogs = 0;
struct ArrowArrayView* catalog_db_schemas_items =
get_objects_data->catalog_schemas_array->children[0];
get_objects_data->db_schema_name_array = catalog_db_schemas_items->children[0];
get_objects_data->db_schema_tables_array = catalog_db_schemas_items->children[1];
struct ArrowArrayView* schema_table_items =
get_objects_data->db_schema_tables_array->children[0];
get_objects_data->table_name_array = schema_table_items->children[0];
get_objects_data->table_type_array = schema_table_items->children[1];
get_objects_data->table_columns_array = schema_table_items->children[2];
get_objects_data->table_constraints_array = schema_table_items->children[3];
struct ArrowArrayView* table_columns_items =
get_objects_data->table_columns_array->children[0];
get_objects_data->column_name_array = table_columns_items->children[0];
get_objects_data->column_position_array = table_columns_items->children[1];
get_objects_data->column_remarks_array = table_columns_items->children[2];
get_objects_data->xdbc_data_type_array = table_columns_items->children[3];
get_objects_data->xdbc_type_name_array = table_columns_items->children[4];
get_objects_data->xdbc_column_size_array = table_columns_items->children[5];
get_objects_data->xdbc_decimal_digits_array = table_columns_items->children[6];
get_objects_data->xdbc_num_prec_radix_array = table_columns_items->children[7];
get_objects_data->xdbc_nullable_array = table_columns_items->children[8];
get_objects_data->xdbc_column_def_array = table_columns_items->children[9];
get_objects_data->xdbc_sql_data_type_array = table_columns_items->children[10];
get_objects_data->xdbc_datetime_sub_array = table_columns_items->children[11];
get_objects_data->xdbc_char_octet_length_array = table_columns_items->children[12];
get_objects_data->xdbc_is_nullable_array = table_columns_items->children[13];
get_objects_data->xdbc_scope_catalog_array = table_columns_items->children[14];
get_objects_data->xdbc_scope_schema_array = table_columns_items->children[15];
get_objects_data->xdbc_scope_table_array = table_columns_items->children[16];
get_objects_data->xdbc_is_autoincrement_array = table_columns_items->children[17];
get_objects_data->xdbc_is_generatedcolumn_array = table_columns_items->children[18];
struct ArrowArrayView* table_constraints_items =
get_objects_data->table_constraints_array->children[0];
get_objects_data->constraint_name_array = table_constraints_items->children[0];
get_objects_data->constraint_type_array = table_constraints_items->children[1];
get_objects_data->constraint_column_names_array = table_constraints_items->children[2];
get_objects_data->constraint_column_name_array =
get_objects_data->constraint_column_names_array->children[0];
get_objects_data->constraint_column_usages_array = table_constraints_items->children[3];
struct ArrowArrayView* constraint_column_usage_items =
get_objects_data->constraint_column_usages_array->children[0];
get_objects_data->fk_catalog_array = constraint_column_usage_items->children[0];
get_objects_data->fk_db_schema_array = constraint_column_usage_items->children[1];
get_objects_data->fk_table_array = constraint_column_usage_items->children[2];
get_objects_data->fk_column_name_array = constraint_column_usage_items->children[3];
get_objects_data->catalogs = (struct AdbcGetObjectsCatalog**)calloc(
array_view->array->length, sizeof(struct AdbcGetObjectsCatalog*));
if (get_objects_data->catalogs == NULL) {
goto error_handler;
}
for (int64_t catalog_idx = 0; catalog_idx < array_view->array->length; catalog_idx++) {
struct AdbcGetObjectsCatalog* catalog =
(struct AdbcGetObjectsCatalog*)calloc(1, sizeof(struct AdbcGetObjectsCatalog));
if (catalog == NULL) {
goto error_handler;
}
get_objects_data->catalogs[catalog_idx] = catalog;
get_objects_data->n_catalogs++;
catalog->n_db_schemas = 0;
catalog->catalog_name =
ArrowArrayViewGetStringUnsafe(get_objects_data->catalog_name_array, catalog_idx);
int64_t db_schema_list_start = ArrowArrayViewListChildOffset(
get_objects_data->catalog_schemas_array, catalog_idx);
int64_t db_schema_list_end = ArrowArrayViewListChildOffset(
get_objects_data->catalog_schemas_array, catalog_idx + 1);
int64_t db_schema_len = db_schema_list_end - db_schema_list_start;
if (db_schema_len == 0) {
catalog->catalog_db_schemas = NULL;
} else {
catalog->catalog_db_schemas = (struct AdbcGetObjectsSchema**)calloc(
db_schema_len, sizeof(struct AdbcGetObjectsSchema*));
if (catalog->catalog_db_schemas == NULL) {
goto error_handler;
}
for (int64_t db_schema_index = db_schema_list_start;
db_schema_index < db_schema_list_end; db_schema_index++) {
struct AdbcGetObjectsSchema* schema =
(struct AdbcGetObjectsSchema*)calloc(1, sizeof(struct AdbcGetObjectsSchema));
if (schema == NULL) {
goto error_handler;
}
catalog->catalog_db_schemas[db_schema_index - db_schema_list_start] = schema;
catalog->n_db_schemas++;
schema->n_db_schema_tables = 0;
schema->db_schema_name = ArrowArrayViewGetStringUnsafe(
get_objects_data->db_schema_name_array, db_schema_index);
int64_t table_list_start = ArrowArrayViewListChildOffset(
get_objects_data->db_schema_tables_array, db_schema_index);
int64_t table_list_end = ArrowArrayViewListChildOffset(
get_objects_data->db_schema_tables_array, db_schema_index + 1);
int64_t table_len = table_list_end - table_list_start;
if (table_len == 0) {
schema->db_schema_tables = NULL;
} else {
schema->db_schema_tables = (struct AdbcGetObjectsTable**)calloc(
table_len, sizeof(struct AdbcGetObjectsTable*));
if (schema->db_schema_tables == NULL) {
goto error_handler;
}
for (int64_t table_index = table_list_start; table_index < table_list_end;
table_index++) {
struct AdbcGetObjectsTable* table = (struct AdbcGetObjectsTable*)calloc(
1, sizeof(struct AdbcGetObjectsTable));
if (table == NULL) {
goto error_handler;
}
schema->db_schema_tables[table_index - table_list_start] = table;
schema->n_db_schema_tables++;
table->n_table_columns = 0;
table->n_table_constraints = 0;
table->table_name = ArrowArrayViewGetStringUnsafe(
get_objects_data->table_name_array, table_index);
table->table_type = ArrowArrayViewGetStringUnsafe(
get_objects_data->table_type_array, table_index);
int64_t columns_list_start = ArrowArrayViewListChildOffset(
get_objects_data->table_columns_array, table_index);
int64_t columns_list_end = ArrowArrayViewListChildOffset(
get_objects_data->table_columns_array, table_index + 1);
int64_t columns_len = columns_list_end - columns_list_start;
if (columns_len == 0) {
table->table_columns = NULL;
} else {
table->table_columns = (struct AdbcGetObjectsColumn**)calloc(
columns_len, sizeof(struct AdbcGetObjectsColumn*));
if (table->table_columns == NULL) {
goto error_handler;
}
for (int64_t column_index = columns_list_start;
column_index < columns_list_end; column_index++) {
struct AdbcGetObjectsColumn* column =
(struct AdbcGetObjectsColumn*)calloc(
1, sizeof(struct AdbcGetObjectsColumn));
if (column == NULL) {
goto error_handler;
}
table->table_columns[column_index - columns_list_start] = column;
table->n_table_columns++;
column->column_name = ArrowArrayViewGetStringUnsafe(
get_objects_data->column_name_array, column_index);
column->ordinal_position = ArrowArrayViewGetIntUnsafe(
get_objects_data->column_position_array, column_index);
column->remarks = ArrowArrayViewGetStringUnsafe(
get_objects_data->column_remarks_array, column_index);
column->xdbc_data_type = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_data_type_array, column_index);
column->xdbc_type_name = ArrowArrayViewGetStringUnsafe(
get_objects_data->xdbc_type_name_array, column_index);
column->xdbc_column_size = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_column_size_array, column_index);
column->xdbc_decimal_digits = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_decimal_digits_array, column_index);
column->xdbc_num_prec_radix = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_num_prec_radix_array, column_index);
column->xdbc_nullable = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_nullable_array, column_index);
column->xdbc_column_def = ArrowArrayViewGetStringUnsafe(
get_objects_data->xdbc_column_def_array, column_index);
column->xdbc_sql_data_type = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_sql_data_type_array, column_index);
column->xdbc_datetime_sub = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_datetime_sub_array, column_index);
column->xdbc_char_octet_length = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_char_octet_length_array, column_index);
column->xdbc_scope_catalog = ArrowArrayViewGetStringUnsafe(
get_objects_data->xdbc_scope_catalog_array, column_index);
column->xdbc_scope_schema = ArrowArrayViewGetStringUnsafe(
get_objects_data->xdbc_scope_schema_array, column_index);
column->xdbc_scope_table = ArrowArrayViewGetStringUnsafe(
get_objects_data->xdbc_scope_table_array, column_index);
// TODO: implement a nanoarrow GetBool view here?
column->xdbc_is_autoincrement = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_is_autoincrement_array, column_index);
column->xdbc_is_generatedcolumn = ArrowArrayViewGetIntUnsafe(
get_objects_data->xdbc_is_generatedcolumn_array, column_index);
}
}
int64_t constraints_list_start = ArrowArrayViewListChildOffset(
get_objects_data->table_constraints_array, table_index);
int64_t constraints_list_end = ArrowArrayViewListChildOffset(
get_objects_data->table_constraints_array, table_index + 1);
int64_t constraints_len = constraints_list_end - constraints_list_start;
if (constraints_len == 0) {
table->table_constraints = NULL;
} else {
table->table_constraints = (struct AdbcGetObjectsConstraint**)calloc(
constraints_len, sizeof(struct AdbcGetObjectsConstraint*));
if (table->table_constraints == NULL) {
goto error_handler;
}
for (int64_t constraint_index = constraints_list_start;
constraint_index < constraints_list_end; constraint_index++) {
struct AdbcGetObjectsConstraint* constraint =
(struct AdbcGetObjectsConstraint*)calloc(
1, sizeof(struct AdbcGetObjectsConstraint));
if (constraint == NULL) {
goto error_handler;
}
table->table_constraints[constraint_index - constraints_list_start] =
constraint;
table->n_table_constraints++;
constraint->n_column_names = 0;
constraint->n_column_usages = 0;
constraint->constraint_name = ArrowArrayViewGetStringUnsafe(
get_objects_data->constraint_name_array, constraint_index);
constraint->constraint_type = ArrowArrayViewGetStringUnsafe(
get_objects_data->constraint_type_array, constraint_index);
int64_t constraint_column_names_start = ArrowArrayViewListChildOffset(
get_objects_data->constraint_column_names_array, constraint_index);
int64_t constraint_column_names_end = ArrowArrayViewListChildOffset(
get_objects_data->constraint_column_names_array,
constraint_index + 1);
int64_t constraint_column_names_len =
constraint_column_names_end - constraint_column_names_start;
if (constraint_column_names_len == 0) {
constraint->constraint_column_names = NULL;
} else {
constraint->constraint_column_names = (struct ArrowStringView*)calloc(
constraint_column_names_len, sizeof(struct ArrowStringView));
if (constraint->constraint_column_names == NULL) {
goto error_handler;
}
for (int64_t constraint_column_name_index =
constraint_column_names_start;
constraint_column_name_index < constraint_column_names_end;
constraint_column_name_index++) {
constraint->constraint_column_names[constraint_column_name_index -
constraint_column_names_start] =
ArrowArrayViewGetStringUnsafe(
get_objects_data->constraint_column_name_array,
constraint_column_name_index);
constraint->n_column_names++;
}
}
int64_t constraint_column_usages_start = ArrowArrayViewListChildOffset(
get_objects_data->constraint_column_usages_array, constraint_index);
int64_t constraint_column_usages_end = ArrowArrayViewListChildOffset(
get_objects_data->constraint_column_usages_array,
constraint_index + 1);
int64_t constraint_column_usages_len =
constraint_column_usages_end - constraint_column_usages_start;
if (constraint_column_usages_len == 0) {
constraint->constraint_column_usages = NULL;
} else {
constraint->constraint_column_usages =
(struct AdbcGetObjectsUsage**)calloc(
constraint_column_usages_len,
sizeof(struct AdbcGetObjectsUsage*));
if (constraint->constraint_column_usages == NULL) {
goto error_handler;
}
for (int64_t constraint_column_usage_index =
constraint_column_usages_start;
constraint_column_usage_index < constraint_column_usages_end;
constraint_column_usage_index++) {
struct AdbcGetObjectsUsage* usage =
(struct AdbcGetObjectsUsage*)calloc(
1, sizeof(struct AdbcGetObjectsUsage));
if (usage == NULL) {
goto error_handler;
}
usage->fk_catalog =
ArrowArrayViewGetStringUnsafe(get_objects_data->fk_catalog_array,
constraint_column_usage_index);
usage->fk_db_schema = ArrowArrayViewGetStringUnsafe(
get_objects_data->fk_db_schema_array,
constraint_column_usage_index);
usage->fk_table = ArrowArrayViewGetStringUnsafe(
get_objects_data->fk_table_array, constraint_column_usage_index);
usage->fk_column_name = ArrowArrayViewGetStringUnsafe(
get_objects_data->fk_column_name_array,
constraint_column_usage_index);
constraint->constraint_column_usages[constraint_column_usage_index -
constraint_column_usages_start] =
usage;
constraint->n_column_usages++;
}
}
}
}
}
}
}
}
}
return get_objects_data;
error_handler:
AdbcGetObjectsDataDelete(get_objects_data);
return NULL;
}
void AdbcGetObjectsDataDelete(struct AdbcGetObjectsData* get_objects_data) {
for (int64_t catalog_index = 0; catalog_index < get_objects_data->n_catalogs;
catalog_index++) {
struct AdbcGetObjectsCatalog* catalog = get_objects_data->catalogs[catalog_index];
for (int64_t db_schema_index = 0; db_schema_index < catalog->n_db_schemas;
db_schema_index++) {
struct AdbcGetObjectsSchema* schema = catalog->catalog_db_schemas[db_schema_index];
for (int64_t table_index = 0; table_index < schema->n_db_schema_tables;
table_index++) {
struct AdbcGetObjectsTable* table = schema->db_schema_tables[table_index];
for (int64_t column_index = 0; column_index < table->n_table_columns;
column_index++) {
free(table->table_columns[column_index]);
}
free(table->table_columns);
for (int64_t constraint_index = 0; constraint_index < table->n_table_constraints;
constraint_index++) {
struct AdbcGetObjectsConstraint* constraint =
table->table_constraints[constraint_index];
free(constraint->constraint_column_names);
for (int64_t usage_index = 0; usage_index < constraint->n_column_usages;
usage_index++) {
free(constraint->constraint_column_usages[usage_index]);
}
free(constraint->constraint_column_usages);
free(table->table_constraints[constraint_index]);
}
free(table->table_constraints);
free(table);
}
free(schema->db_schema_tables);
free(schema);
}
free(catalog->catalog_db_schemas);
free(catalog);
}
free(get_objects_data->catalogs);
free(get_objects_data);
}
struct AdbcGetObjectsCatalog* AdbcGetObjectsDataGetCatalogByName(
struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name) {
if (catalog_name != NULL) {
for (int64_t i = 0; i < get_objects_data->n_catalogs; i++) {
struct AdbcGetObjectsCatalog* catalog = get_objects_data->catalogs[i];
struct ArrowStringView name = catalog->catalog_name;
if (!strncmp(name.data, catalog_name, name.size_bytes)) {
return catalog;
}
}
}
return NULL;
}
struct AdbcGetObjectsSchema* AdbcGetObjectsDataGetSchemaByName(
struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name,
const char* const schema_name) {
if (schema_name != NULL) {
struct AdbcGetObjectsCatalog* catalog =
AdbcGetObjectsDataGetCatalogByName(get_objects_data, catalog_name);
if (catalog != NULL) {
for (int64_t i = 0; i < catalog->n_db_schemas; i++) {
struct AdbcGetObjectsSchema* schema = catalog->catalog_db_schemas[i];
struct ArrowStringView name = schema->db_schema_name;
if (!strncmp(name.data, schema_name, name.size_bytes)) {
return schema;
}
}
}
}
return NULL;
}
struct AdbcGetObjectsTable* AdbcGetObjectsDataGetTableByName(
struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name,
const char* const schema_name, const char* const table_name) {
if (table_name != NULL) {
struct AdbcGetObjectsSchema* schema =
AdbcGetObjectsDataGetSchemaByName(get_objects_data, catalog_name, schema_name);
if (schema != NULL) {
for (int64_t i = 0; i < schema->n_db_schema_tables; i++) {
struct AdbcGetObjectsTable* table = schema->db_schema_tables[i];
struct ArrowStringView name = table->table_name;
if (!strncmp(name.data, table_name, name.size_bytes)) {
return table;
}
}
}
}
return NULL;
}
struct AdbcGetObjectsColumn* AdbcGetObjectsDataGetColumnByName(
struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name,
const char* const schema_name, const char* const table_name,
const char* const column_name) {
if (column_name != NULL) {
struct AdbcGetObjectsTable* table = AdbcGetObjectsDataGetTableByName(
get_objects_data, catalog_name, schema_name, table_name);
if (table != NULL) {
for (int64_t i = 0; i < table->n_table_columns; i++) {
struct AdbcGetObjectsColumn* column = table->table_columns[i];
struct ArrowStringView name = column->column_name;
if (!strncmp(name.data, column_name, name.size_bytes)) {
return column;
}
}
}
}
return NULL;
}
struct AdbcGetObjectsConstraint* AdbcGetObjectsDataGetConstraintByName(
struct AdbcGetObjectsData* get_objects_data, const char* const catalog_name,
const char* const schema_name, const char* const table_name,
const char* const constraint_name) {
if (constraint_name != NULL) {
struct AdbcGetObjectsTable* table = AdbcGetObjectsDataGetTableByName(
get_objects_data, catalog_name, schema_name, table_name);
if (table != NULL) {
for (int64_t i = 0; i < table->n_table_constraints; i++) {
struct AdbcGetObjectsConstraint* constraint = table->table_constraints[i];
struct ArrowStringView name = constraint->constraint_name;
if (!strncmp(name.data, constraint_name, name.size_bytes)) {
return constraint;
}
}
}
}
return NULL;
}