Java Code Examples for org.apache.calcite.sql.SqlSelect

The following examples show how to use org.apache.calcite.sql.SqlSelect. These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source Project: alchemy   Source File: SqlParseUtil.java    License: Apache License 2.0 6 votes vote down vote up
public static void parse(List<String> sqls, List<String> sources, List<String> udfs, List<String> sinks)
    throws SqlParseException {
    for (String sql : sqls) {
        SqlParser sqlParser = SqlParser.create(sql, CONFIG);
        SqlNode sqlNode = sqlParser.parseStmt();
        SqlKind kind = sqlNode.getKind();
        switch (kind){
            case INSERT:
                SqlInsert sqlInsert = (SqlInsert)sqlNode;
                addSink(sinks, findSinkName(sqlInsert));
                SqlSelect source = (SqlSelect) sqlInsert.getSource();
                parseSource(source, sources, udfs);
                break;
            case SELECT:
                parseSource((SqlSelect) sqlNode, sources, udfs);
                break;
            default:
                throw new IllegalArgumentException("It must be an insert SQL, sql:" + sql);
        }
    }
}
 
Example 2
Source Project: alchemy   Source File: SideParser.java    License: Apache License 2.0 6 votes vote down vote up
public static void parse(SqlNode sqlNode, Deque<SqlNode> deque) {
    deque.offer(sqlNode);
    SqlKind sqlKind = sqlNode.getKind();
    switch (sqlKind) {
        case INSERT:
            SqlNode sqlSource = ((SqlInsert)sqlNode).getSource();
            parse(sqlSource, deque);
            break;
        case SELECT:
            SqlNode sqlFrom = ((SqlSelect)sqlNode).getFrom();
            parse(sqlFrom, deque);
            break;
        case JOIN:
            SqlNode sqlLeft = ((SqlJoin)sqlNode).getLeft();
            SqlNode sqlRight = ((SqlJoin)sqlNode).getRight();
            parse(sqlLeft, deque);
            parse(sqlRight, deque);
            break;
        case AS:
            SqlNode sqlAs = ((SqlBasicCall)sqlNode).getOperands()[0];
            parse(sqlAs, deque);
            break;
        default:
            return;
    }
}
 
Example 3
Source Project: Bats   Source File: SqlImplementor.java    License: Apache License 2.0 6 votes vote down vote up
private boolean hasNestedAggregations(LogicalAggregate rel) {
    if (node instanceof SqlSelect) {
        final SqlNodeList selectList = ((SqlSelect) node).getSelectList();
        if (selectList != null) {
            final Set<Integer> aggregatesArgs = new HashSet<>();
            for (AggregateCall aggregateCall : rel.getAggCallList()) {
                aggregatesArgs.addAll(aggregateCall.getArgList());
            }
            for (int aggregatesArg : aggregatesArgs) {
                if (selectList.get(aggregatesArg) instanceof SqlBasicCall) {
                    final SqlBasicCall call = (SqlBasicCall) selectList.get(aggregatesArg);
                    for (SqlNode operand : call.getOperands()) {
                        if (operand instanceof SqlCall
                                && ((SqlCall) operand).getOperator() instanceof SqlAggFunction) {
                            return true;
                        }
                    }
                }
            }
        }
    }
    return false;
}
 
Example 4
Source Project: streamline   Source File: RuleParser.java    License: Apache License 2.0 6 votes vote down vote up
public void parse() {
    try {
        SchemaPlus schema = Frameworks.createRootSchema(true);
        FrameworkConfig config = Frameworks.newConfigBuilder().defaultSchema(schema).build();
        Planner planner = Frameworks.getPlanner(config);
        SqlSelect sqlSelect = (SqlSelect) planner.parse(sql);
        // FROM
        streams = parseStreams(sqlSelect);
        // SELECT
        projection = parseProjection(sqlSelect);
        // WHERE
        condition = parseCondition(sqlSelect);
        // GROUP BY
        groupBy = parseGroupBy(sqlSelect);
        // HAVING
        having = parseHaving(sqlSelect);
    } catch (Exception ex) {
        LOG.error("Got Exception while parsing rule {}", sql);
        throw new RuntimeException(ex);
    }
}
 
