Simplified db schema

This commit is contained in:
emeric
2014-11-24 19:42:33 +01:00
parent f7edebaf8e
commit b9657a5680
24 changed files with 485 additions and 691 deletions
+4 -3
View File
@@ -28,6 +28,7 @@
#include "logger/Logger.hpp"
#include "TableFilter.hpp"
#include "TableFilterGenre.hpp"
#include "KeywordSearchFilter.hpp"
#include "TrackView.hpp"
#include "PlayQueue.hpp"
@@ -49,17 +50,17 @@ _mediaPlayer(nullptr)
Wt::WHBoxLayout *filterLayout = new Wt::WHBoxLayout();
{
TableFilter *filter = new TableFilter(_db, "genre", "name");
TableFilterGenre *filter = new TableFilterGenre(_db);
filterLayout->addWidget(filter);
_filterChain.addFilter(filter);
}
{
TableFilter *filter = new TableFilter(_db, "artist", "name");
TableFilter *filter = new TableFilter(_db, "track", "artist_name");
filterLayout->addWidget(filter);
_filterChain.addFilter(filter);
}
{
TableFilter *filter = new TableFilter(_db, "release", "name");
TableFilter *filter = new TableFilter(_db, "track", "release_name");
filterLayout->addWidget(filter);
_filterChain.addFilter(filter);
}
-3
View File
@@ -52,9 +52,6 @@ FilterChain::updateFilters(std::size_t startIdx)
Filter::Constraint currentConstraint;
// TODO: replace with inner joins?
currentConstraint.where.And( WhereClause( "track.artist_id = artist.id and track.release_id = release.id and track_genre.track_id = track.id and genre.id = track_genre.genre_id"));
for (std::size_t idFilter = 0; idFilter < _filters.size(); ++idFilter)
{
Filter* filter = _filters.at(idFilter);
+1 -1
View File
@@ -39,7 +39,7 @@ KeywordSearchFilter::getConstraint(Constraint& constraint)
// No active search means no constaint!
if (!_lastEmittedText.empty()) {
const std::string bindText ("%%" + _lastEmittedText + "%%");
constraint.where.And( WhereClause("(track.name like ? or release.name like ? or artist.name like ?)").bind(bindText).bind(bindText).bind(bindText));
constraint.where.And( WhereClause("(track.name like ? or track.release_name like ? or track.artist_name like ? or track.genre_list like ?)").bind(bindText).bind(bindText).bind(bindText).bind(bindText));
}
// else no constraint!
+1 -1
View File
@@ -87,7 +87,7 @@ PlayQueue::addTracks(const std::vector<Database::Track::id_type>& trackIds)
_model->setData(dataRow, 0, track.id());
_model->setData(dataRow, 1, dataRow + 1);
_model->setData(dataRow, 2, track->getArtist()->getName() + " - " + track->getName());
_model->setData(dataRow, 2, track->getArtistName() + " - " + track->getName());
_model->setData(dataRow, 3, track->getDuration());
}
}
+10 -19
View File
@@ -32,9 +32,9 @@ _db(db),
_table(table),
_field(field)
{
_queryModel.setQuery( _db.getSession().query< ResultType >("select " + _table + "." + _field + ",count(DISTINCT track.id),0 as ORDERBY from track,artist,release,genre,track_genre WHERE track.artist_id = artist.id and track.release_id = release.id and track_genre.track_id = track.id and genre.id = track_genre.genre_id GROUP BY " + _table + "." + _field + " UNION select '<All>',0,1 AS ORDERBY").orderBy("ORDERBY DESC," + _table + "." + _field));
_queryModel.addColumn( _table + "." + _field, table);
_queryModel.addColumn( "count(DISTINCT track.id)", "Tracks");
_queryModel.setQuery( _db.getSession().query< ResultType >("select track." + _field + ", COUNT(DISTINCT track.id) from track GROUP BY track." + _field).orderBy("track." + _field));
_queryModel.addColumn( "track." + _field, field);
_queryModel.addColumn( "COUNT(DISTINCT track.id)", "tracks");
this->setSelectionMode(Wt::ExtendedSelection);
this->setSortingEnabled(false);
@@ -67,19 +67,16 @@ TableFilter::refresh(const Constraint& constraint)
{
SqlQuery sqlQuery;
sqlQuery.select(_table + "." + _field + ",count(DISTINCT track.id),0 as ORDERBY");
sqlQuery.from().And( FromClause("artist,release,track,genre,track_genre")) ;
sqlQuery.select("track." + _field + ", COUNT(DISTINCT track.id)");
sqlQuery.from().And( FromClause("track")) ;
sqlQuery.where().And(constraint.where); // Add constraint made by other filters
sqlQuery.groupBy().And( _table + "." + _field); // Add constraint made by other filters
sqlQuery.groupBy().And( "track." + _field); // Add constraint made by other filters
SqlQuery AllSqlQuery;
AllSqlQuery.select("'<All>',0,1 AS ORDERBY");
LMS_LOG(MOD_UI, SEV_DEBUG) << _table << ", generated query = '" << sqlQuery.get() << "'";
LMS_LOG(MOD_UI, SEV_DEBUG) << _table << ", generated query = '" << sqlQuery.get() + " UNION " + AllSqlQuery.get() << "'";
Wt::Dbo::Query<ResultType> query = _db.getSession().query<ResultType>( sqlQuery.get() );
Wt::Dbo::Query<ResultType> query = _db.getSession().query<ResultType>( sqlQuery.get() + " UNION " + AllSqlQuery.get() );
query.orderBy("ORDERBY DESC," + _table + "." + _field);
query.orderBy(_table + "." + _field);
BOOST_FOREACH(const std::string& bindArg, sqlQuery.where().getBindArgs()) {
LMS_LOG(MOD_UI, SEV_DEBUG) << "Binding value '" << bindArg << "'";
@@ -108,13 +105,7 @@ TableFilter::getConstraint(Constraint& constraint)
const ResultType& result = _queryModel.resultRow( index.row() );
// Get the track part
std::string name( result.get<0>() );
bool isAll( result.get<2>() ) ;
if (isAll) {
// no constraint, just return
return;
}
std::string name(result.get<0>());
clause.Or(_table + "." + _field + " = ?").bind(name);
}
+1 -1
View File
@@ -50,7 +50,7 @@ class TableFilter : public Wt::WTableView, public Filter
const std::string _field;
// Name, track count, special value that means 'all' if set to 1
typedef boost::tuple<std::string, int, int> ResultType;
typedef boost::tuple<std::string, int> ResultType;
Wt::Dbo::QueryModel< ResultType > _queryModel;
};
+119
View File
@@ -0,0 +1,119 @@
/*
* Copyright (C) 2013 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <boost/foreach.hpp>
#include "logger/Logger.hpp"
#include "TableFilterGenre.hpp"
namespace UserInterface {
TableFilterGenre::TableFilterGenre(Database::Handler& db, Wt::WContainerWidget* parent)
: Wt::WTableView( parent ),
Filter(),
_db(db)
{
_queryModel.setQuery( _db.getSession().query< ResultType >("select genre.name, COUNT(DISTINCT track.id) from genre INNER JOIN track_genre ON track_genre.genre_id = genre.id INNER JOIN track ON track.id = track_genre.track_id").orderBy("genre.name").groupBy("genre.name").orderBy("genre.name"));
_queryModel.addColumn("genre.name", "Genre");
_queryModel.addColumn("COUNT(DISTINCT track.id)", "tracks");
this->setSelectionMode(Wt::ExtendedSelection);
this->setSortingEnabled(false);
this->setAlternatingRowColors(true);
this->setModel(&_queryModel);
this->selectionChanged().connect(this, &TableFilterGenre::emitUpdate);
setLayoutSizeAware(true);
_queryModel.setBatchSize(100);
}
void
TableFilterGenre::layoutSizeChanged (int width, int height)
{
LMS_LOG(MOD_UI, SEV_DEBUG) << "LAYOUT CHANGED!";
/* TODO
std::size_t trackColumnSize = this->columnWidth(1).toPixels() + 30 ;
// Set the remaining size for the name column
this->setColumnWidth(0, width - 7 - trackColumnSize);
*/
}
// Set constraints on this filter
void
TableFilterGenre::refresh(const Constraint& constraint)
{
SqlQuery sqlQuery;
sqlQuery.select("genre.name, COUNT(DISTINCT track.id)");
sqlQuery.from().And( std::string("genre INNER JOIN track_genre ON track_genre.genre_id = genre.id INNER JOIN track ON track.id = track_genre.track_id") );
sqlQuery.where().And(constraint.where); // Add constraint made by other filters
sqlQuery.groupBy().And( std::string("genre.name") );
LMS_LOG(MOD_UI, SEV_DEBUG) << "genre, generated query = '" << sqlQuery.get() << "'";
Wt::Dbo::Query<ResultType> query = _db.getSession().query<ResultType>( sqlQuery.get() );
query.orderBy("genre.name");
BOOST_FOREACH(const std::string& bindArg, sqlQuery.where().getBindArgs()) {
LMS_LOG(MOD_UI, SEV_DEBUG) << "Binding value '" << bindArg << "'";
query.bind(bindArg);
}
_queryModel.setQuery( query, true );
}
// Get constraint created by this filter
void
TableFilterGenre::getConstraint(Constraint& constraint)
{
Wt::WModelIndexSet indexSet = this->selectedIndexes();
// WHERE statement
WhereClause clause;
BOOST_FOREACH(Wt::WModelIndex index, indexSet) {
if (!index.isValid())
continue;
const ResultType& result = _queryModel.resultRow( index.row() );
// Get the track part
std::string name(result.get<0>());
if (name == "<None>")
clause.Or( std::string("track.genre_list = ?") ).bind("");
else
clause.Or( std::string("track.genre_list LIKE ?") ).bind("%%" + name + "%%");
}
// Adding our WHERE clause
constraint.where.And( clause );
}
} // namespace UserInterface
+59
View File
@@ -0,0 +1,59 @@
/*
* Copyright (C) 2013 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TABLE_FILTER_GENRE_HPP
#define TABLE_FILTER_GENRE_HPP
#include <Wt/Dbo/QueryModel>
#include <Wt/WTableView>
#include "Filter.hpp"
#include "database/DatabaseHandler.hpp"
namespace UserInterface {
class TableFilterGenre : public Wt::WTableView, public Filter
{
public:
TableFilterGenre(Database::Handler& db, Wt::WContainerWidget* parent = 0);
// Set constraints on this filter
void refresh(const Constraint& constraint);
// Get constraints created by this filter
void getConstraint(Constraint& constraint);
void layoutSizeChanged (int width, int height);
protected:
Database::Handler& _db;
// genre_name, count
typedef boost::tuple<std::string, int> ResultType;
Wt::Dbo::QueryModel< ResultType > _queryModel;
};
} // namespace UserInterface
#endif
+6 -28
View File
@@ -33,9 +33,9 @@ TrackView::TrackView( Database::Handler& db, Wt::WContainerWidget* parent)
: Wt::WTableView( parent ),
_db(db)
{
_queryModel.setQuery(_db.getSession().query<ResultType>("select track,release,artist from track,release,artist where track.release_id = release.id and track.artist_id = artist.id" ).orderBy("artist.name,release.name,track.disc_number,track.track_number"));
_queryModel.addColumn( "artist.name", "Artist" );
_queryModel.addColumn( "release.name", "Album" );
_queryModel.setQuery(_db.getSession().query<ResultType>("select track from track").orderBy("track.artist_name,track.date,track.release_name,track.disc_number,track.track_number"));
_queryModel.addColumn( "track.artist_name", "Artist" );
_queryModel.addColumn( "track.release_name", "Album" );
_queryModel.addColumn( "track.disc_number", "Disc #" );
_queryModel.addColumn( "track.track_number", "Track #" );
_queryModel.addColumn( "track.name", "Track" );
@@ -107,15 +107,15 @@ TrackView::refresh(const Constraint& constraint)
SqlQuery sqlQuery;
sqlQuery.select( "track,release,artist" );
sqlQuery.from().And( FromClause("artist,release,track,genre,track_genre"));
sqlQuery.select( "track" );
sqlQuery.from().And( FromClause("track"));
sqlQuery.where().And(constraint.where);
LMS_LOG(MOD_UI, SEV_DEBUG) << "TRACK REQ = '" << sqlQuery.get() << "'";
Wt::Dbo::Query<ResultType> query = _db.getSession().query<ResultType>( sqlQuery.get() );
query.groupBy("track").orderBy("artist.name,track.date,release.name,track.disc_number,track.track_number");
query.groupBy("track").orderBy("track.artist_name,track.date,track.release_name,track.disc_number,track.track_number");
BOOST_FOREACH(const std::string& bindArg, sqlQuery.where().getBindArgs()) {
LMS_LOG(MOD_UI, SEV_DEBUG) << "Binding value '" << bindArg << "'";
@@ -126,28 +126,6 @@ TrackView::refresh(const Constraint& constraint)
}
/*
void
TrackView::handleTrackSelected(void)
{
Wt::WModelIndexSet indexSet = this->selectedIndexes();
if (!indexSet.empty()) {
Wt::WModelIndex currentIndex( *indexSet.begin() );
// Check there are remainin tracks!
if (currentIndex.isValid())
{
ResultType result = _queryModel.resultRow( currentIndex.row());
// Get the track part
Wt::Dbo::ptr<Database::Track> track ( result.get<0>() );
_trackSelected.emit( track->getPath() );
}
}
}
*/
void
TrackView::getSelectedTracks(std::vector<Database::Track::id_type>& track_ids)
{
+1 -1
View File
@@ -60,7 +60,7 @@ class TrackView : public Wt::WTableView, public Filter
Database::Handler& _db;
typedef boost::tuple<Database::Track::pointer, Database::Release::pointer, Database::Artist::pointer> ResultType;
typedef boost::tuple<Database::Track::pointer> ResultType;
Wt::Dbo::QueryModel< ResultType > _queryModel;
Wt::WTableView* _tableView;