int StatementReaderGetOneValue()

in c/driver/sqlite/statement_reader.c [501:622]


int StatementReaderGetOneValue(struct StatementReader* reader, int col,
                               struct ArrowArray* out) {
  int sqlite_type = sqlite3_column_type(reader->stmt, col);

  if (sqlite_type == SQLITE_NULL) {
    return ArrowArrayAppendNull(out, 1);
  }

  switch (reader->types[col]) {
    case NANOARROW_TYPE_INT64: {
      switch (sqlite_type) {
        case SQLITE_INTEGER: {
          int64_t value = sqlite3_column_int64(reader->stmt, col);
          return ArrowArrayAppendInt(out, value);
        }
        case SQLITE_FLOAT: {
          // TODO: behavior needs to be configurable
          snprintf(reader->error.message, sizeof(reader->error.message),
                   "[SQLite] Type mismatch in column %d: expected INT64 but got DOUBLE",
                   col);
          return EIO;
        }
        case SQLITE_TEXT:
        case SQLITE_BLOB: {
          snprintf(
              reader->error.message, sizeof(reader->error.message),
              "[SQLite] Type mismatch in column %d: expected INT64 but got STRING/BINARY",
              col);
          return EIO;
        }
        default: {
          snprintf(reader->error.message, sizeof(reader->error.message),
                   "[SQLite] Type mismatch in column %d: expected INT64 but got unknown "
                   "type %d",
                   col, sqlite_type);
          return ENOTSUP;
        }
      }
      break;
    }

    case NANOARROW_TYPE_DOUBLE: {
      switch (sqlite_type) {
        case SQLITE_INTEGER:
        case SQLITE_FLOAT: {
          // Let SQLite convert
          double value = sqlite3_column_double(reader->stmt, col);
          return ArrowArrayAppendDouble(out, value);
        }
        case SQLITE_TEXT:
        case SQLITE_BLOB: {
          snprintf(reader->error.message, sizeof(reader->error.message),
                   "[SQLite] Type mismatch in column %d: expected DOUBLE but got "
                   "STRING/BINARY",
                   col);
          return EIO;
        }
        default: {
          snprintf(reader->error.message, sizeof(reader->error.message),
                   "[SQLite] Type mismatch in column %d: expected DOUBLE but got unknown "
                   "type %d",
                   col, sqlite_type);
          return ENOTSUP;
        }
      }
      break;
    }

    case NANOARROW_TYPE_STRING: {
      switch (sqlite_type) {
        case SQLITE_INTEGER:
        case SQLITE_FLOAT:
        case SQLITE_TEXT:
        case SQLITE_BLOB:
          break;
        default: {
          snprintf(reader->error.message, sizeof(reader->error.message),
                   "[SQLite] Type mismatch in column %d: expected STRING but got unknown "
                   "type %d",
                   col, sqlite_type);
          return ENOTSUP;
        }
      }

      // Let SQLite convert
      struct ArrowStringView value = {
          .data = (const char*)sqlite3_column_text(reader->stmt, col),
          .size_bytes = sqlite3_column_bytes(reader->stmt, col),
      };
      return ArrowArrayAppendString(out, value);
    }

    case NANOARROW_TYPE_BINARY: {
      switch (sqlite_type) {
        case SQLITE_TEXT:
        case SQLITE_BLOB:
          break;
        default: {
          snprintf(reader->error.message, sizeof(reader->error.message),
                   "[SQLite] Type mismatch in column %d: expected BLOB but got unknown "
                   "type %d",
                   col, sqlite_type);
          return ENOTSUP;
        }
      }

      // Let SQLite convert
      struct ArrowBufferView value;
      value.data.data = sqlite3_column_blob(reader->stmt, col);
      value.size_bytes = sqlite3_column_bytes(reader->stmt, col);
      return ArrowArrayAppendBytes(out, value);
    }

    default:
      break;
  }

  snprintf(reader->error.message, sizeof(reader->error.message),
           "[SQLite] Internal error: unknown inferred column type %d",
           reader->types[col]);
  return ENOTSUP;
}