| 1133 | } |
| 1134 | |
| 1135 | void deeplake_table_am_routine::relation_set_new_node( |
| 1136 | Relation rel, const RelFileLocator* newrnode, char persistence, TransactionId* freezeXid, MultiXactId* minmulti) |
| 1137 | { |
| 1138 | // Get the schema-qualified table name |
| 1139 | const std::string table_name = get_qualified_table_name(rel); |
| 1140 | |
| 1141 | // Block temp table creation from VACUUM FULL |
| 1142 | // VACUUM FULL tries to create a temp table (pg_temp_*) to rebuild the original table |
| 1143 | // This is not supported for columnar storage |
| 1144 | if (table_name.find("pg_temp_") != std::string::npos) { |
| 1145 | ereport( |
| 1146 | ERROR, |
| 1147 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 1148 | errmsg("VACUUM FULL is not supported for deeplake tables"), |
| 1149 | errhint( |
| 1150 | "Deeplake uses columnar storage which is already compact. Use VACUUM or VACUUM ANALYZE instead."))); |
| 1151 | } |
| 1152 | |
| 1153 | *freezeXid = RecentXmin; |
| 1154 | *minmulti = GetOldestMultiXactId(); |
| 1155 | |
| 1156 | // Create physical storage for the relation. |
| 1157 | // Even though DeepLake uses columnar storage (S3/cloud), PostgreSQL's ANALYZE |
| 1158 | // requires a physical storage file for block sampling. The read_stream API |
| 1159 | // expects to read physical blocks from the relation's storage file. |
| 1160 | // Without this, ANALYZE fails with "could not open file" errors. |
| 1161 | SMgrRelation srel = RelationCreateStorage(*newrnode, persistence, true); |
| 1162 | |
| 1163 | // Extend the storage to have at least one block. |
| 1164 | // This is needed because ANALYZE's BlockSampler will try to read blocks, |
| 1165 | // and if the file is empty, read_stream_next_buffer will fail. |
| 1166 | // We create a minimal block so that ANALYZE can proceed. |
| 1167 | // The actual data comes from our columnar storage via scan_analyze_next_tuple. |
| 1168 | smgrzeroextend(srel, MAIN_FORKNUM, 0, 1, true); |
| 1169 | |
| 1170 | if (persistence == RELPERSISTENCE_UNLOGGED) { |
| 1171 | smgrcreate(srel, INIT_FORKNUM, false); |
| 1172 | log_smgrcreate(&srel->smgr_rlocator.locator, INIT_FORKNUM); |
| 1173 | smgrimmedsync(srel, INIT_FORKNUM); |
| 1174 | } |
| 1175 | |
| 1176 | smgrclose(srel); |
| 1177 | |
| 1178 | // Get the tuple descriptor |
| 1179 | TupleDesc tupdesc = RelationGetDescr(rel); |
| 1180 | if (tupdesc == nullptr) { |
| 1181 | ereport(ERROR, |
| 1182 | (errcode(ERRCODE_UNDEFINED_TABLE), |
| 1183 | errmsg("could not get tuple descriptor for relation \"%s\"", RelationGetRelationName(rel)))); |
| 1184 | } |
| 1185 | |
| 1186 | convert_schema(tupdesc); |
| 1187 | |
| 1188 | // Set DDL context to prevent auto-creation of tables from catalog during |
| 1189 | // concurrent table creation (which causes race conditions). |
| 1190 | table_storage::ddl_context_guard ddl_guard; |
| 1191 | |
| 1192 | try { |
nothing calls this directly
no test coverage detected