Example 5
Source Project: alchemy   Source File: SideParser.java    License: Apache License 2.0 6 votes vote down vote up
public static void rewrite(SqlNode sqlNode, SqlSelect sqlSelect) {
    SqlKind sqlKind = sqlNode.getKind();
    switch (sqlKind) {
        case INSERT:
            SqlInsert sqlInsert = ((SqlInsert)sqlNode);
            sqlInsert.setSource(sqlSelect);
            break;
        case SELECT:
            SqlSelect select = (SqlSelect)sqlNode;
            select.setFrom(sqlSelect);
            break;
        case AS:
            SqlBasicCall basicCall = (SqlBasicCall)sqlNode;
            basicCall.setOperand(0, sqlSelect);
            break;
        default:
            throw new UnsupportedOperationException(sqlKind + "目前不支持维表操作");
    }
}
 
Example 6
Source Project: flink   Source File: SqlValidatorImpl.java    License: Apache License 2.0 6 votes vote down vote up
public void validateUpdate(SqlUpdate call) {
	final SqlValidatorNamespace targetNamespace = getNamespace(call);
	validateNamespace(targetNamespace, unknownType);
	final RelOptTable relOptTable = SqlValidatorUtil.getRelOptTable(
		targetNamespace, catalogReader.unwrap(Prepare.CatalogReader.class), null, null);
	final SqlValidatorTable table = relOptTable == null
		? targetNamespace.getTable()
		: relOptTable.unwrap(SqlValidatorTable.class);

	final RelDataType targetRowType =
		createTargetRowType(
			table,
			call.getTargetColumnList(),
			true);

	final SqlSelect select = call.getSourceSelect();
	validateSelect(select, targetRowType);

	final RelDataType sourceRowType = getNamespace(call).getRowType();
	checkTypeAssignment(sourceRowType, targetRowType, call);

	checkConstraint(table, call, targetRowType);

	validateAccess(call.getTargetTable(), table, SqlAccessEnum.UPDATE);
}
 
Example 7
Source Project: alchemy   Source File: SqlParseUtil.java    License: Apache License 2.0 6 votes vote down vote up
private static void parseSelect(SqlNode sqlNode, List<String> sources, List<String> udfs) throws SqlParseException {
    SqlKind sqlKind = sqlNode.getKind();
    switch (sqlKind) {
        case IDENTIFIER:
            break;
        case AS:
            SqlNode firstNode = ((SqlBasicCall)sqlNode).operand(0);
            parseSelect(firstNode, sources, udfs);
            break;
        case SELECT:
            parseSource((SqlSelect)sqlNode, sources, udfs);
            break;
        default:
            parseFunction(sqlNode, udfs);

    }
}
 
Example 8
Source Project: Flink-CEPplus   Source File: SqlValidatorImpl.java    License: Apache License 2.0 6 votes vote down vote up
public boolean isAggregate(SqlSelect select) {
	if (getAggregate(select) != null) {
		return true;
	}
	// Also when nested window aggregates are present
	for (SqlCall call : overFinder.findAll(select.getSelectList())) {
		assert call.getKind() == SqlKind.OVER;
		if (isNestedAggregateWindow(call.operand(0))) {
			return true;
		}
		if (isOverAggregateWindow(call.operand(1))) {
			return true;
		}
	}
	return false;
}
 
Example 9
Source Project: calcite   Source File: SqlImplementor.java    License: Apache License 2.0 6 votes vote down vote up
/** Wraps a node in a SELECT statement that has no clauses:
 *  "SELECT ... FROM (node)". */
SqlSelect wrapSelect(SqlNode node) {
  assert node instanceof SqlJoin
      || node instanceof SqlIdentifier
      || node instanceof SqlMatchRecognize
      || node instanceof SqlCall
          && (((SqlCall) node).getOperator() instanceof SqlSetOperator
              || ((SqlCall) node).getOperator() == SqlStdOperatorTable.AS
              || ((SqlCall) node).getOperator() == SqlStdOperatorTable.VALUES)
      : node;
  if (requiresAlias(node)) {
    node = as(node, "t");
  }
  return new SqlSelect(POS, SqlNodeList.EMPTY, null, node, null, null, null,
      SqlNodeList.EMPTY, null, null, null, null);
}
 
