class MappedUpdate extends BaseMappedStatement<T, ID> {

	public static <T, ID> MappedUpdate<T, ID> build(DatabaseType databaseType, TableInfo<T, ID> tableInfo)
			throws SQLException {
		FieldType idField = tableInfo.getIdField();
		if (idField == null) {
			throw new SQLException("Cannot update " + tableInfo.getDataClass() + " because it doesn't have an id field");
		}
		StringBuilder sb = new StringBuilder(64);
		appendTableName(databaseType, sb, "UPDATE ", tableInfo.getTableName());
		boolean first = true;
		int argFieldC = 0;
		FieldType versionFieldType = null;
		int versionFieldTypeIndex = -1;
		// first we count up how many arguments we are going to have
		for (FieldType fieldType : tableInfo.getFieldTypes()) {
			if (isFieldUpdatable(fieldType, idField)) {
				if (fieldType.isVersion()) {
					versionFieldType = fieldType;
					versionFieldTypeIndex = argFieldC;
				}
				argFieldC++;
			}
		}
		// one more for where id = ?
		argFieldC++;
		if (versionFieldType != null) {
			// one more for the AND version = ?
			argFieldC++;
		}
		FieldType[] argFieldTypes = new FieldType[argFieldC];
		argFieldC = 0;
		for (FieldType fieldType : tableInfo.getFieldTypes()) {
			if (!isFieldUpdatable(fieldType, idField)) {
				continue;
			}
			if (first) {
				sb.append("SET ");
				first = false;
			} else {
				sb.append(", ");
			}
			appendFieldColumnName(databaseType, sb, fieldType, null);
			argFieldTypes[argFieldC++] = fieldType;
			sb.append("= ?");
		}
		sb.append(' ');
		appendWhereFieldEq(databaseType, idField, sb, null);
		argFieldTypes[argFieldC++] = idField;
		if (versionFieldType != null) {
			sb.append(" AND ");
			appendFieldColumnName(databaseType, sb, versionFieldType, null);
			sb.append("= ?");
			argFieldTypes[argFieldC++] = versionFieldType;
		}
		return new MappedUpdate<T, ID>(tableInfo, sb.toString(), argFieldTypes, versionFieldType, versionFieldTypeIndex);
	}

	private  MappedUpdate(TableInfo<T, ID> tableInfo, String statement, FieldType[] argFieldTypes,
			FieldType versionFieldType, int versionFieldTypeIndex);

}