| 1882 | } |
| 1883 | |
| 1884 | void validateVirtualColumns(IStorage & storage, ContextPtr context) |
| 1885 | { |
| 1886 | const auto metadata = storage.getInMemoryMetadataPtr(context, false); |
| 1887 | for (const auto & storage_column : metadata->columns) |
| 1888 | { |
| 1889 | if (metadata->virtuals.tryGet(storage_column.name, VirtualsKind::Persistent, VirtualsMaterializationPlace::All)) |
| 1890 | { |
| 1891 | throw Exception(ErrorCodes::ILLEGAL_COLUMN, |
| 1892 | "Cannot create table with column '{}' for {} engines because it is reserved for persistent virtual column", |
| 1893 | storage_column.name, storage.getName()); |
| 1894 | } |
| 1895 | |
| 1896 | /// An EPHEMERAL user column has no physical storage and no read-time expression, |
| 1897 | /// so it cannot properly shadow a virtual column of the same name. |
| 1898 | /// This leads to a type mismatch: the Block header uses the user column's type |
| 1899 | /// while the data comes from the virtual column (which may have a different type). |
| 1900 | if (storage_column.default_desc.kind == ColumnDefaultKind::Ephemeral && metadata->virtuals.tryGet(storage_column.name, VirtualsKind::Ephemeral, VirtualsMaterializationPlace::All)) |
| 1901 | { |
| 1902 | throw Exception(ErrorCodes::ILLEGAL_COLUMN, |
| 1903 | "Cannot create table with ephemeral column '{}' for {} engines " |
| 1904 | "because it conflicts with a virtual column of the same name", |
| 1905 | storage_column.name, storage.getName()); |
| 1906 | } |
| 1907 | } |
| 1908 | } |
| 1909 | |
| 1910 | void validateStorage(IStorage & storage, LoadingStrictnessLevel mode, ContextPtr context) |
| 1911 | try |
no test coverage detected