Search in sources :

Example 1 with QueryFilterSearch

use of siena.QueryFilterSearch in project siena by mandubian.

the class BaseTest method testDumpRestoreQueryFilterSearch.

public void testDumpRestoreQueryFilterSearch() {
    Query<PersonLongAutoID> query = pm.createQuery(PersonLongAutoID.class).search("test", "firstName", "lastName");
    QueryFilterSearch qf = (QueryFilterSearch) query.getFilters().get(0);
    String str = JsonSerializer.serialize(qf).toString();
    assertNotNull(str);
    QueryFilterSearch qfRes = (QueryFilterSearch) JsonSerializer.deserialize(QueryFilter.class, Json.loads(str));
    assertNotNull(qfRes);
    assertEquals(qf.match, qfRes.match);
    for (int i = 0; i < qfRes.fields.length; i++) {
        assertEquals(qf.fields[i], qfRes.fields[i]);
    }
}
Also used : QueryFilter(siena.QueryFilter) PersonLongAutoID(siena.base.test.model.PersonLongAutoID) QueryFilterSearch(siena.QueryFilterSearch)

Example 2 with QueryFilterSearch

use of siena.QueryFilterSearch in project siena by mandubian.

the class H2PersistenceManager method doSearch.

protected <T> List<T> doSearch(Query<T> query, int limit, int offset) {
    // TODO this is a very raw impl: need some work certainly
    try {
        Connection conn = this.getConnection();
        ClassInfo ci = ClassInfo.getClassInfo(query.getQueriedClass());
        // doesn't index a table that has already been indexed
        if (!tableIndexMap.containsKey(ci.tableName)) {
            List<String> colList = ci.getUpdateFieldsColumnNames();
            String cols = null;
            if (!colList.isEmpty()) {
                cols = "";
                // removes auto generated IDs from index
                int sz = colList.size();
                for (int i = 0; i < sz; i++) {
                    if ("h2".equals(dbMode))
                        cols += colList.get(i).toUpperCase();
                    else // !!! mysql mode means case INsensitive to lowercase !!!!
                    if ("mysql".equals(dbMode))
                        cols += colList.get(i).toLowerCase();
                    else
                        cols += colList.get(i).toUpperCase();
                    if (i < sz - 1)
                        cols += ",";
                }
            }
            // creates the index
            FullText.createIndex(conn, "PUBLIC", ci.tableName.toUpperCase(), cols);
            tableIndexMap.put(ci.tableName, true);
        }
        String searchString = "";
        Iterator<QueryFilterSearch> it = query.getSearches().iterator();
        boolean first = true;
        while (it.hasNext()) {
            if (!first) {
                searchString += " ";
            } else {
                first = false;
            }
            searchString += it.next().match;
        }
        ResultSet rs = FullText.searchData(conn, searchString, limit, offset);
        List<T> res = new ArrayList<T>();
        Field idField = ci.getIdField();
        Class<?> idClass = idField.getType();
        while (rs.next()) {
            // String queryStr = rs.getString("QUERY");
            // String score = rs.getString("SCORE");
            // Array columns = rs.getArray("COLUMNS");
            Object[] keys = (Object[]) rs.getArray("KEYS").getArray();
            // convert keys into real type if the key is not a string
            Object[] realKeys = null;
            if (idField.getType() != String.class) {
                realKeys = new Object[keys.length];
                for (int i = 0; i < keys.length; i++) {
                    realKeys[i] = Util.fromString(idClass, (String) keys[i]);
                }
            } else {
                realKeys = keys;
            }
            if (res == null)
                res = this.getByKeys(query.getQueriedClass(), realKeys);
            else
                res.addAll(this.getByKeys(query.getQueriedClass(), realKeys));
        }
        return res;
    } catch (SQLException e) {
        throw new SienaException(e);
    }
}
Also used : SQLException(java.sql.SQLException) Connection(java.sql.Connection) ArrayList(java.util.ArrayList) QueryFilterSearch(siena.QueryFilterSearch) Field(java.lang.reflect.Field) ResultSet(java.sql.ResultSet) SienaException(siena.SienaException) ClassInfo(siena.ClassInfo)

Example 3 with QueryFilterSearch

use of siena.QueryFilterSearch in project siena by mandubian.

the class JdbcPersistenceManager method appendSqlWhere.