Example 10
Source Project: alchemy   Source File: SideParser.java    License: Apache License 2.0 6 votes vote down vote up
public static SqlSelect newSelect(SqlSelect selectSelf, String table, String alias, boolean left, boolean newTable) {
    List<SqlNode> operand = selectSelf.getOperandList();
    SqlNodeList keywordList = (SqlNodeList)operand.get(0);
    SqlNodeList selectList = (SqlNodeList)operand.get(1);
    SqlNode from = operand.get(2);
    SqlNode where = operand.get(3);
    SqlNodeList groupBy = (SqlNodeList)operand.get(4);
    SqlNode having = operand.get(5);
    SqlNodeList windowDecls = (SqlNodeList)operand.get(6);
    SqlNodeList orderBy = (SqlNodeList)operand.get(7);
    SqlNode offset = operand.get(8);
    SqlNode fetch = operand.get(9);
    if (left) {
        return newSelect(selectSelf.getParserPosition(), keywordList, selectList, ((SqlJoin)from).getLeft(), where,
            groupBy, having, windowDecls, orderBy, offset, fetch, alias, newTable);
    }
    if (newTable) {
        return newSelect(selectSelf.getParserPosition(), null,  creatFullNewSelectList(alias, selectList), createNewFrom(table, alias, from),
            where, groupBy, having, windowDecls, orderBy, offset, fetch, alias, newTable);
    } else {
        return newSelect(selectSelf.getParserPosition(), null, selectList, ((SqlJoin)from).getRight(), where,
            groupBy, having, windowDecls, orderBy, offset, fetch, alias, newTable);
    }

}
 
Example 11
Source Project: Flink-CEPplus   Source File: SqlValidatorImpl.java    License: Apache License 2.0 6 votes vote down vote up
public void validateUpdate(SqlUpdate call) {
	final SqlValidatorNamespace targetNamespace = getNamespace(call);
	validateNamespace(targetNamespace, unknownType);
	final RelOptTable relOptTable = SqlValidatorUtil.getRelOptTable(
		targetNamespace, catalogReader.unwrap(Prepare.CatalogReader.class), null, null);
	final SqlValidatorTable table = relOptTable == null
		? targetNamespace.getTable()
		: relOptTable.unwrap(SqlValidatorTable.class);

	final RelDataType targetRowType =
		createTargetRowType(
			table,
			call.getTargetColumnList(),
			true);

	final SqlSelect select = call.getSourceSelect();
	validateSelect(select, targetRowType);

	final RelDataType sourceRowType = getNamespace(call).getRowType();
	checkTypeAssignment(sourceRowType, targetRowType, call);

	checkConstraint(table, call, targetRowType);

	validateAccess(call.getTargetTable(), table, SqlAccessEnum.UPDATE);
}
 
Example 12
Source Project: calcite   Source File: SelectScope.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Creates a scope corresponding to a SELECT clause.
 *
 * @param parent    Parent scope, must not be null
 * @param winParent Scope for window parent, may be null
 * @param select    Select clause
 */
SelectScope(
    SqlValidatorScope parent,
    SqlValidatorScope winParent,
    SqlSelect select) {
  super(parent);
  this.select = select;
  this.windowParent = winParent;
}
 
Example 13
Source Project: Bats   Source File: SqlImplementor.java    License: Apache License 2.0 5 votes vote down vote up
/** Converts a non-query node into a SELECT node. Set operators (UNION,
 * INTERSECT, EXCEPT) remain as is. */
public SqlSelect asSelect() {
    if (node instanceof SqlSelect) {
        return (SqlSelect) node;
    }
    if (!dialect.hasImplicitTableAlias()) {
        return wrapSelect(asFrom());
    }
    return wrapSelect(node);
}
 
Example 14
Source Project: Bats   Source File: SqlImplementor.java    License: Apache License 2.0 5 votes vote down vote up
public Builder(RelNode rel, List<Clause> clauses, SqlSelect select, Context context,
        Map<String, RelDataType> aliases) {
    this.rel = rel;
    this.clauses = clauses;
    this.select = select;
    this.context = context;
    this.aliases = aliases;
}
 
