encodeRanges(c.dates, "date", statement);
encodeRanges(c.dates, "date", 1, statement);
    private static void encodeConstraint(int mailboxId, DbSearchConstraintsNode node, StringBuilder statement, Connection conn) throws ServiceException {        DbSearchConstraintsNode.NodeType ntype = node.getNodeType();        if (ntype == DbSearchConstraintsNode.NodeType.AND || ntype == DbSearchConstraintsNode.NodeType.OR) {            boolean first = true, and = ntype == DbSearchConstraintsNode.NodeType.AND;            statement.append('(');            for (DbSearchConstraintsNode subnode : node.getSubNodes()) {                if (!first)                    statement.append(and ? " AND " : " OR ");                encodeConstraint(mailboxId, subnode, statement, conn);                first = false;            }            statement.append(')');            return;        }        // we're here, so we must be in a DbSearchConstraints leaf node        DbSearchConstraints c = node.getSearchConstraints();        assert(ntype == DbSearchConstraintsNode.NodeType.LEAF && c != null);        c.checkDates();        // if there are no possible matches, short-circuit here...        if (c.automaticEmptySet()) {            statement.append("FALSE");            return;        }        statement.append('(');        if (ListUtil.isEmpty(c.types))            statement.append("type NOT IN " + NON_SEARCHABLE_TYPES);        else            statement.append("type IN").append(DbUtil.suitableNumberOfVariables(c.types));                if (!ListUtil.isEmpty(c.excludeTypes))            statement.append(" AND type NOT IN").append(DbUtil.suitableNumberOfVariables(c.excludeTypes));        // Determine the set of matching tags        TagConstraints tc = TagConstraints.getTagContraints(mailboxId, c, conn);        if (tc.noMatches)            statement.append(" AND FALSE");        if (c.hasTags != null)            statement.append(" AND tags ").append(c.hasTags.booleanValue() ? "!= 0" : "= 0");        if (tc.searchTagsets != null)            statement.append(" AND tags IN").append(DbUtil.suitableNumberOfVariables(tc.searchTagsets));        if (tc.searchFlagsets != null)            statement.append(" AND flags IN").append(DbUtil.suitableNumberOfVariables(tc.searchFlagsets));        if (tc.unread != null)            statement.append(" AND unread = ?");        Collection<Folder> targetFolders = (!ListUtil.isEmpty(c.folders)) ? c.folders : c.excludeFolders;        if (!ListUtil.isEmpty(targetFolders))            statement.append(" AND folder_id").append(targetFolders == c.folders ? "" : " NOT").append(" IN").append(DbUtil.suitableNumberOfVariables(targetFolders));        if (c.convId > 0)            statement.append(" AND parent_id = ?");        else if (!ListUtil.isEmpty(c.prohibitedConvIds))            statement.append(" AND parent_id NOT IN").append(DbUtil.suitableNumberOfVariables(c.prohibitedConvIds));        if (!ListUtil.isEmpty(c.itemIds))            statement.append(" AND id IN").append(DbUtil.suitableNumberOfVariables(c.itemIds));        if (!ListUtil.isEmpty(c.prohibitedItemIds))            statement.append(" AND id NOT IN").append(DbUtil.suitableNumberOfVariables(c.prohibitedItemIds));        if (!ListUtil.isEmpty(c.indexIds))            statement.append(" AND index_id IN").append(DbUtil.suitableNumberOfVariables(c.indexIds));        if (!ListUtil.isEmpty(c.dates))            encodeRanges(c.dates, "date", statement);                if (!ListUtil.isEmpty(c.modified))            encodeRanges(c.modified, "mod_metadata", statement);        if (!ListUtil.isEmpty(c.sizes))            encodeRanges(c.sizes, "size", statement);        statement.append(')');    }