public <T> void appendSqlWhere(Query<T> query, StringBuilder sql, List<Object> parameters) {
    Class<T> clazz = query.getQueriedClass();
    JdbcClassInfo info = JdbcClassInfo.getClassInfo(clazz);
    List<QueryFilter> filters = query.getFilters();
    if (filters.isEmpty()) {
        return;
    }
    sql.append(JdbcDBUtils.WHERE);
    boolean first = true;
    for (QueryFilter filter : filters) {
        if (QueryFilterSimple.class.isAssignableFrom(filter.getClass())) {
            QueryFilterSimple qf = (QueryFilterSimple) filter;
            String op = qf.operator;
            Object value = qf.value;
            Field f = qf.field;
            if (!first) {
                sql.append(JdbcDBUtils.AND);
            }
            first = false;
            String[] columns = ClassInfo.getColumnNames(f, info.tableName);
            if ("IN".equals(op)) {
                if (!Collection.class.isAssignableFrom(value.getClass()))
                    throw new SienaException("Collection needed when using IN operator in filter() query");
                StringBuilder s = new StringBuilder();
                Collection<?> col = (Collection<?>) value;
                for (Object object : col) {
                    // TODO: if object isModel
                    parameters.add(object);
                    s.append(",?");
                }
                sql.append(columns[0] + " IN(" + s.toString().substring(1) + ")");
            } else if (ClassInfo.isModel(f.getType())) {
                if (!op.equals("=")) {
                    throw new SienaException("Unsupported operator for relationship: " + op);
                }
                JdbcClassInfo classInfo = JdbcClassInfo.getClassInfo(f.getType());
                int i = 0;
                JdbcMappingUtils.checkForeignKeyMapping(classInfo.keys, columns, query.getQueriedClass(), f);
                for (Field key : classInfo.keys) {
                    if (value == null) {
                        sql.append(columns[i++] + JdbcDBUtils.IS_NULL);
                    } else {
                        sql.append(columns[i++] + "=?");
                        key.setAccessible(true);
                        Object o;
                        try {
                            o = key.get(value);
                            parameters.add(o);
                        } catch (Exception e) {
                            throw new SienaException(e);
                        }
                    }
                }
            } else {
                if (value == null && op.equals("=")) {
                    sql.append(columns[0] + JdbcDBUtils.IS_NULL);
                } else if (value == null && op.equals("!=")) {
                    sql.append(columns[0] + JdbcDBUtils.IS_NOT_NULL);
                } else {
                    sql.append(columns[0] + op + "?");
                    if (value == null) {
                        parameters.add(Types.NULL);
                    } else {
                        if (value instanceof Date) {
                            value = Util.translateDate(f, (Date) value);
                        } else if (value instanceof Enum) {
                            value = value.toString();
                        }
                        parameters.add(value);
                    }
                }
            }
        } else if (QueryFilterSearch.class.isAssignableFrom(filter.getClass())) {
            // TODO MYSQL implementation manages only 1 search in a query
            if (query.getSearches().size() > 1) {
                throw new SienaRestrictedApiException(DB, "search", "MySQL implementation manages only on single search at a time in a query");
            }
            // adds querysearch
            QueryFilterSearch qf = (QueryFilterSearch) filter;
            appendSqlSearch(qf, clazz, info, sql, parameters);
        }
    }
}
Also used : SienaRestrictedApiException(siena.SienaRestrictedApiException) SQLException(java.sql.SQLException) SienaException(siena.SienaException) IOException(java.io.IOException) SienaRestrictedApiException(siena.SienaRestrictedApiException) Date(java.util.Date) QueryFilterSearch(siena.QueryFilterSearch) Field(java.lang.reflect.Field) QueryFilter(siena.QueryFilter) QueryFilterSimple(siena.QueryFilterSimple) Collection(java.util.Collection) SienaException(siena.SienaException)

Example 4 with QueryFilterSearch

use of siena.QueryFilterSearch in project siena by mandubian.

the class SdbMappingUtils method buildFilterOrder.

