Changeset 1917


Ignore:
Timestamp:
Jun 8, 2011, 11:24:23 AM (9 years ago)
Author:
robert@…
Message:

Solved bugs in searching:

  • exception when searching for [any field in any object] equals "" (#480)
  • the authentication in searching works properly again
Location:
trunk/src/groovy/dbnp/query
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/groovy/dbnp/query/Criterion.groovy

    r1913 r1917  
    194194                        case 'Template':
    195195                        case 'Module':
     196                        case 'File':
    196197                                return value?.toString();
    197                         case 'File':
    198                                 return null; // Never search in filenames, since they are not very descriptive
    199198                        case 'Date':
    200199                                // The comparison with date values should only be performed iff the value
     
    296295               
    297296                // If no value is given, don't do anything
    298                 if( !value )
     297                if( value == null )
    299298                        return emptyCriterion;
    300299               
     
    398397                }
    399398
    400                 def where = whereClause?.findAll { it } ? "( " + whereClause.join( " OR " ) + " )" : ""
     399                def where = whereClause?.findAll { it } ? "( " + whereClause.findAll { it }.join( " OR " ) + " )" : ""
    401400               
    402401                return [ "join": joinClause, "where": where , "parameters": parameters ];
     
    423422                       
    424423                        def fieldName = field.name;
     424                        def condition
    425425                       
     426                        // Searching in (complex) domain fields with value NULL will result in the whole
     427                        // where clause to fail. e.g.:
     428                        //
     429                        // SELECT * FROM Sample sample WHERE sample.material LIKE '%m%' OR 1 = 1
     430                        // should result in all samples. However, it only results in those samples
     431                        // with sample.material =! NULL.
     432                        //
     433                        // For that reason, we use a subquery to select those 
    426434                        if(     ( objectToSearchIn.toLowerCase() == "subject" && fieldName.toLowerCase() == "species" ) ||
    427435                                ( objectToSearchIn.toLowerCase() == "sample" && fieldName.toLowerCase() == "material" ) ||
    428436                                ( objectToSearchIn.toLowerCase() == "assay" && fieldName.toLowerCase() == "module" ) ||
    429437                                ( objectToSearchIn.toLowerCase() == "samplingevent" && fieldName.toLowerCase() == "sampletemplate" ) ) {
     438                               
     439                                condition = manyToManyWhereCondition( objectToSearchIn, fieldName, prefix, "name", value );
    430440                                fieldName += ".name"
    431                         }
    432                        
    433                         // Search in template name
    434                         def condition = extendWhereClause( "( %s )", objectToSearchIn + "." + fieldName, prefix, criterionType, castValue( criterionType ) );
     441                        } else {
     442                                condition = extendWhereClause( "( %s )", objectToSearchIn + "." + fieldName, prefix, criterionType, castValue( criterionType ) );
     443                        }
     444
     445                        // Search in fields
    435446                        whereClause += condition[ "where" ];
    436447       
     
    468479                switch( this.operator ) {
    469480                        case Operator.contains:
     481                                // Every field contains an empty string, so we don't search on it
     482                                if( !fieldValue )
     483                                        return [ "where": "", "parameters": [:] ]
     484                                       
    470485                                // Text fields should be handled case insensitive
     486                                def clause
    471487                                if( textFieldTypes.contains( fieldType ) ) {
    472                                         hql = sprintf( hql, "lower( " + fieldName + ") like lower( :" + uniquePrefix + "ValueLike )" );
     488                                        clause = "lower( " + fieldName + ") like lower( :" + uniquePrefix + "ValueLike )"
    473489                                } else {
    474                                         hql = sprintf( hql, fieldName + " like :" + uniquePrefix + "ValueLike" );
     490                                        clause = fieldName + " like :" + uniquePrefix + "ValueLike";
    475491                                }
     492                               
     493                                hql = sprintf( hql, clause );
    476494                                parameters[ uniquePrefix + "ValueLike" ] = "%" + fieldValue + "%"
    477495                                break;
     
    481499                        case Operator.lte:
    482500                        case Operator.lt:
     501                                // Text fields should be handled case insensitive
     502                                def clause;
    483503                                if( textFieldTypes.contains( fieldType ) ) {
    484                                         hql = sprintf( hql, "lower( " + fieldName + " ) "  + this.operator.name + " lower( :" + uniquePrefix + "Value" + fieldType + ")" );
     504                                        clause = "lower( " + fieldName + " ) "  + this.operator.name + " lower( :" + uniquePrefix + "Value" + fieldType + ")"
    485505                                } else {
    486                                         hql = sprintf( hql, fieldName + " "  + this.operator.name + " :" + uniquePrefix + "Value" + fieldType );
     506                                        clause = fieldName + " "  + this.operator.name + " :" + uniquePrefix + "Value" + fieldType
    487507                                }
     508                               
     509                                // If the user searches for an empty string, it should also match the database NULL value
     510                                if( operator == Operator.equals && !fieldValue ) {
     511                                        clause += " OR " + fieldName + " IS NULL"
     512                                }
     513                               
     514                                hql = sprintf( hql, clause );
    488515                                parameters[ uniquePrefix + "Value" + fieldType ] = fieldValue
    489516                                break;
     
    509536                def parameters = [:]
    510537
     538                // If looking for a specific field, that field should also be mentioned in the where clause
    511539                if( this.field != '*' ) {
    512540                        condition = "( %s AND index(" + fieldName + ") = :" + uniquePrefix + "Field )"
  • trunk/src/groovy/dbnp/query/Search.groovy

    r1913 r1917  
    168168                }
    169169               
     170                // Generate where clause
     171                def whereClause = " WHERE ";
     172                if( fullHQL.where ) {
     173                        whereClause += " ( " + fullHQL.where.join( " " + searchMode.toString() + " "  ) + " ) "
     174                        whereClause += " AND ";
     175                }
     176               
     177                // Add a filter such that only readable studies are returned
     178                def studyName = elementName( "Study" );
     179                if( this.user == null ) {
     180                        // Anonymous readers are only given access when published and public
     181                        whereClause +=  " ( " + studyName + ".publicstudy = true AND " + studyName + ".published = true )"
     182                } else if( !this.user.hasAdminRights() ) {
     183                        // Administrators are allowed to read every study
     184
     185                        // Owners and writers are allowed to read this study
     186                        // Readers are allowed to read this study when it is published
     187                        whereClause += " ( " + studyName + ".owner = :sessionUser OR :sessionUser member of " + studyName + ".writers OR ( :sessionUser member of " + studyName + ".readers AND " + studyName + ".published = true ) )"
     188                        fullHQL.parameters[ "sessionUser" ] = this.user
     189                }
     190               
    170191                // Combine all parts to generate a full HQL query
    171                 def hqlQuery = selectClause + " " + fullHQL.from + ( fullHQL.where ? "  WHERE " + fullHQL.where.join( " " + searchMode.toString() + " "  ) : "" );
    172                
     192                def hqlQuery = selectClause + " " + fullHQL.from + whereClause;
    173193               
    174194                // Find all objects
     
    387407                       
    388408                // Wildcards should be checked within each entity
    389                 def wildcardHQL = createHQLForEntity( this.entity, null, false );
     409                def wildcardHQL = createHQLForEntity( this.entity, entityCriteria, false );
    390410               
    391411                // Create SQL for other entities, by executing a subquery first, and
     
    411431                if( whereClauses ) {
    412432                        fullHQL.from += wildcardHQL.from
    413                         fullHQL.where << whereClauses.join( " OR " )
     433                        fullHQL.where << whereClauses.findAll { it }.join( " OR " )
    414434                         
    415435                        wildcardHQL[ "parameters" ].each {
     
    440460                entityCriteria.each {
    441461                        def criteriaHQL = it.toHQL( "criterion" +entityName + criterionNum++, entityName.toLowerCase() );
    442                         fromClause += " " + criteriaHQL[ "join" ]
    443                         whereClause << criteriaHQL[ "where" ]
     462                       
     463                        if( criteriaHQL[ "join" ] )
     464                                fromClause += " " + criteriaHQL[ "join" ]
     465                               
     466                        if( criteriaHQL[ "where" ] )
     467                                whereClause << criteriaHQL[ "where" ]
     468                               
    444469                        criteriaHQL[ "parameters" ].each {
    445470                                parameters[ it.key ] = it.value
    446                         }
    447                 }
    448                
    449                 // Add a filter such that only readable studies are returned
    450                 if( entityName == "Study" ) {
    451                        
    452                         if( this.user == null ) {
    453                                 // Anonymous readers are only given access when published and public
    454                                 whereClause << "( study.publicstudy = true AND study.published = true )"
    455                         } else if( !this.user.hasAdminRights() ) {
    456                                 // Administrators are allowed to read every study
    457 
    458                                 // Owners and writers are allowed to read this study
    459                                 // Readers are allowed to read this study when it is published
    460                                 whereClause << "( study.owner = :sessionUser OR :sessionUser member of study.writers OR ( :sessionUser member of study.readers AND study.published = true ) )"
    461                                 parameters[ "sessionUser" ] = this.user
    462471                        }
    463472                }
Note: See TracChangeset for help on using the changeset viewer.