Example 15
Source Project: flink   Source File: SqlValidatorImpl.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Validates an item in the ORDER BY clause of a SELECT statement.
 *
 * @param select Select statement
 * @param orderItem ORDER BY clause item
 */
private void validateOrderItem(SqlSelect select, SqlNode orderItem) {
	switch (orderItem.getKind()) {
		case DESCENDING:
			validateFeature(RESOURCE.sQLConformance_OrderByDesc(),
				orderItem.getParserPosition());
			validateOrderItem(select,
				((SqlCall) orderItem).operand(0));
			return;
	}

	final SqlValidatorScope orderScope = getOrderScope(select);
	validateExpr(orderItem, orderScope);
}
 
Example 16
Source Project: Bats   Source File: SelectScope.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Creates a scope corresponding to a SELECT clause.
 *
 * @param parent    Parent scope, must not be null
 * @param winParent Scope for window parent, may be null
 * @param select    Select clause
 */
SelectScope(
    SqlValidatorScope parent,
    SqlValidatorScope winParent,
    SqlSelect select) {
  super(parent);
  this.select = select;
  this.windowParent = winParent;
}
 
Example 17
Source Project: streamline   Source File: RuleParser.java    License: Apache License 2.0 5 votes vote down vote up
private List<Stream> parseStreams(SqlSelect sqlSelect) throws Exception {
    List<Stream> streams = new ArrayList<>();
    SqlNode sqlFrom = sqlSelect.getFrom();
    LOG.debug("from = {}", sqlFrom);
    if (sqlFrom instanceof SqlJoin) {
        throw new IllegalArgumentException("Sql join is not yet supported");
    } else if (sqlFrom instanceof SqlIdentifier) {
        streams.add(getStream(((SqlIdentifier) sqlFrom).getSimple()));
    }
    LOG.debug("Streams {}", streams);
    return streams;
}
 
Example 18
Source Project: flink   Source File: SqlValidatorImpl.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Processes SubQuery found in Select list. Checks that is actually Scalar
 * sub-query and makes proper entries in each of the 3 lists used to create
 * the final rowType entry.
 *
 * @param parentSelect        base SqlSelect item
 * @param selectItem          child SqlSelect from select list
 * @param expandedSelectItems Select items after processing
 * @param aliasList           built from user or system values
 * @param fieldList           Built up entries for each select list entry
 */
private void handleScalarSubQuery(
	SqlSelect parentSelect,
	SqlSelect selectItem,
	List<SqlNode> expandedSelectItems,
	Set<String> aliasList,
	List<Map.Entry<String, RelDataType>> fieldList) {
	// A scalar sub-query only has one output column.
	if (1 != selectItem.getSelectList().size()) {
		throw newValidationError(selectItem,
			RESOURCE.onlyScalarSubQueryAllowed());
	}

	// No expansion in this routine just append to list.
	expandedSelectItems.add(selectItem);

	// Get or generate alias and add to list.
	final String alias =
		deriveAlias(
			selectItem,
			aliasList.size());
	aliasList.add(alias);

	final SelectScope scope = (SelectScope) getWhereScope(parentSelect);
	final RelDataType type = deriveType(scope, selectItem);
	setValidatedNodeType(selectItem, type);

	// we do not want to pass on the RelRecordType returned
	// by the sub query.  Just the type of the single expression
	// in the sub-query select list.
	assert type instanceof RelRecordType;
	RelRecordType rec = (RelRecordType) type;

	RelDataType nodeType = rec.getFieldList().get(0).getType();
	nodeType = typeFactory.createTypeWithNullability(nodeType, true);
	fieldList.add(Pair.of(alias, nodeType));
}
 