public static <T> StringBuilder buildFilterOrder(Query<T> query, StringBuilder q) {
    List<QueryFilter> filters = query.getFilters();
    Set<Field> filteredFields = new HashSet<Field>();
    boolean first = true;
    if (!filters.isEmpty()) {
        q.append(WHERE);
        for (QueryFilter filter : filters) {
            if (QueryFilterSimple.class.isAssignableFrom(filter.getClass())) {
                QueryFilterSimple qf = (QueryFilterSimple) filter;
                Field f = qf.field;
                Object value = qf.value;
                String op = qf.operator;
                // for order verification in case the order is not on a filtered field
                filteredFields.add(f);
                if (!first) {
                    q.append(AND);
                }
                first = false;
                String[] columns = ClassInfo.getColumnNames(f);
                if ("IN".equals(op)) {
                    if (!Collection.class.isAssignableFrom(value.getClass()))
                        throw new SienaException("Collection needed when using IN operator in filter() query");
                    StringBuilder s = new StringBuilder();
                    Collection<?> col = (Collection<?>) value;
                    for (Object object : col) {
                        // TO BE VERIFIED: SHOULD BE MANAGED by toString!!!
                        if (object != null) {
                            s.append("," + SimpleDB.quote(toString(f, object)));
                        } else {
                            throw new SienaException("Can't use NULL in collection for IN operator");
                        }
                    }
                    String column = null;
                    if (ClassInfo.isId(f)) {
                        column = ITEM_NAME;
                    } else {
                        column = ClassInfo.getColumnNames(f)[0];
                    }
                    q.append(column + " in(" + s.toString().substring(1) + ")");
                } else if (ClassInfo.isModel(f.getType())) {
                    // TODO could manage other ops here
                    if (!op.equals("=")) {
                        throw new SienaException("Unsupported operator for relationship: " + op);
                    }
                    ClassInfo relInfo = ClassInfo.getClassInfo(f.getType());
                    int i = 0;
                    for (Field key : relInfo.keys) {
                        if (value == null) {
                            q.append(columns[i++] + IS_NULL);
                        } else {
                            q.append(columns[i++] + op + SimpleDB.quote(objectFieldToString(value, key)));
                        }
                    }
                } else {
                    String column = null;
                    if (ClassInfo.isId(f)) {
                        column = "itemName()";
                        if (value == null && op.equals("=")) {
                            throw new SienaException("SDB filter on @Id field with 'IS NULL' is not possible");
                        }
                    } else {
                        column = ClassInfo.getColumnNames(f)[0];
                    }
                    if (value == null && op.equals("=")) {
                        q.append(column + IS_NULL);
                    } else if (value == null && op.equals("!=")) {
                        q.append(column + IS_NOT_NULL);
                    } else {
                        q.append(column + op + SimpleDB.quote(toString(f, value)));
                    }
                }
            } else if (QueryFilterSearch.class.isAssignableFrom(filter.getClass())) {
                Class<T> clazz = query.getQueriedClass();
                QueryFilterSearch qf = (QueryFilterSearch) filter;
                // throw new SienaException("Search not possible for several fields in SDB: only one field");
                try {
                    // Field field = Util.getField(clazz, qf.fields[0]);
                    // if(field.isAnnotationPresent(Unindexed.class)){
                    // throw new SienaException("Cannot search the @Unindexed field "+field.getName());
                    // }
                    // cuts match into words
                    String[] words = qf.match.split("\\s");
                    // if several words, then only OR operator represented by IN GAE
                    Pattern pNormal = Pattern.compile("[\\%]*(\\w+)[\\%]*");
                    if (!first) {
                        q.append(AND);
                    }
                    // forces true
                    first = true;
                    q.append(" ( ");
                    for (String f : qf.fields) {
                        Field field = Util.getField(clazz, f);
                        if (!first) {
                            q.append(OR);
                        }
                        first = false;
                        q.append(" ( ");
                        String column = null;
                        if (ClassInfo.isId(field)) {
                            column = "itemName()";
                        } else {
                            column = ClassInfo.getColumnNames(field)[0];
                        }
                        first = true;
                        for (String word : words) {
                            if (!first) {
                                q.append(OR);
                            }
                            first = false;
                            if (!pNormal.matcher(word).matches()) {
                                throw new SienaException("'" + word + "' doesn't match pattern [\\%]*(\\w+)[\\%]*");
                            }
                            if (word.contains("%")) {
                                q.append(column + LIKE + SimpleDB.quote(word));
                            } else {
                                q.append(column + EQ + SimpleDB.quote(word));
                            }
                        }
                        q.append(" ) ");
                    }
                    q.append(" ) ");
                } catch (Exception e) {
                    throw new SienaException(e);
                }
            }
        }
    }
    List<QueryOrder> orders = query.getOrders();
    if (!orders.isEmpty()) {
        QueryOrder last = orders.get(orders.size() - 1);
        Field field = last.field;
        if (ClassInfo.isId(field)) {
            if (!filteredFields.contains(field)) {
                if (filters.isEmpty()) {
                    q.append(WHERE);
                } else {
                    q.append(AND);
                }
                q.append(ITEM_NAME + IS_NOT_NULL);
            }
            q.append(ORDER_BY + ITEM_NAME);
        } else {
            String column = ClassInfo.getColumnNames(field)[0];
            if (!filteredFields.contains(field)) {
                if (filters.isEmpty()) {
                    q.append(WHERE);
                } else {
                    q.append(AND);
                }
                q.append(column + IS_NOT_NULL);
            }
            q.append(ORDER_BY + column);
        }
        if (!last.ascending)
            q.append(DESC);
    }
    QueryOptionSdbContext sdbCtx = (QueryOptionSdbContext) query.option(QueryOptionSdbContext.ID);
    QueryOptionOffset off = (QueryOptionOffset) query.option(QueryOptionOffset.ID);
    if (sdbCtx != null && sdbCtx.realPageSize != 0) {
        if (off != null && off.isActive()) {
            // if offset is active, adds it to the page size to be sure to retrieve enough elements
            q.append(LIMIT + (sdbCtx.realPageSize + off.offset));
        } else {
            q.append(LIMIT + sdbCtx.realPageSize);
        }
    }
    return q;
}
Also used : Pattern(java.util.regex.Pattern) QueryOptionOffset(siena.core.options.QueryOptionOffset) SienaException(siena.SienaException) SienaRestrictedApiException(siena.SienaRestrictedApiException) IOException(java.io.IOException) QueryFilterSearch(siena.QueryFilterSearch) QueryOrder(siena.QueryOrder) Field(java.lang.reflect.Field) QueryFilter(siena.QueryFilter) QueryFilterSimple(siena.QueryFilterSimple) Collection(java.util.Collection) SienaException(siena.SienaException) HashSet(java.util.HashSet) ClassInfo(siena.ClassInfo)

