| 105 | |
| 106 | |
| 107 | BlockInputStreamPtr InterpreterDescribeQuery::executeImpl() |
| 108 | { |
| 109 | ColumnsDescription columns; |
| 110 | StorageSnapshotPtr storage_snapshot; |
| 111 | |
| 112 | const auto & ast = query_ptr->as<ASTDescribeQuery &>(); |
| 113 | const auto & table_expression = ast.table_expression->as<ASTTableExpression &>(); |
| 114 | const auto & settings = getContext()->getSettingsRef(); |
| 115 | |
| 116 | if (table_expression.subquery) |
| 117 | { |
| 118 | auto names_and_types = InterpreterSelectWithUnionQuery::getSampleBlock( |
| 119 | table_expression.subquery->children.at(0), getContext()).getNamesAndTypesList(); |
| 120 | columns = ColumnsDescription(std::move(names_and_types)); |
| 121 | } |
| 122 | else if (table_expression.table_function) |
| 123 | { |
| 124 | TableFunctionPtr table_function_ptr = TableFunctionFactory::instance().get(table_expression.table_function, getContext()); |
| 125 | columns = table_function_ptr->getActualTableStructure(getContext()); |
| 126 | } |
| 127 | else |
| 128 | { |
| 129 | auto table_id = getContext()->resolveStorageID(table_expression.database_and_table_name); |
| 130 | getContext()->checkAccess(AccessType::SHOW_COLUMNS, table_id); |
| 131 | auto table = DatabaseCatalog::instance().getTable(table_id, getContext()); |
| 132 | auto table_lock = table->lockForShare(getContext()->getInitialQueryId(), settings.lock_acquire_timeout); |
| 133 | auto metadata_snapshot = table->getInMemoryMetadataPtr(); |
| 134 | storage_snapshot = table->getStorageSnapshot(metadata_snapshot, getContext()); |
| 135 | columns = metadata_snapshot->getColumns(); |
| 136 | } |
| 137 | |
| 138 | bool extend_object_types = settings.describe_extend_object_types && storage_snapshot; |
| 139 | bool include_subcolumns = settings.describe_include_subcolumns; |
| 140 | Block sample_block = getSampleBlock(getContext(), include_subcolumns); |
| 141 | MutableColumns res_columns = sample_block.cloneEmptyColumns(); |
| 142 | |
| 143 | auto dialect_type = getContext()->getSettingsRef().dialect_type; |
| 144 | |
| 145 | for (const auto & column : columns) |
| 146 | { |
| 147 | size_t i = 0; |
| 148 | res_columns[i++]->insert(column.name); |
| 149 | if (extend_object_types) |
| 150 | res_columns[i++]->insert(storage_snapshot->getConcreteType(column.name)->getName()); |
| 151 | else if (dialect_type != DialectType::CLICKHOUSE) |
| 152 | { |
| 153 | /// Under ANSI mode, data type will be parsed by ANSI type parser, which converts Nullable to |
| 154 | /// null modifiers. And the nullability of root type will be demonstrated in the separate |
| 155 | /// field: `nullable`. For instance, the type field Nullable(Array(Array(Nullable(Array(String))))) |
| 156 | /// will be divided into two fields under ANSI mode: |
| 157 | /// type: Array(Array(Array(String NOT NULL) NULL) NOT NULL |
| 158 | /// nullable: true |
| 159 | ParserDataType type_parser(ParserSettings::ANSI); |
| 160 | String type_name = column.type->getName(); |
| 161 | const char * type_name_pos = type_name.data(); |
| 162 | const char * type_name_end = type_name_pos + type_name.size(); |
| 163 | auto type_ast = parseQuery(type_parser, type_name_pos, type_name_end, "data type", 0, DBMS_DEFAULT_MAX_PARSER_DEPTH); |
| 164 |
nothing calls this directly
no test coverage detected