Example 19
Source Project: calcite   Source File: MysqlSqlDialect.java    License: Apache License 2.0 5 votes vote down vote up
@Override public SqlNode rewriteSingleValueExpr(SqlNode aggCall) {
  final SqlNode operand = ((SqlBasicCall) aggCall).operand(0);
  final SqlLiteral nullLiteral = SqlLiteral.createNull(SqlParserPos.ZERO);
  final SqlNode unionOperand = new SqlSelect(SqlParserPos.ZERO, SqlNodeList.EMPTY,
      SqlNodeList.of(nullLiteral), null, null, null, null,
      SqlNodeList.EMPTY, null, null, null, SqlNodeList.EMPTY);
  // For MySQL, generate
  //   CASE COUNT(*)
  //   WHEN 0 THEN NULL
  //   WHEN 1 THEN <result>
  //   ELSE (SELECT NULL UNION ALL SELECT NULL)
  //   END
  final SqlNode caseExpr =
      new SqlCase(SqlParserPos.ZERO,
          SqlStdOperatorTable.COUNT.createCall(SqlParserPos.ZERO, operand),
          SqlNodeList.of(
              SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO),
              SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO)),
          SqlNodeList.of(
              nullLiteral,
              operand),
          SqlStdOperatorTable.SCALAR_QUERY.createCall(SqlParserPos.ZERO,
              SqlStdOperatorTable.UNION_ALL
                  .createCall(SqlParserPos.ZERO, unionOperand, unionOperand)));

  LOGGER.debug("SINGLE_VALUE rewritten into [{}]", caseExpr);

  return caseExpr;
}
 
Example 20
Source Project: calcite   Source File: GroupByScope.java    License: Apache License 2.0 5 votes vote down vote up
GroupByScope(
    SqlValidatorScope parent,
    SqlNodeList groupByList,
    SqlSelect select) {
  super(parent);
  this.groupByList = groupByList;
  this.select = select;
}
 
Example 21
Source Project: Bats   Source File: OrderByScope.java    License: Apache License 2.0 5 votes vote down vote up
OrderByScope(
    SqlValidatorScope parent,
    SqlNodeList orderList,
    SqlSelect select) {
  super(parent);
  this.orderList = orderList;
  this.select = select;
}
 
Example 22
Source Project: Bats   Source File: AggregatingSelectScope.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Creates an AggregatingSelectScope
 *
 * @param selectScope Parent scope
 * @param select      Enclosing SELECT node
 * @param distinct    Whether SELECT is DISTINCT
 */
AggregatingSelectScope(
    SqlValidatorScope selectScope,
    SqlSelect select,
    boolean distinct) {
  // The select scope is the parent in the sense that all columns which
  // are available in the select scope are available. Whether they are
  // valid as aggregation expressions... now that's a different matter.
  super(selectScope);
  this.select = select;
  this.distinct = distinct;
}
 
Example 23
Source Project: calcite   Source File: OrderByScope.java    License: Apache License 2.0 5 votes vote down vote up
OrderByScope(
    SqlValidatorScope parent,
    SqlNodeList orderList,
    SqlSelect select) {
  super(parent);
  this.orderList = orderList;
  this.select = select;
}
 
Example 24
Source Project: flink   Source File: SqlValidatorImpl.java    License: Apache License 2.0 5 votes vote down vote up
private SqlSelect getInnerSelect(SqlNode node) {
	for (;;) {
		if (node instanceof SqlSelect) {
			return (SqlSelect) node;
		} else if (node instanceof SqlOrderBy) {
			node = ((SqlOrderBy) node).query;
		} else if (node instanceof SqlWith) {
			node = ((SqlWith) node).body;
		} else {
			return null;
		}
	}
}
 
Example 25
Source Project: flink   Source File: SqlValidatorImpl.java    License: Apache License 2.0 5 votes vote down vote up
private List<String> getFieldOrigin(SqlNode sqlQuery, int i) {
	if (sqlQuery instanceof SqlSelect) {
		SqlSelect sqlSelect = (SqlSelect) sqlQuery;
		final SelectScope scope = getRawSelectScope(sqlSelect);
		final List<SqlNode> selectList = scope.getExpandedSelectList();
		final SqlNode selectItem = stripAs(selectList.get(i));
		if (selectItem instanceof SqlIdentifier) {
			final SqlQualified qualified =
				scope.fullyQualify((SqlIdentifier) selectItem);
			SqlValidatorNamespace namespace = qualified.namespace;
			final SqlValidatorTable table = namespace.getTable();
			if (table == null) {
				return null;
			}
			final List<String> origin =
				new ArrayList<>(table.getQualifiedName());
			for (String name : qualified.suffix()) {
				namespace = namespace.lookupChild(name);
				if (namespace == null) {
					return null;
				}
				origin.add(name);
			}
			return origin;
		}
		return null;
	} else if (sqlQuery instanceof SqlOrderBy) {
		return getFieldOrigin(((SqlOrderBy) sqlQuery).query, i);
	} else {
		return null;
	}
}
 
