| 673 | } |
| 674 | |
| 675 | TableScanDesc deeplake_table_am_routine::scan_begin(Relation relation, |
| 676 | Snapshot snapshot, |
| 677 | int32_t nkeys, |
| 678 | struct ScanKeyData* key, |
| 679 | ParallelTableScanDesc parallel_scan, |
| 680 | uint32_t flags) |
| 681 | { |
| 682 | // Ensure DeepLake is initialized (for processes that bypass planner/executor hooks, |
| 683 | // such as autovacuum workers, parallel workers, or standalone ANALYZE) |
| 684 | pg::init_deeplake(); |
| 685 | |
| 686 | DeeplakeScanData* extended_scan = static_cast<DeeplakeScanData*>(palloc0(sizeof(DeeplakeScanData))); |
| 687 | auto table_id = RelationGetRelid(relation); |
| 688 | bool is_parallel = (pg::use_parallel_workers && parallel_scan != nullptr); |
| 689 | |
| 690 | // Refresh table data BEFORE creating the scan to ensure num_rows is up to date |
| 691 | // (table_scan constructor caches num_rows at construction time) |
| 692 | auto& td_for_refresh = pg::table_storage::instance().get_table_data(table_id); |
| 693 | const_cast<pg::table_data&>(td_for_refresh).refresh(); |
| 694 | |
| 695 | // Initialize extended structure with embedded scan data |
| 696 | new (extended_scan) |
| 697 | DeeplakeScanData(table_scan(table_id, is_parallel, query_info::current().receiver_registered())); |
| 698 | |
| 699 | TableScanDesc scan_desc = &extended_scan->postgres_scan; |
| 700 | scan_desc->rs_rd = relation; |
| 701 | scan_desc->rs_snapshot = snapshot; |
| 702 | scan_desc->rs_nkeys = nkeys; |
| 703 | scan_desc->rs_key = key; |
| 704 | scan_desc->rs_flags = flags; |
| 705 | scan_desc->rs_parallel = parallel_scan; |
| 706 | |
| 707 | if (parallel_scan != nullptr) { |
| 708 | DeeplakeParallelScanDesc* custom_pscan = reinterpret_cast<DeeplakeParallelScanDesc*>(parallel_scan); |
| 709 | if (IsParallelWorker()) { |
| 710 | custom_pscan->is_initialized = true; |
| 711 | } |
| 712 | } |
| 713 | |
| 714 | auto& td = table_storage::instance().get_table_data(table_id); |
| 715 | // For UPDATE/DELETE operations, we need all columns because PostgreSQL needs to reconstruct |
| 716 | // the entire tuple. For SELECT *, we also need all columns. |
| 717 | // For ANALYZE, we also need all columns to sample data and calculate statistics. |
| 718 | bool need_all_columns = (flags & SO_TYPE_ANALYZE) || |
| 719 | (!pg::query_info::current().is_count_star() && td.is_star_selected()) || |
| 720 | (pg::query_info::current().command_type() == pg::command_type::CMD_UPDATE) || |
| 721 | (pg::query_info::current().command_type() == pg::command_type::CMD_DELETE); |
| 722 | |
| 723 | if (need_all_columns) { |
| 724 | for (auto i = 0; i < td.num_columns(); ++i) { |
| 725 | if (!td.is_column_requested(i)) { |
| 726 | td.set_column_requested(i, true); |
| 727 | if (td.can_stream_column(i)) { |
| 728 | td.create_streamer(i, -1); |
| 729 | } |
| 730 | } |
| 731 | } |
| 732 | } |
nothing calls this directly
no test coverage detected