Uploaded image for project: 'Calcite'
  1. Calcite
  2. CALCITE-2336

SqlValidatorImpl throws java.lang.IndexOutOfBoundsException

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Duplicate
    • None
    • None
    • core
    • None

    Description

      I register a table "users" with a single column, age. And try to insert two columns into the "users".

          rootSchema = Frameworks.createRootSchema(true);
          rootSchema.add("USERS", new AbstractTable() {
            @Override public RelDataType getRowType(final RelDataTypeFactory typeFactory) {
              RelDataTypeFactory.FieldInfoBuilder builder = typeFactory.builder();
              builder.add("age", new BasicSqlType(new RelDataTypeSystemImpl() {}, SqlTypeName.CHAR));
              return builder.build();
            }
          });
      
          final FrameworkConfig config = Frameworks.newConfigBuilder()
              .parserConfig(SqlParser.Config.DEFAULT)
              .defaultSchema(rootSchema)
              .build();
          planner = Frameworks.getPlanner(config);
          dataContext = new MyDataContext(planner);
      
          SqlNode parse =
              planner.parse("insert into users select y, x\n"
                  + "from (values (1, 'a'), (2, 'b'), (3, 'c')) as t(x, y)\n"
                  + "where x > 1");
      
          SqlNode validate = planner.validate(parse);
      

      Apparently, I want to see some error message like:

      Number of INSERT target columns (1) does not equal number of source items (2)
      

      But actually, I got message:

      org.apache.calcite.tools.ValidationException: java.lang.IndexOutOfBoundsException: index (1) must be less than size (1)
      

      which was confused.

      Then I debug the code in SqlValidatorImpl#validateSelectList method.

       

      protected RelDataType validateSelectList(
          final SqlNodeList selectItems,
          SqlSelect select,
          RelDataType targetRowType) {
        // First pass, ensure that aliases are unique. "*" and "TABLE.*" items
        // are ignored.
      
        // Validate SELECT list. Expand terms of the form "*" or "TABLE.*".
        final SqlValidatorScope selectScope = getSelectScope(select);
        final List<SqlNode> expandedSelectItems = new ArrayList<>();
        final Set<String> aliases = Sets.newHashSet();
        final List<Map.Entry<String, RelDataType>> fieldList = new ArrayList<>();
      
        for (int i = 0; i < selectItems.size(); i++) {
          SqlNode selectItem = selectItems.get(i);
          if (selectItem instanceof SqlSelect) {
            handleScalarSubQuery(
                select,
                (SqlSelect) selectItem,
                expandedSelectItems,
                aliases,
                fieldList);
          } else {
            expandSelectItem(
                selectItem,
                select,
                targetRowType.isStruct()
                    && targetRowType.getFieldCount() >= i
                    ? targetRowType.getFieldList().get(i).getType()
                    : unknownType,
                expandedSelectItems,
                aliases,
                fieldList,
                false);
          }
        }
      

      See the exception is throw from here, if selectItems's size more than targetRowType's field count

      && targetRowType.getFieldCount() >= i
      ? targetRowType.getFieldList().get(i).getType()

      When I change it to this, I get what I need.

      && targetRowType.getFieldCount() - 1 >= i  
      ? targetRowType.getFieldList().get(i).getType()

      So is this a Bug ? Do we need fix it ? 

       

       

      Attachments

        1. 1.patch
          2 kB
          yuqi

        Issue Links

          Activity

            People

              Unassigned Unassigned
              xu fei Fei Xu
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: