| 159 | |
| 160 | |
| 161 | double EXT_cardinality(thread_db* tdbb, jrd_rel* relation) |
| 162 | { |
| 163 | /************************************** |
| 164 | * |
| 165 | * E X T _ c a r d i n a l i t y |
| 166 | * |
| 167 | ************************************** |
| 168 | * |
| 169 | * Functional description |
| 170 | * Return cardinality for the external file. |
| 171 | * |
| 172 | **************************************/ |
| 173 | ExternalFile* const file = relation->rel_file; |
| 174 | fb_assert(file); |
| 175 | |
| 176 | try |
| 177 | { |
| 178 | bool must_close = false; |
| 179 | if (!file->ext_ifi) |
| 180 | { |
| 181 | ext_fopen(tdbb->getDatabase(), file); |
| 182 | must_close = true; |
| 183 | } |
| 184 | |
| 185 | FB_UINT64 file_size = 0; |
| 186 | |
| 187 | #ifdef WIN_NT |
| 188 | struct __stat64 statistics; |
| 189 | if (!_fstat64(_fileno(file->ext_ifi), &statistics)) |
| 190 | #else |
| 191 | struct STAT statistics; |
| 192 | if (!os_utils::fstat(fileno(file->ext_ifi), &statistics)) |
| 193 | #endif |
| 194 | { |
| 195 | file_size = statistics.st_size; |
| 196 | } |
| 197 | |
| 198 | if (must_close) |
| 199 | { |
| 200 | fclose(file->ext_ifi); |
| 201 | file->ext_ifi = NULL; |
| 202 | } |
| 203 | |
| 204 | const Format* const format = MET_current(tdbb, relation); |
| 205 | fb_assert(format && format->fmt_length); |
| 206 | const USHORT offset = (USHORT)(IPTR) format->fmt_desc[0].dsc_address; |
| 207 | const ULONG record_length = format->fmt_length - offset; |
| 208 | |
| 209 | return (double) file_size / record_length; |
| 210 | } |
| 211 | catch (const Exception&) |
| 212 | { |
| 213 | fb_utils::init_status(tdbb->tdbb_status_vector); |
| 214 | } |
| 215 | |
| 216 | return 10000; // just a wild guess |
| 217 | } |
| 218 |
no test coverage detected