MyCATApache/Mycat-Server · error · RuntimeException

number of columns error

Error message

number of  columns error

What it means

InsertData() validates an INSERT statement before building MongoDB BasicDBObjects. If the VALUES clause contains zero value expressions, it throws RuntimeException("number of columns error"). This guards against INSERT statements with an empty VALUES list, which cannot be translated to a Mongo document insert.

Solutions

  1. Ensure every INSERT statement includes at least one row of values
  2. Validate the generated SQL before executing: values list must be non-empty
  3. Catch RuntimeException around executeUpdate and surface a clearer 'empty VALUES clause' message to the caller
  4. If rows are optional, skip execution when the values list is empty instead of issuing the INSERT

Example fix

// before
String sql = "INSERT INTO users (name) VALUES ()";
stmt.executeUpdate(sql); // throws

// after
if (values.length == 0) {
    return 0; // nothing to insert
}
stmt.executeUpdate("INSERT INTO users (name) VALUES ('" + values[0] + "')");
Defensive patterns

Strategy: validation

Validate before calling

SQLStatement st = SQLUtils.parseSingleStatement(sql, dbType);
if (st instanceof SQLInsertStatement) {
    SQLInsertStatement ins = (SQLInsertStatement) st;
    if (ins.getValues() == null || ins.getValues().getValues().isEmpty()) {
        throw new IllegalArgumentException("INSERT requires a non-empty VALUES clause");
    }
}

Try / catch

try {
    return stmt.executeUpdate(sql);
} catch (RuntimeException e) {
    if ("number of  columns error".equals(e.getMessage())) {
        throw new SQLException("INSERT has empty VALUES clause: " + sql, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Executing INSERT INTO t () VALUES () or any INSERT whose values clause parses to an empty list, via executeUpdate on the MongoDB handler.

Common situations: Dynamically generated INSERT SQL where the value list was filtered to empty; SQL builders emitting INSERT with no rows; mistyped SQL with missing VALUES contents.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/4f19a1147e907319. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/backend/jdbc/mongodb/MongoSQLParser.java:178

        }	
        if (statement instanceof SQLUpdateStatement) {
        	return UpData((SQLUpdateStatement)statement);
        }
        if (statement instanceof SQLDropTableStatement) {
        	return dropTable((SQLDropTableStatement)statement);
        }
        if (statement instanceof SQLDeleteStatement) {
        	return DeleteDate((SQLDeleteStatement)statement);
        }
        if (statement instanceof SQLCreateTableStatement) {
        	return 1;
        }          
		return 1;
		
	}
	private int InsertData(SQLInsertStatement state) {
		if (state.getValues().getValues().size() ==0 ){
			throw new RuntimeException("number of  columns error");
		}		
		if (state.getValues().getValues().size() != state.getColumns().size()){
			throw new RuntimeException("number of values and columns have to match");
		}
		SQLTableSource table=state.getTableSource();
		BasicDBObject[] oList = new BasicDBObject[state.getValuesList().size()];
		int i = 0;
		for(SQLInsertStatement.ValuesClause values : state.getValuesList()){
			int j = 0;
			BasicDBObject o = new BasicDBObject();
			oList[i++] = o ;
			for(SQLExpr col : state.getColumns()) {
				o.put(getFieldName2(col), getExpValue(values.getValues().get(j++)));
			}
		}

		DBCollection coll =this._db.getCollection(table.toString());
		WriteResult result = coll.insert(oList);

View on GitHub (pinned to 65f8d8beb7)