Repository: duckdb/duckdb
File: src/storage/table/row_group.cpp (C++)

Code before:
		}

		if (children.empty()) {
			// scan all struct children
			scan_child_column.resize(struct_children.size(), true);
			for (idx_t i = 0; i < struct_children.size(); i++) {
				child_states[i + 1].Initialize(context, struct_children[i].second, options);
			}
		} else {
			if (storage_index.IsPushdownExtract()) {
				scan_child_column.resize(1, true);
				D_ASSERT(children.size() == 1);
				auto &child = children[0];
				auto child_index = child.GetPrimaryIndex();
				child_states[1].Initialize(context, struct_children[child_index].second, child, options);
			} else {
				// only scan the specified subset of columns
				scan_child_column.resize(struct_children.size(), false);
				for (idx_t i = 0; i < children.size(); i++) {
					auto &child = children[i];
					auto index = child.GetPrimaryIndex();
					scan_child_column[index] = true;
					child_states[index + 1].Initialize(context, struct_children[index].second, child, options);
				}
			}
		}
		child_states[0].scan_options = options;
	} else if (type.InternalType() == PhysicalType::LIST) {
		// validity + list child
		for (idx_t i = 0; i < 2; i++) {
			child_states.emplace_back(parent);
		}
		child_states[1].Initialize(context, ListType::GetChildType(type), options);
		child_states[0].scan_options = options;
	} else if (type.InternalType() == PhysicalType::ARRAY) {
		// validity + array child
		for (idx_t i = 0; i < 2; i++) {
			child_states.emplace_back(parent);
		}
		child_states[0].scan_options = options;
		child_states[1].Initialize(context, ArrayType::GetChildType(type), options);
	} else {
		// validity
		child_states.emplace_back(parent);
		child_states[0].scan_options = options;
	}
}

void ColumnScanState::Initialize(const QueryContext &context_p, const LogicalType &type,
                                 optional_ptr<TableScanOptions> options) {
	auto column_id = StorageIndex(0);

Review comment (suggestion):
Maybe we can change the `ColumnScanState::Initialize` API to actually take a `ClientContext` in a follow-up PR? That could prevent subtle errors from happening "sometimes" when the client context is missing. 

Code after:

	if (type.id() == LogicalTypeId::VARIANT) {
		// variant - column scan states are created later
		// this is done because the internal shape of the VARIANT is different per rowgroup
		scan_child_column.resize(2, true);
		return;
	}

	D_ASSERT(child_states.empty());
	if (type.InternalType() == PhysicalType::STRUCT) {
		// validity + struct children
		auto &struct_children = StructType::GetChildTypes(type);
		child_states.reserve(struct_children.size() + 1);
		for (idx_t i = 0; i <= struct_children.size(); i++) {
			child_states.emplace_back(parent);
		}

		if (children.empty()) {
			// scan all struct children
			scan_child_column.resize(struct_children.size(), true);
			for (idx_t i = 0; i < struct_children.size(); i++) {
				child_states[i + 1].Initialize(context, struct_children[i].second, options);
			}
		} else {
			if (storage_index.IsPushdownExtract()) {
				D_ASSERT(context.Valid());
				scan_child_column.resize(1, true);
				D_ASSERT(children.size() == 1);
				auto &child = children[0];
				auto child_index = child.GetPrimaryIndex();
				auto &child_type = StructType::GetChildTypes(type)[child_index].second;
				if (!child.HasChildren() && child_type != child.GetType()) {
					expression_state = CreateCast(*context.GetClientContext(), child_type, child.GetType());
				}
				child_states[1].Initialize(context, struct_children[child_index].second, child, options);
			} else {
				// only scan the specified subset of columns
				scan_child_column.resize(struct_children.size(), false);
				for (idx_t i = 0; i < children.size(); i++) {
					auto &child = children[i];
					auto index = child.GetPrimaryIndex();
					scan_child_column[index] = true;
					child_states[index + 1].Initialize(context, struct_children[index].second, child, options);
				}
			}
		}
		child_states[0].scan_options = options;
	} else if (type.InternalType() == PhysicalType::LIST) {
		// validity + list child
		for (idx_t i = 0; i < 2; i++) {
			child_states.emplace_back(parent);