Example 26
Source Project: calcite   Source File: JdbcTable.java    License: Apache License 2.0 5 votes vote down vote up
SqlString generateSql() {
  final SqlNodeList selectList = SqlNodeList.SINGLETON_STAR;
  SqlSelect node =
      new SqlSelect(SqlParserPos.ZERO, SqlNodeList.EMPTY, selectList,
          tableName(), null, null, null, null, null, null, null, null);
  final SqlWriterConfig config = SqlPrettyWriter.config()
      .withAlwaysUseParentheses(true)
      .withDialect(jdbcSchema.dialect);
  final SqlPrettyWriter writer = new SqlPrettyWriter(config);
  node.unparse(writer, 0, 0);
  return writer.toSqlString();
}
 
Example 27
Source Project: dremio-oss   Source File: UnsupportedOperatorsVisitor.java    License: Apache License 2.0 5 votes vote down vote up
private void checkGrouping(SqlSelect sqlSelect) {
  final ExprFinder groupingFinder = new ExprFinder(GroupingID);
  sqlSelect.accept(groupingFinder);
  if (groupingFinder.find()) {
    // DRILL-3962
    unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION,
        "Grouping, Grouping_ID, Group_ID are not supported.");
    throw new UnsupportedOperationException();
  }
}
 
Example 28
Source Project: Bats   Source File: TableScope.java    License: Apache License 2.0 5 votes vote down vote up
@Override public boolean isWithin(SqlValidatorScope scope2) {
  if (this == scope2) {
    return true;
  }
  SqlValidatorScope s = getValidator().getSelectScope((SqlSelect) node);
  return s.isWithin(scope2);
}
 
Example 29
Source Project: Bats   Source File: MysqlSqlDialect.java    License: Apache License 2.0 5 votes vote down vote up
@Override public SqlNode rewriteSingleValueExpr(SqlNode aggCall) {
  final SqlNode operand = ((SqlBasicCall) aggCall).operand(0);
  final SqlLiteral nullLiteral = SqlLiteral.createNull(SqlParserPos.ZERO);
  final SqlNode unionOperand = new SqlSelect(SqlParserPos.ZERO, SqlNodeList.EMPTY,
      SqlNodeList.of(nullLiteral), null, null, null, null, SqlNodeList.EMPTY, null, null, null);
  // For MySQL, generate
  //   CASE COUNT(*)
  //   WHEN 0 THEN NULL
  //   WHEN 1 THEN <result>
  //   ELSE (SELECT NULL UNION ALL SELECT NULL)
  //   END
  final SqlNode caseExpr =
      new SqlCase(SqlParserPos.ZERO,
          SqlStdOperatorTable.COUNT.createCall(SqlParserPos.ZERO, operand),
          SqlNodeList.of(
              SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO),
              SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO)),
          SqlNodeList.of(
              nullLiteral,
              operand),
          SqlStdOperatorTable.SCALAR_QUERY.createCall(SqlParserPos.ZERO,
              SqlStdOperatorTable.UNION_ALL
                  .createCall(SqlParserPos.ZERO, unionOperand, unionOperand)));

  LOGGER.debug("SINGLE_VALUE rewritten into [{}]", caseExpr);

  return caseExpr;
}
 
Example 30
Source Project: calcite   Source File: SqlAdvisorValidator.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Calls the parent class method and masks Farrago exception thrown.
 */
protected void validateHavingClause(SqlSelect select) {
  try {
    super.validateHavingClause(select);
  } catch (CalciteException e) {
    Util.swallow(e, TRACER);
  }
}