Repository: duckdb/duckdb
File: tools/pythonpkg/src/pandas/analyzer.cpp (C++)

Code before:
	default:
		throw InternalException("Unsupported PythonObjectType");
	}
}

//! Get the increment for the given sample size
uint64_t PandasAnalyzer::GetSampleIncrement(idx_t rows) {
	//! Apply the maximum
	auto sample = sample_size;
	if (sample > rows) {
		sample = rows;
	}
	if (sample == 0) {
		return rows;
	}
	return rows / sample;
}

LogicalType PandasAnalyzer::InnerAnalyze(py::object column, bool &can_convert, idx_t increment) {
	idx_t rows = py::len(column);

	if (rows == 0) {
		return LogicalType::SQLNULL;
	}
	auto &import_cache = *DuckDBPyConnection::ImportCache();
	auto pandas_series = import_cache.pandas.Series(false);

	// Keys are not guaranteed to start at 0 for Series, use the internal __array__ instead
	if (pandas_series && py::isinstance(column, pandas_series)) {
		// TODO: check if '_values' is more portable, and behaves the same as '__array__()'
		column = column.attr("__array__")();
	}
	auto row = column.attr("__getitem__");

	LogicalType item_type = LogicalType::SQLNULL;
	vector<LogicalType> types;
	for (idx_t i = 0; i < rows; i += increment) {
		auto obj = row(i);
		auto next_item_type = GetItemType(obj, can_convert);
		types.push_back(next_item_type);

		if (!can_convert || !UpgradeType(item_type, next_item_type)) {
			can_convert = false;
			return next_item_type;
		}
	}

	if (can_convert && item_type.id() == LogicalTypeId::STRUCT) {
		can_convert = VerifyStructValidity(types);
	}


Review comment (bug):
Hmm this is now not even attempting to import pandas, which I thought would be correct..

~~Since this is pandas analyze, if pandas wasn't imported by the user - there is nothing to analyze.~~
^ That's incorrect, this does not mean that the *user* hasn't imported pandas, it means *we* haven't imported pandas.

~~But I think that's incorrect, a bit of a misnomer kinda~~

Code after:
	default:
		throw InternalException("Unsupported PythonObjectType");
	}
}

//! Get the increment for the given sample size
uint64_t PandasAnalyzer::GetSampleIncrement(idx_t rows) {
	//! Apply the maximum
	auto sample = sample_size;
	if (sample > rows) {
		sample = rows;
	}
	if (sample == 0) {
		return rows;
	}
	return rows / sample;
}

LogicalType PandasAnalyzer::InnerAnalyze(py::object column, bool &can_convert, idx_t increment) {
	idx_t rows = py::len(column);

	if (rows == 0) {
		return LogicalType::SQLNULL;
	}
	auto &import_cache = *DuckDBPyConnection::ImportCache();
	auto pandas_series = import_cache.pandas.Series();

	// Keys are not guaranteed to start at 0 for Series, use the internal __array__ instead
	if (pandas_series && py::isinstance(column, pandas_series)) {
		// TODO: check if '_values' is more portable, and behaves the same as '__array__()'
		column = column.attr("__array__")();
	}
	auto row = column.attr("__getitem__");

	LogicalType item_type = LogicalType::SQLNULL;
	vector<LogicalType> types;
	for (idx_t i = 0; i < rows; i += increment) {
		auto obj = row(i);
		auto next_item_type = GetItemType(obj, can_convert);
		types.push_back(next_item_type);

		if (!can_convert || !UpgradeType(item_type, next_item_type)) {
			can_convert = false;
			return next_item_type;
		}
	}

	if (can_convert && item_type.id() == LogicalTypeId::STRUCT) {
		can_convert = VerifyStructValidity(types);
	}