From 82e5f6038b8c49c9ee4e35f97446538386845f92 Mon Sep 17 00:00:00 2001 From: Brendan Abolivier Date: Wed, 16 Aug 2017 16:07:13 +0100 Subject: [PATCH] Support filtering --- .../publicroomsapi/directory/public_rooms.go | 8 +- .../publicroomsapi/storage/prepare.go | 35 ++++++++ .../storage/public_rooms_table.go | 88 ++++++++++++------- .../publicroomsapi/storage/storage.go | 4 +- 4 files changed, 100 insertions(+), 35 deletions(-) create mode 100644 src/github.com/matrix-org/dendrite/publicroomsapi/storage/prepare.go diff --git a/src/github.com/matrix-org/dendrite/publicroomsapi/directory/public_rooms.go b/src/github.com/matrix-org/dendrite/publicroomsapi/directory/public_rooms.go index 93c9302c0..ea99636e2 100644 --- a/src/github.com/matrix-org/dendrite/publicroomsapi/directory/public_rooms.go +++ b/src/github.com/matrix-org/dendrite/publicroomsapi/directory/public_rooms.go @@ -28,7 +28,11 @@ import ( type publicRoomReq struct { Since string `json:"since,omitempty"` Limit int16 `json:"limit,omitempty"` - Filter string `json:"filter,omitempty"` + Filter filter `json:"filter,omitempty"` +} + +type filter struct { + SearchTerms string `json:"generic_search_term,omitempty"` } type publicRoomRes struct { @@ -70,7 +74,7 @@ func GetPublicRooms( response.NextBatch = strconv.Itoa(int(offset) + int(limit)) } - if response.Chunk, err = publicRoomDatabase.GetPublicRooms(offset, limit); err != nil { + if response.Chunk, err = publicRoomDatabase.GetPublicRooms(offset, limit, request.Filter.SearchTerms); err != nil { return httputil.LogThenError(req, err) } diff --git a/src/github.com/matrix-org/dendrite/publicroomsapi/storage/prepare.go b/src/github.com/matrix-org/dendrite/publicroomsapi/storage/prepare.go new file mode 100644 index 000000000..b19765992 --- /dev/null +++ b/src/github.com/matrix-org/dendrite/publicroomsapi/storage/prepare.go @@ -0,0 +1,35 @@ +// Copyright 2017 Vector Creations Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package storage + +import ( + "database/sql" +) + +// a statementList is a list of SQL statements to prepare and a pointer to where to store the resulting prepared statement. +type statementList []struct { + statement **sql.Stmt + sql string +} + +// prepare the SQL for each statement in the list and assign the result to the prepared statement. +func (s statementList) prepare(db *sql.DB) (err error) { + for _, statement := range s { + if *statement.statement, err = db.Prepare(statement.sql); err != nil { + return + } + } + return +} diff --git a/src/github.com/matrix-org/dendrite/publicroomsapi/storage/public_rooms_table.go b/src/github.com/matrix-org/dendrite/publicroomsapi/storage/public_rooms_table.go index 37b42b06d..f0632693b 100644 --- a/src/github.com/matrix-org/dendrite/publicroomsapi/storage/public_rooms_table.go +++ b/src/github.com/matrix-org/dendrite/publicroomsapi/storage/public_rooms_table.go @@ -71,12 +71,32 @@ const selectPublicRoomsSQL = "" + " ORDER BY joined_members DESC" + " OFFSET $1" -const selectPublicRoomswithLimitSQL = "" + +const selectPublicRoomsWithLimitSQL = "" + "SELECT room_id, joined_members, aliases, canonical_alias, name, topic, world_readable, guest_can_join, avatar_url" + " FROM publicroomsapi_public_rooms WHERE visibility = true" + " ORDER BY joined_members DESC" + " OFFSET $1 LIMIT $2" +const selectPublicRoomsWithFilterSQL = "" + + "SELECT room_id, joined_members, aliases, canonical_alias, name, topic, world_readable, guest_can_join, avatar_url" + + " FROM publicroomsapi_public_rooms" + + " WHERE visibility = true" + + " AND (LOWER(name) LIKE LOWER($1)" + + " OR LOWER(topic) LIKE LOWER($1)" + + " OR LOWER(ARRAY_TO_STRING(aliases, ',')) LIKE LOWER($1))" + + " ORDER BY joined_members DESC" + + " OFFSET $2" + +const selectPublicRoomsWithLimitAndFilterSQL = "" + + "SELECT room_id, joined_members, aliases, canonical_alias, name, topic, world_readable, guest_can_join, avatar_url" + + " FROM publicroomsapi_public_rooms" + + " WHERE visibility = true" + + " AND (LOWER(name) LIKE LOWER($1)" + + " OR LOWER(topic) LIKE LOWER($1)" + + " OR LOWER(ARRAY_TO_STRING(aliases, ',')) LIKE LOWER($1))" + + " ORDER BY joined_members DESC" + + " OFFSET $2 LIMIT $3" + const selectRoomVisibilitySQL = "" + "SELECT visibility FROM publicroomsapi_public_rooms" + " WHERE room_id = $1" @@ -101,14 +121,16 @@ const updateRoomAttributeSQL = "" + " WHERE room_id = $2" type publicRoomsStatements struct { - countPublicRoomsStmt *sql.Stmt - selectPublicRoomsStmt *sql.Stmt - selectPublicRoomswithLimitStmt *sql.Stmt - selectRoomVisibilityStmt *sql.Stmt - insertNewRoomStmt *sql.Stmt - incrementJoinedMembersInRoomStmt *sql.Stmt - decrementJoinedMembersInRoomStmt *sql.Stmt - updateRoomAttributeStmts map[string]*sql.Stmt + countPublicRoomsStmt *sql.Stmt + selectPublicRoomsStmt *sql.Stmt + selectPublicRoomsWithLimitStmt *sql.Stmt + selectPublicRoomsWithFilterStmt *sql.Stmt + selectPublicRoomsWithLimitAndFilterStmt *sql.Stmt + selectRoomVisibilityStmt *sql.Stmt + insertNewRoomStmt *sql.Stmt + incrementJoinedMembersInRoomStmt *sql.Stmt + decrementJoinedMembersInRoomStmt *sql.Stmt + updateRoomAttributeStmts map[string]*sql.Stmt } func (s *publicRoomsStatements) prepare(db *sql.DB) (err error) { @@ -116,25 +138,20 @@ func (s *publicRoomsStatements) prepare(db *sql.DB) (err error) { if err != nil { return } - if s.countPublicRoomsStmt, err = db.Prepare(countPublicRoomsSQL); err != nil { - return + + stmts := statementList{ + {&s.countPublicRoomsStmt, countPublicRoomsSQL}, + {&s.selectPublicRoomsStmt, selectPublicRoomsSQL}, + {&s.selectPublicRoomsWithLimitStmt, selectPublicRoomsWithLimitSQL}, + {&s.selectPublicRoomsWithFilterStmt, selectPublicRoomsWithFilterSQL}, + {&s.selectPublicRoomsWithLimitAndFilterStmt, selectPublicRoomsWithLimitAndFilterSQL}, + {&s.selectRoomVisibilityStmt, selectRoomVisibilitySQL}, + {&s.insertNewRoomStmt, insertNewRoomSQL}, + {&s.incrementJoinedMembersInRoomStmt, incrementJoinedMembersInRoomSQL}, + {&s.decrementJoinedMembersInRoomStmt, decrementJoinedMembersInRoomSQL}, } - if s.selectPublicRoomsStmt, err = db.Prepare(selectPublicRoomsSQL); err != nil { - return - } - if s.selectPublicRoomswithLimitStmt, err = db.Prepare(selectPublicRoomswithLimitSQL); err != nil { - return - } - if s.selectRoomVisibilityStmt, err = db.Prepare(selectRoomVisibilitySQL); err != nil { - return - } - if s.insertNewRoomStmt, err = db.Prepare(insertNewRoomSQL); err != nil { - return - } - if s.incrementJoinedMembersInRoomStmt, err = db.Prepare(incrementJoinedMembersInRoomSQL); err != nil { - return - } - if s.decrementJoinedMembersInRoomStmt, err = db.Prepare(decrementJoinedMembersInRoomSQL); err != nil { + + if err = stmts.prepare(db); err != nil { return } @@ -154,14 +171,23 @@ func (s *publicRoomsStatements) countPublicRooms() (nb int64, err error) { return } -func (s *publicRoomsStatements) selectPublicRooms(offset int64, limit int16) ([]types.PublicRoom, error) { +func (s *publicRoomsStatements) selectPublicRooms(offset int64, limit int16, filter string) ([]types.PublicRoom, error) { var rows *sql.Rows var err error - if limit == 0 { - rows, err = s.selectPublicRoomsStmt.Query(offset) + if len(filter) > 0 { + pattern := "%" + filter + "%" + if limit == 0 { + rows, err = s.selectPublicRoomsWithFilterStmt.Query(pattern, offset) + } else { + rows, err = s.selectPublicRoomsWithLimitAndFilterStmt.Query(pattern, offset, limit) + } } else { - rows, err = s.selectPublicRoomswithLimitStmt.Query(offset, limit) + if limit == 0 { + rows, err = s.selectPublicRoomsStmt.Query(offset) + } else { + rows, err = s.selectPublicRoomsWithLimitStmt.Query(offset, limit) + } } if err != nil { diff --git a/src/github.com/matrix-org/dendrite/publicroomsapi/storage/storage.go b/src/github.com/matrix-org/dendrite/publicroomsapi/storage/storage.go index a93a49836..664ed1649 100644 --- a/src/github.com/matrix-org/dendrite/publicroomsapi/storage/storage.go +++ b/src/github.com/matrix-org/dendrite/publicroomsapi/storage/storage.go @@ -86,8 +86,8 @@ func (d *PublicRoomsServerDatabase) CountPublicRooms() (int64, error) { // If the limit is 0, doesn't limit the number of results. If the offset is 0 too, the array contains all // the rooms set as publicly visible on the server. // Returns an error if the retrieval failed. -func (d *PublicRoomsServerDatabase) GetPublicRooms(offset int64, limit int16) ([]types.PublicRoom, error) { - return d.statements.selectPublicRooms(offset, limit) +func (d *PublicRoomsServerDatabase) GetPublicRooms(offset int64, limit int16, filter string) ([]types.PublicRoom, error) { + return d.statements.selectPublicRooms(offset, limit, filter) } // UpdateRoomFromEvent updates the database representation of a room from a Matrix event, by