AdbcStatusCode StatementReaderInferOneValue()

in c/driver/sqlite/statement_reader.c [973:1126]


AdbcStatusCode StatementReaderInferOneValue(
    sqlite3_stmt* stmt, int col, struct ArrowBitmap* validity, struct ArrowBuffer* data,
    struct ArrowBuffer* binary, enum ArrowType* current_type, struct AdbcError* error) {
  // TODO: static_assert sizeof(int64) == sizeof(double)

  int sqlite_type = sqlite3_column_type(stmt, col);
  switch (sqlite_type) {
    case SQLITE_NULL: {
      ArrowBitmapAppendUnsafe(validity, /*set=*/0, /*length=*/1);
      switch (*current_type) {
        case NANOARROW_TYPE_INT64: {
          int64_t value = 0;
          ArrowBufferAppendUnsafe(data, &value, sizeof(int64_t));
          break;
        }
        case NANOARROW_TYPE_DOUBLE: {
          double value = 0.0;
          ArrowBufferAppendUnsafe(data, &value, sizeof(int64_t));
          break;
        }
        case NANOARROW_TYPE_STRING:
        case NANOARROW_TYPE_BINARY: {
          const int32_t offset = ((int32_t*)data->data)[data->size_bytes / 4 - 1];
          CHECK_NA(INTERNAL, ArrowBufferAppend(data, &offset, sizeof(offset)), error);
          return ADBC_STATUS_OK;
        }
        default:
          return ADBC_STATUS_INTERNAL;
      }
      break;
    }
    case SQLITE_INTEGER: {
      ArrowBitmapAppendUnsafe(validity, /*set=*/1, /*length=*/1);

      switch (*current_type) {
        case NANOARROW_TYPE_INT64: {
          int64_t value = sqlite3_column_int64(stmt, col);
          ArrowBufferAppendUnsafe(data, &value, sizeof(int64_t));
          break;
        }
        case NANOARROW_TYPE_DOUBLE: {
          double value = sqlite3_column_double(stmt, col);
          ArrowBufferAppendUnsafe(data, &value, sizeof(int64_t));
          break;
        }
        case NANOARROW_TYPE_STRING:
        case NANOARROW_TYPE_BINARY: {
          int32_t offset = ((int32_t*)data->data)[data->size_bytes / 4 - 1];
          return StatementReaderAppendInt64ToBinary(
              data, binary, sqlite3_column_int64(stmt, col), &offset, error);
        }
        default:
          return ADBC_STATUS_INTERNAL;
      }
      break;
    }
    case SQLITE_FLOAT: {
      ArrowBitmapAppendUnsafe(validity, /*set=*/1, /*length=*/1);

      switch (*current_type) {
        case NANOARROW_TYPE_INT64: {
          AdbcStatusCode status = StatementReaderUpcastInt64ToDouble(data, error);
          if (status != ADBC_STATUS_OK) return status;
          *current_type = NANOARROW_TYPE_DOUBLE;
          double value = sqlite3_column_double(stmt, col);
          ArrowBufferAppendUnsafe(data, &value, sizeof(double));
          break;
        }
        case NANOARROW_TYPE_DOUBLE: {
          double value = sqlite3_column_double(stmt, col);
          ArrowBufferAppendUnsafe(data, &value, sizeof(double));
          break;
        }
        case NANOARROW_TYPE_STRING:
        case NANOARROW_TYPE_BINARY: {
          int32_t offset = ((int32_t*)data->data)[data->size_bytes / 4 - 1];
          return StatementReaderAppendDoubleToBinary(
              data, binary, sqlite3_column_double(stmt, col), &offset, error);
        }
        default:
          return ADBC_STATUS_INTERNAL;
      }
      break;
    }
    case SQLITE_TEXT: {
      ArrowBitmapAppendUnsafe(validity, /*set=*/1, /*length=*/1);

      switch (*current_type) {
        case NANOARROW_TYPE_INT64: {
          AdbcStatusCode status = StatementReaderUpcastInt64ToBinary(data, binary, error);
          if (status != ADBC_STATUS_OK) return status;
          *current_type = NANOARROW_TYPE_STRING;
          break;
        }
        case NANOARROW_TYPE_DOUBLE: {
          AdbcStatusCode status =
              StatementReaderUpcastDoubleToBinary(data, binary, error);
          if (status != ADBC_STATUS_OK) return status;
          *current_type = NANOARROW_TYPE_STRING;
          break;
        }
        case NANOARROW_TYPE_STRING:
        case NANOARROW_TYPE_BINARY:
          break;
        default:
          return ADBC_STATUS_INTERNAL;
      }

      const unsigned char* value = sqlite3_column_text(stmt, col);
      const int size = sqlite3_column_bytes(stmt, col);
      const int32_t offset = ((int32_t*)data->data)[data->size_bytes / 4 - 1] + size;
      CHECK_NA(INTERNAL, ArrowBufferAppend(binary, value, size), error);
      CHECK_NA(INTERNAL, ArrowBufferAppend(data, &offset, sizeof(offset)), error);
      break;
    }
    case SQLITE_BLOB: {
      ArrowBitmapAppendUnsafe(validity, /*set=*/1, /*length=*/1);

      switch (*current_type) {
        case NANOARROW_TYPE_INT64: {
          AdbcStatusCode status = StatementReaderUpcastInt64ToBinary(data, binary, error);
          if (status != ADBC_STATUS_OK) return status;
          *current_type = NANOARROW_TYPE_BINARY;
          break;
        }
        case NANOARROW_TYPE_DOUBLE: {
          AdbcStatusCode status =
              StatementReaderUpcastDoubleToBinary(data, binary, error);
          if (status != ADBC_STATUS_OK) return status;
          *current_type = NANOARROW_TYPE_BINARY;
          break;
        }
        case NANOARROW_TYPE_STRING:
          *current_type = NANOARROW_TYPE_BINARY;
          break;
        case NANOARROW_TYPE_BINARY:
          break;
        default:
          return ADBC_STATUS_INTERNAL;
      }

      const void* value = sqlite3_column_blob(stmt, col);
      const int size = sqlite3_column_bytes(stmt, col);
      const int32_t offset = ((int32_t*)data->data)[data->size_bytes / 4 - 1] + size;
      CHECK_NA(INTERNAL, ArrowBufferAppend(binary, value, size), error);
      CHECK_NA(INTERNAL, ArrowBufferAppend(data, &offset, sizeof(offset)), error);
      break;
    }
    default: {
      return ADBC_STATUS_NOT_IMPLEMENTED;
    }
  }
  return ADBC_STATUS_OK;
}  // NOLINT(whitespace/indent)