Example 5 with QueryFilterSearch

use of siena.QueryFilterSearch in project siena by mandubian.

the class H2PersistenceManager method doSearchCount.

protected <T> int doSearchCount(Query<T> query) {
    // TODO this is a very raw impl: need some work certainly
    try {
        Connection conn = this.getConnection();
        ClassInfo ci = ClassInfo.getClassInfo(query.getQueriedClass());
        // doesn't index a table that has already been indexed
        if (!tableIndexMap.containsKey(ci.tableName)) {
            List<String> colList = ci.getUpdateFieldsColumnNames();
            String cols = null;
            if (!colList.isEmpty()) {
                cols = "";
                // removes auto generated IDs from index
                int sz = colList.size();
                for (int i = 0; i < sz; i++) {
                    if ("h2".equals(dbMode))
                        cols += colList.get(i).toUpperCase();
                    else // !!! mysql mode means case INsensitive to lowercase !!!!
                    if ("mysql".equals(dbMode))
                        cols += colList.get(i).toLowerCase();
                    else
                        cols += colList.get(i).toUpperCase();
                    if (i < sz - 1)
                        cols += ",";
                }
            }
            // creates the index
            FullText.createIndex(conn, "PUBLIC", ci.tableName.toUpperCase(), cols);
            tableIndexMap.put(ci.tableName, true);
        }
        String searchString = "";
        Iterator<QueryFilterSearch> it = query.getSearches().iterator();
        boolean first = true;
        while (it.hasNext()) {
            if (!first) {
                searchString += " ";
            } else {
                first = false;
            }
            searchString += it.next().match;
        }
        ResultSet rs = FullText.searchData(conn, searchString, 0, 0);
        int count = 0;
        while (rs.next()) {
            // String queryStr = rs.getString("QUERY");
            // String score = rs.getString("SCORE");
            // Array columns = rs.getArray("COLUMNS");
            Object[] keys = (Object[]) rs.getArray("KEYS").getArray();
            count += keys.length;
        }
        return count;
    } catch (SQLException e) {
        throw new SienaException(e);
    }
}
Also used : SQLException(java.sql.SQLException) Connection(java.sql.Connection) QueryFilterSearch(siena.QueryFilterSearch) ResultSet(java.sql.ResultSet) SienaException(siena.SienaException) ClassInfo(siena.ClassInfo)

Aggregations

QueryFilterSearch (siena.QueryFilterSearch)7 SienaException (siena.SienaException)6 Field (java.lang.reflect.Field)5 SQLException (java.sql.SQLException)4 ClassInfo (siena.ClassInfo)4 QueryFilter (siena.QueryFilter)4 Connection (java.sql.Connection)3 ResultSet (java.sql.ResultSet)3 ArrayList (java.util.ArrayList)3 Collection (java.util.Collection)3 QueryFilterSimple (siena.QueryFilterSimple)3 SienaRestrictedApiException (siena.SienaRestrictedApiException)3 IOException (java.io.IOException)2 Pattern (java.util.regex.Pattern)2 QueryOrder (siena.QueryOrder)2 Key (com.google.appengine.api.datastore.Key)1 FilterOperator (com.google.appengine.api.datastore.Query.FilterOperator)1 Date (java.util.Date)1 HashSet (java.util.HashSet)1 List (java.util.List)1