summaryrefslogtreecommitdiff
path: root/mg_order.c
diff options
context:
space:
mode:
Diffstat (limited to 'mg_order.c')
-rw-r--r--mg_order.c1254
1 files changed, 0 insertions, 1254 deletions
diff --git a/mg_order.c b/mg_order.c
deleted file mode 100644
index 4c44f28..0000000
--- a/mg_order.c
+++ /dev/null
@@ -1,1254 +0,0 @@
-#include "mg_order.h"
-#include "mg_tools.h"
-#include "i18n.h"
-#include <stdio.h>
-#include <assert.h>
-
-static map <mgKeyTypes, map<string,string> > map_values;
-static map <mgKeyTypes, map<string,string> > map_ids;
-
-mgKeyMaps KeyMaps;
-
-bool iskeyGenre(mgKeyTypes kt)
-{
- return kt>=keyGenre1 && kt <= keyGenres;
-}
-
-class mgRefParts : public mgParts {
- public:
- mgRefParts(const mgReference& r);
-};
-
-
-strlist& operator+=(strlist&a, strlist b)
-{
- a.insert(a.end(), b.begin(),b.end());
- return a;
-}
-
-
-/*! \brief if the SQL command works on only 1 table, remove all table
-* qualifiers. Example: SELECT tracks.title FROM tracks becomes SELECT title
-* FROM tracks
-* \param spar the sql command. It will be edited in place
-* \return the new sql command is also returned
-*/
-static string
-optimize (string & spar)
-{
- string s = spar;
- string::size_type tmp = s.find (" WHERE");
- if (tmp != string::npos)
- s.erase (tmp, 9999);
- tmp = s.find (" ORDER");
- if (tmp != string::npos)
- s.erase (tmp, 9999);
- string::size_type frompos = s.find (" FROM ") + 6;
- if (s.substr (frompos).find (",") == string::npos)
- {
- string from = s.substr (frompos, 999) + '.';
- string::size_type track;
- while ((track = spar.find (from)) != string::npos)
- {
- spar.erase (track, from.size ());
- }
- }
- return spar;
-}
-
-string&
-addsep (string & s, string sep, string n)
-{
- if (!n.empty ())
- {
- if (!s.empty ())
- s.append (sep);
- s.append (n);
- }
- return s;
-}
-
-
-static string
-sql_list (string prefix,strlist v,string sep=",",string postfix="")
-{
- string result = "";
- for (list < string >::iterator it = v.begin (); it != v.end (); ++it)
- {
- addsep (result, sep, *it);
- }
- if (!result.empty())
- {
- result.insert(0," "+prefix+" ");
- result += postfix;
- }
- return result;
-}
-
-//! \brief converts long to string
-string
-itos (int i)
-{
- stringstream s;
- s << i;
- return s.str ();
-}
-
-//! \brief convert long to string
-string
-ltos (long l)
-{
- stringstream s;
- s << l;
- return s.str ();
-}
-
-
-class mgKeyNormal : public mgKey {
- public:
- mgKeyNormal(const mgKeyNormal& k);
- mgKeyNormal(const mgKeyTypes kt, string table, string field);
- virtual mgParts Parts(mgmySql &db,bool orderby=false) const;
- string value() const;
- string id() const;
- bool valid() const;
- void set(mgListItem& item);
- mgListItem& get();
- mgKeyTypes Type() const { return m_kt; }
- virtual string expr() const { return m_table + "." + m_field; }
- virtual string table() const { return m_table; }
- protected:
- string IdClause(mgmySql &db,string what,string::size_type start=0,string::size_type len=string::npos) const;
- void AddIdClause(mgmySql &db,mgParts &result,string what) const;
- mgListItem m_item;
- string m_field;
- private:
- mgKeyTypes m_kt;
- string m_table;
-};
-
-class mgKeyABC : public mgKeyNormal {
- public:
- mgKeyABC(const mgKeyNormal& k) : mgKeyNormal(k) {}
- mgKeyABC(const mgKeyTypes kt, string table, string field) : mgKeyNormal(kt,table,field) {}
- virtual string expr() const { return "substring("+mgKeyNormal::expr()+",1,1)"; }
- protected:
- //void AddIdClause(mgmySql &db,mgParts &result,string what) const;
-};
-
-class mgKeyDate : public mgKeyNormal {
- public:
- mgKeyDate(mgKeyTypes kt,string table, string field) : mgKeyNormal(kt,table,field) {}
-};
-
-class mgKeyTrack : public mgKeyNormal {
- public:
- mgKeyTrack() : mgKeyNormal(keyTrack,"tracks","tracknb") {};
- mgParts Parts(mgmySql &db,bool orderby=false) const;
-};
-
-class mgKeyAlbum : public mgKeyNormal {
- public:
- mgKeyAlbum() : mgKeyNormal(keyAlbum,"album","title") {};
- mgParts Parts(mgmySql &db,bool orderby=false) const;
-};
-
-mgParts
-mgKeyAlbum::Parts(mgmySql &db,bool orderby) const
-{
- mgParts result = mgKeyNormal::Parts(db,orderby);
- result.tables.push_back("tracks");
- return result;
-}
-
-class mgKeyFolder : public mgKeyNormal {
- public:
- mgKeyFolder(mgKeyTypes kt,const char *fname)
- : mgKeyNormal(kt,"tracks",fname) { m_enabled=-1;};
- bool Enabled(mgmySql &db);
- private:
- int m_enabled;
-};
-
-class mgKeyFolder1 : public mgKeyFolder {
- public:
- mgKeyFolder1() : mgKeyFolder(keyFolder1,"folder1") {};
-};
-class mgKeyFolder2 : public mgKeyFolder {
- public:
- mgKeyFolder2() : mgKeyFolder(keyFolder2,"folder2") {};
-};
-class mgKeyFolder3 : public mgKeyFolder {
- public:
- mgKeyFolder3() : mgKeyFolder(keyFolder3,"folder3") {};
-};
-class mgKeyFolder4 : public mgKeyFolder {
- public:
- mgKeyFolder4() : mgKeyFolder(keyFolder4,"folder4") {};
-};
-
-bool
-mgKeyFolder::Enabled(mgmySql &db)
-{
- if (m_enabled<0)
- {
- if (!db.Connected())
- return false;
- char *b;
- asprintf(&b,"DESCRIBE tracks %s",m_field.c_str());
- MYSQL_RES * rows = db.exec_sql (b);
- free(b);
- if (rows)
- {
- m_enabled = mysql_num_rows(rows);
- mysql_free_result (rows);
- }
- }
- return (m_enabled==1);
-}
-
-class mgKeyGenres : public mgKeyNormal {
- public:
- mgKeyGenres() : mgKeyNormal(keyGenres,"tracks","genre1") {};
- mgKeyGenres(mgKeyTypes kt) : mgKeyNormal(kt,"tracks","genre1") {};
- mgParts Parts(mgmySql &db,bool orderby=false) const;
- protected:
- string map_idfield() const { return "id"; }
- string map_valuefield() const { return "genre"; }
- string map_table() const { return "genre"; }
- virtual unsigned int genrelevel() const { return 4; }
- private:
- string GenreClauses(mgmySql &db,bool orderby) const;
-};
-
-class mgKeyGenre1 : public mgKeyGenres
-{
- public:
- mgKeyGenre1() : mgKeyGenres(keyGenre1) {}
- unsigned int genrelevel() const { return 1; }
-};
-
-class mgKeyGenre2 : public mgKeyGenres
-{
- public:
- mgKeyGenre2() : mgKeyGenres(keyGenre2) {}
- unsigned int genrelevel() const { return 2; }
-};
-
-class mgKeyGenre3 : public mgKeyGenres
-{
- public:
- mgKeyGenre3() : mgKeyGenres(keyGenre3) {}
- unsigned int genrelevel() const { return 3; }
-};
-
-string
-mgKeyGenres::GenreClauses(mgmySql &db,bool orderby) const
-{
- strlist g1;
- strlist g2;
-
- if (orderby)
- if (genrelevel()==4)
- {
- g1.push_back("tracks.genre1=genre.id");
- g2.push_back("tracks.genre2=genre.id");
- }
- else
- {
- g1.push_back("substring(tracks.genre1,1,"+ltos(genrelevel())+")=genre.id");
- g2.push_back("substring(tracks.genre2,1,"+ltos(genrelevel())+")=genre.id");
- }
-
- if (valid())
- {
- unsigned int len=genrelevel();
- if (len==4) len=0;
- g1.push_back(IdClause(db,"tracks.genre1",0,genrelevel()));
- g2.push_back(IdClause(db,"tracks.genre2",0,genrelevel()));
- }
-
- extern bool needGenre2;
- if (needGenre2)
- {
- string o1=sql_list("(",g1," AND ",")");
- if (o1.empty())
- return "";
- string o2=sql_list("(",g2," AND ",")");
- return string("(") + o1 + " OR " + o2 + string(")");
- }
- else
- return sql_list("",g1," AND ");
-}
-
-
-mgParts
-mgKeyGenres::Parts(mgmySql &db,bool orderby) const
-{
- mgParts result;
- result.clauses.push_back(GenreClauses(db,orderby));
- result.tables.push_back("tracks");
- if (orderby)
- {
- result.fields.push_back("genre.genre");
- result.fields.push_back("genre.id");
- result.tables.push_back("genre");
- result.orders.push_back("genre.genre");
- }
- return result;
-}
-
-
-class mgKeyLanguage : public mgKeyNormal {
- public:
- mgKeyLanguage() : mgKeyNormal(keyLanguage,"tracks","lang") {};
- mgParts Parts(mgmySql &db,bool orderby=false) const;
- protected:
- string map_idfield() const { return "id"; }
- string map_valuefield() const { return "language"; }
- string map_table() const { return "language"; }
-};
-
-class mgKeyCollection: public mgKeyNormal {
- public:
- mgKeyCollection() : mgKeyNormal(keyCollection,"playlist","id") {};
- mgParts Parts(mgmySql &db,bool orderby=false) const;
- protected:
- string map_idfield() const { return "id"; }
- string map_valuefield() const { return "title"; }
- string map_table() const { return "playlist"; }
-};
-class mgKeyCollectionItem : public mgKeyNormal {
- public:
- mgKeyCollectionItem() : mgKeyNormal(keyCollectionItem,"playlistitem","tracknumber") {};
- mgParts Parts(mgmySql &db,bool orderby=false) const;
-};
-
-class mgKeyDecade : public mgKeyNormal {
- public:
- mgKeyDecade() : mgKeyNormal(keyDecade,"tracks","year") {}
- string expr() const { return "substring(convert(10 * floor(tracks.year/10), char),3)"; }
-};
-
-string
-mgKeyNormal::id() const
-{
- return m_item.id();
-}
-
-bool
-mgKeyNormal::valid() const
-{
- return m_item.valid();
-}
-
-string
-mgKeyNormal::value() const
-{
- return m_item.value();
-}
-
-
-mgKeyNormal::mgKeyNormal(const mgKeyNormal& k)
-{
- m_kt = k.m_kt;
- m_table = k.m_table;
- m_field = k.m_field;
- m_item = k.m_item;
-}
-
-mgKeyNormal::mgKeyNormal(const mgKeyTypes kt, string table, string field)
-{
- m_kt = kt;
- m_table = table;
- m_field = field;
-}
-
-void
-mgKeyNormal::set(mgListItem& item)
-{
- m_item=item;
-}
-
-mgListItem&
-mgKeyNormal::get()
-{
- return m_item;
-}
-
-mgParts::mgParts()
-{
- m_sql_select="";
- orderByCount = false;
-}
-
-mgParts::~mgParts()
-{
-}
-
-mgParts
-mgKeyNormal::Parts(mgmySql &db, bool orderby) const
-{
- mgParts result;
- result.tables.push_back(table());
- AddIdClause(db,result,expr());
- if (orderby)
- {
- result.fields.push_back(expr());
- result.orders.push_back(expr());
- }
- return result;
-}
-
-string
-mgKeyNormal::IdClause(mgmySql &db,string what,string::size_type start,string::size_type len) const
-{
- if (len==0)
- len=string::npos;
- if (id() == "'NULL'")
- return what + " is NULL";
- else if (len==string::npos)
- return what + "=" + db.sql_string(id());
- else
- {
- return "substring("+what + ","+ltos(start+1)+","+ltos(len)+")="
- + db.sql_string(id().substr(start,len));
- }
-}
-
-void
-mgKeyNormal::AddIdClause(mgmySql &db,mgParts &result,string what) const
-{
- if (valid())
- result.clauses.push_back(IdClause(db,what));
-}
-
-mgParts
-mgKeyTrack::Parts(mgmySql &db,bool orderby) const
-{
- mgParts result;
- result.tables.push_back("tracks");
- AddIdClause(db,result,"tracks.title");
- if (orderby)
- {
- // if you change tracks.title, please also
- // change mgContentItem::getKeyItem()
- result.fields.push_back("tracks.title");
- result.orders.push_back("tracks.tracknb");
- }
- return result;
-}
-
-mgParts
-mgKeyLanguage::Parts(mgmySql &db,bool orderby) const
-{
- mgParts result;
- AddIdClause(db,result,"tracks.lang");
- result.tables.push_back("tracks");
- if (orderby)
- {
- result.fields.push_back("language.language");
- result.fields.push_back("tracks.lang");
- result.tables.push_back("language");
- result.orders.push_back("language.language");
- }
- return result;
-}
-
-mgParts
-mgKeyCollection::Parts(mgmySql &db,bool orderby) const
-{
- mgParts result;
- if (orderby)
- {
- result.tables.push_back("playlist");
- AddIdClause(db,result,"playlist.id");
- result.fields.push_back("playlist.title");
- result.fields.push_back("playlist.id");
- result.orders.push_back("playlist.title");
- }
- else
- {
- result.tables.push_back("playlistitem");
- AddIdClause(db,result,"playlistitem.playlist");
- }
- return result;
-}
-
-mgParts
-mgKeyCollectionItem::Parts(mgmySql &db,bool orderby) const
-{
- mgParts result;
- result.tables.push_back("playlistitem");
- AddIdClause(db,result,"playlistitem.tracknumber");
- if (orderby)
- {
- // tracks nur hier, fuer sql_delete_from_coll wollen wir es nicht
- result.tables.push_back("tracks");
- result.fields.push_back("tracks.title");
- result.fields.push_back("playlistitem.tracknumber");
- result.orders.push_back("playlistitem.tracknumber");
- }
- return result;
-}
-
-mgParts&
-mgParts::operator+=(mgParts a)
-{
- fields += a.fields;
- tables += a.tables;
- clauses += a.clauses;
- orders += a.orders;
- return *this;
-}
-
-mgRefParts::mgRefParts(const mgReference& r)
-{
- tables.push_back(r.t1());
- tables.push_back(r.t2());
- clauses.push_back(r.t1() + '.' + r.f1() + '=' + r.t2() + '.' + r.f2());
-}
-
-void
-mgParts::Prepare()
-{
- tables.sort();
- tables.unique();
- strlist::reverse_iterator it;
- string prevtable = "";
- for (it = tables.rbegin(); it != tables.rend(); ++it)
- {
- if (!prevtable.empty())
- *this += ref.Connect(prevtable,*it);
- prevtable = *it;
- }
- tables.sort();
- tables.unique();
- clauses.sort();
- clauses.unique();
- orders.unique();
-}
-
-string
-mgParts::sql_select(bool distinct)
-{
- if (!m_sql_select.empty())
- return m_sql_select;
- Prepare();
- string result;
- if (distinct)
- {
- fields.push_back("COUNT(*) AS mgcount");
- result = sql_list("SELECT",fields);
- fields.pop_back();
- }
- else
- result = sql_list("SELECT",fields);
- if (result.empty())
- return result;
- result += sql_list("FROM",tables);
- result += sql_list("WHERE",clauses," AND ");
- if (distinct)
- {
- result += sql_list("GROUP BY",fields);
- if (orderByCount)
- orders.insert(orders.begin(),"mgcount desc");
- }
- result += sql_list("ORDER BY",orders);
- optimize(result);
- return result;
-}
-
-string
-mgParts::sql_count()
-{
- Prepare();
- string result = sql_list("SELECT COUNT(DISTINCT",fields,",",")");
- if (result.empty())
- return result;
- result += sql_list("FROM",tables);
- result += sql_list("WHERE",clauses," AND ");
- optimize(result);
- return result;
-}
-
-bool
-mgParts::UsesTracks()
-{
- for (list < string >::iterator it = tables.begin (); it != tables.end (); ++it)
- if (*it == "tracks") return true;
- return false;
-}
-
-string
-mgParts::sql_delete_from_collection(string pid)
-{
- if (pid.empty())
- return "";
- Prepare();
- // del nach vorne, weil DELETE playlistitem die erste Table nimmt,
- // die passt, egal ob alias oder nicht.
- tables.push_front("playlistitem as del");
- clauses.push_back("del.playlist="+pid);
- // todo geht so nicht fuer andere selections
- if (UsesTracks())
- clauses.push_back("del.trackid=tracks.id");
- else
- clauses.push_back("del.trackid=playlistitem.trackid");
- string result = "DELETE playlistitem";
- result += sql_list(" FROM",tables);
- result += sql_list(" WHERE",clauses," AND ");
- optimize(result);
- return result;
-}
-
-string
-mgParts::sql_update(strlist new_values)
-{
- Prepare();
- assert(fields.size()==new_values.size());
- string result = sql_list("UPDATE",fields);
- result += sql_list(" FROM",tables);
- result += sql_list(" WHERE",clauses," AND ");
- result += sql_list("VALUES(",new_values,",",")");
- optimize(result);
- return result;
-}
-
-mgReference::mgReference(string t1,string f1,string t2,string f2)
-{
- m_t1 = t1;
- m_f1 = f1;
- m_t2 = t2;
- m_f2 = f2;
-}
-
-mgOrder::mgOrder()
-{
- clear();
- setKey (keyArtist);
- setKey (keyAlbum);
- setKey (keyTrack);
- m_orderByCount = false;
-}
-
-mgOrder::~mgOrder()
-{
- truncate(0);
-}
-
-mgKey*
-mgOrder::Key(unsigned int idx) const
-{
- return Keys[idx];
-}
-
-mgKey*&
-mgOrder::operator[](unsigned int idx)
-{
- assert(idx<size());
- return Keys[idx];
-}
-
-bool
-operator==(const mgOrder& a, const mgOrder &b)
-{
- bool result = a.size()==b.size();
- if (result)
- for (unsigned int i=0; i<a.size();i++)
- {
- result &= a.Key(i)->Type()==b.Key(i)->Type();
- if (!result) break;
- }
- return result;
-}
-
-const mgOrder&
-mgOrder::operator=(const mgOrder& from)
-{
- clear();
- InitFrom(from);
- return *this;
-}
-
-mgOrder::mgOrder(const mgOrder &from)
-{
- InitFrom(from);
-}
-
-void
-mgOrder::InitFrom(const mgOrder &from)
-{
- for (unsigned int i = 0; i < from.size();i++)
- {
- mgKey *k = ktGenerate(from.getKeyType(i));
- k->set(from.getKeyItem(i));
- Keys.push_back(k);
- }
- m_orderByCount=from.m_orderByCount;
-}
-
-string
-mgOrder::Name()
-{
- string result="";
- for (unsigned int idx=0;idx<size();idx++)
- {
- if (!result.empty()) result += ":";
- result += ktName(Keys[idx]->Type());
- }
- return result;
-}
-
-void
-mgOrder::setKey (const mgKeyTypes kt)
-{
- mgKey *newkey = ktGenerate(kt);
- if (newkey)
- Keys.push_back(newkey);
-}
-
-mgOrder::mgOrder(mgValmap& nv,char *prefix)
-{
- char *idx;
- asprintf(&idx,"%s.OrderByCount",prefix);
- m_orderByCount = nv.getbool(idx);
- free(idx);
- clear();
- for (unsigned int i = 0; i < 999 ; i++)
- {
- asprintf(&idx,"%s.Keys.%u.Type",prefix,i);
- unsigned int v = nv.getuint(idx);
- free(idx);
- if (v==0) break;
- setKey (mgKeyTypes(v) );
- }
- if (size()>0)
- clean();
-}
-
-void
-mgOrder::DumpState(mgValmap& nv, char *prefix) const
-{
- char n[100];
- sprintf(n,"%s.OrderByCount",prefix);
- nv.put(n,m_orderByCount);
- for (unsigned int i=0;i<size();i++)
- {
- sprintf(n,"%s.Keys.%d.Type",prefix,i);
- nv.put(n,int(Key(i)->Type()));
- }
-}
-
-mgOrder::mgOrder(vector<mgKeyTypes> kt)
-{
- m_orderByCount = false;
- setKeys(kt);
-}
-
-void
-mgOrder::setKeys(vector<mgKeyTypes> kt)
-{
- clear();
- for (unsigned int i=0;i<kt.size();i++)
- setKey(kt[i]);
- clean();
-}
-
-
-mgKeyTypes
-mgOrder::getKeyType(unsigned int idx) const
-{
- assert(idx<Keys.size());
- return Keys[idx]->Type();
-}
-
-mgListItem&
-mgOrder::getKeyItem(unsigned int idx) const
-{
- assert(idx<Keys.size());
- return Keys[idx]->get();
-}
-
-void
-mgOrder::truncate(unsigned int i)
-{
- while (size()>i)
- {
- delete Keys.back();
- Keys.pop_back();
- }
-}
-
-void
-mgOrder::clear()
-{
- truncate(0);
-}
-
-void
-mgOrder::clean()
-{
- // remove double entries:
- keyvector::iterator i;
- keyvector::iterator j;
- bool collection_found = false;
- bool collitem_found = false;
- bool album_found = false;
- bool tracknb_found = false;
- bool title_found = false;
- bool is_unique = false;
- for (i = Keys.begin () ; i != Keys.end (); ++i)
- {
- mgKeyNormal* k = dynamic_cast<mgKeyNormal*>(*i);
- collection_found |= (k->Type()==keyCollection);
- collitem_found |= (k->Type()==keyCollectionItem);
- album_found |= (k->Type()==keyAlbum);
- tracknb_found |= (k->Type()==keyTrack);
- title_found |= (k->Type()==keyTitle);
- is_unique = tracknb_found || (album_found && title_found)
- || (collection_found && collitem_found);
- if (is_unique)
- {
- for (j = i+1 ; j !=Keys.end(); ++j)
- delete *j;
- Keys.erase(i+1,Keys.end ());
- break;
- }
- if (k->Type()==keyYear)
- {
- for (j = i+1 ; j != Keys.end(); ++j)
- if ((*j)->Type() == keyDecade)
- {
- delete *j;
- Keys.erase(j);
- break;
- }
- }
-cleanagain:
- for (j = i+1 ; j != Keys.end(); ++j)
- if ((*i)->Type() == (*j)->Type())
- {
- delete *j;
- Keys.erase(j);
- goto cleanagain;
- }
- }
- if (!is_unique)
- {
- if (!album_found)
- Keys.push_back(ktGenerate(keyAlbum));
- if (!title_found)
- Keys.push_back(ktGenerate(keyTitle));
- }
-}
-
-bool
-mgOrder::isCollectionOrder() const
-{
- return (size()==2
- && (Keys[0]->Type()==keyCollection)
- && (Keys[1]->Type()==keyCollectionItem));
-}
-
-mgParts
-mgOrder::Parts(mgmySql &db,unsigned int level,bool orderby) const
-{
- mgParts result;
- result.orderByCount = m_orderByCount;
- if (level==0 && isCollectionOrder())
- {
- // sql command contributed by jarny
- result.m_sql_select = string("select playlist.title,playlist.id, "
- "count(*) * (playlistitem.playlist is not null) from playlist "
- "left join playlistitem on playlist.id = playlistitem.playlist "
- "group by playlist.title");
- return result;
- }
- for (unsigned int i=0;i<=level;i++)
- {
- if (i==Keys.size()) break;
- mgKeyNormal *k = dynamic_cast<mgKeyNormal*>(Keys[i]);
- mgKeyTypes kt = k->Type();
- if (iskeyGenre(kt))
- {
- for (unsigned int j=i+1;j<=level;j++)
- {
- if (j>=Keys.size())
- break;
- mgKeyNormal *kn = dynamic_cast<mgKeyNormal*>(Keys[j]);
- if (kn)
- {
- mgKeyTypes knt = kn->Type();
- if (iskeyGenre(knt) && knt>kt && !kn->id().empty())
- goto next;
- }
- }
- }
- result += k->Parts(db,orderby && (i==level));
-next:
- continue;
- }
- return result;
-}
-
-string
-mgOrder::GetContent(mgmySql &db,unsigned int level,vector < mgContentItem > &content) const
-{
- mgParts p = Parts(db,level);
- p.fields.clear();
- p.fields.push_back("tracks.id");
- p.fields.push_back("tracks.title");
- p.fields.push_back("tracks.mp3file");
- p.fields.push_back("tracks.artist");
- p.fields.push_back("album.title");
- p.fields.push_back("tracks.genre1");
- p.fields.push_back("tracks.genre2");
- p.fields.push_back("tracks.bitrate");
- p.fields.push_back("tracks.year");
- p.fields.push_back("tracks.rating");
- p.fields.push_back("tracks.length");
- p.fields.push_back("tracks.samplerate");
- p.fields.push_back("tracks.channels");
- p.fields.push_back("tracks.lang");
- p.tables.push_back("tracks");
- p.tables.push_back("album");
- for (unsigned int i = level; i<size(); i++)
- p += Key(i)->Parts(db,true);
- string result = p.sql_select(false);
- content.clear ();
- MYSQL_RES *rows = db.exec_sql (result);
- if (rows)
- {
- MYSQL_ROW row;
- while ((row = mysql_fetch_row (rows)) != 0)
- content.push_back (mgContentItem (row));
- mysql_free_result (rows);
- }
- return result;
-}
-
-
-//! \brief right now thread locking should not be needed here
-mgReferences::mgReferences()
-{
- push_back(mgReference ("tracks","id","playlistitem","trackid"));
- push_back(mgReference ("playlist","id","playlistitem","playlist"));
- push_back(mgReference ("tracks","sourceid","album","cddbid"));
- push_back(mgReference ("tracks","lang","language","id"));
-}
-
-bool
-mgReferences::Equal(unsigned int i,string table1, string table2) const
-{
- const mgReference& r = operator[](i);
- string s1 = r.t1();
- string s2 = r.t2();
- return ((s1==table1) && (s2==table2))
- || ((s1==table2) && (s2==table1));
-}
-
-mgParts
-mgReferences::FindConnectionBetween(string table1, string table2) const
-{
- for (unsigned int i=0 ; i<size(); i++ )
- if (Equal(i,table1,table2))
- return mgRefParts(operator[](i));
- return mgParts();
-}
-
-mgParts
-mgReferences::ConnectToTracks(string table) const
-{
- mgParts result;
- if (table=="tracks")
- return result;
- result += FindConnectionBetween(table,"tracks");
- if (result.empty())
- {
- result += FindConnectionBetween(table,"playlistitem");
- if (!result.empty())
- {
- result += FindConnectionBetween("playlistitem","tracks");
- }
- else
- assert(false);
- }
- return result;
-}
-
-mgParts
-mgReferences::Connect(string table1, string table2) const
-{
- mgParts result;
- // same table?
- if (table1 == table2) return result;
- if (table1=="genre") return ConnectToTracks(table2);
- if (table2=="genre") return ConnectToTracks(table1);
- // do not connect aliases. See sql_delete_from_collection
- if (table1.find(" as ")!=string::npos) return result;
- if (table2.find(" as ")!=string::npos) return result;
- if (table1.find(" AS ")!=string::npos) return result;
- if (table2.find(" AS ")!=string::npos) return result;
- // direct connection?
- result += FindConnectionBetween(table1,table2);
- if (result.empty())
- {
- // indirect connection? try connecting via tracks
- result += ConnectToTracks(table1);
- result += ConnectToTracks(table2);
- }
- return result;
-}
-
-
-mgKey*
-ktGenerate(const mgKeyTypes kt)
-{
- mgKey* result = 0;
- switch (kt)
- {
- case keyGenres: result = new mgKeyGenres;break;
- case keyGenre1: result = new mgKeyGenre1;break;
- case keyGenre2: result = new mgKeyGenre2;break;
- case keyGenre3: result = new mgKeyGenre3;break;
- case keyFolder1:result = new mgKeyFolder1;break;
- case keyFolder2:result = new mgKeyFolder2;break;
- case keyFolder3:result = new mgKeyFolder3;break;
- case keyFolder4:result = new mgKeyFolder4;break;
- case keyArtist: result = new mgKeyNormal(kt,"tracks","artist");break;
- case keyArtistABC: result = new mgKeyABC(kt,"tracks","artist");break;
- case keyTitle: result = new mgKeyNormal(kt,"tracks","title");break;
- case keyTitleABC: result = new mgKeyABC(kt,"tracks","title");break;
- case keyTrack: result = new mgKeyTrack;break;
- case keyDecade: result = new mgKeyDecade;break;
- case keyAlbum: result = new mgKeyAlbum;break;
- case keyCreated: result = new mgKeyDate(kt,"tracks","created");break;
- case keyModified: result = new mgKeyDate(kt,"tracks","modified");break;
- case keyCollection: result = new mgKeyCollection;break;
- case keyCollectionItem: result = new mgKeyCollectionItem;break;
- case keyLanguage: result = new mgKeyLanguage;break;
- case keyRating: result = new mgKeyNormal(kt,"tracks","rating");break;
- case keyYear: result = new mgKeyNormal(kt,"tracks","year");break;
- }
- return result;
-}
-
-const char * const
-ktName(const mgKeyTypes kt)
-{
- const char * result = "";
- switch (kt)
- {
- case keyGenres: result = "Genre";break;
- case keyGenre1: result = "Genre1";break;
- case keyGenre2: result = "Genre2";break;
- case keyGenre3: result = "Genre3";break;
- case keyFolder1: result = "Folder1";break;
- case keyFolder2: result = "Folder2";break;
- case keyFolder3: result = "Folder3";break;
- case keyFolder4: result = "Folder4";break;
- case keyArtist: result = "Artist";break;
- case keyArtistABC: result = "ArtistABC";break;
- case keyTitle: result = "Title";break;
- case keyTitleABC: result = "TitleABC";break;
- case keyTrack: result = "Track";break;
- case keyDecade: result = "Decade";break;
- case keyAlbum: result = "Album";break;
- case keyCreated: result = "Created";break;
- case keyModified: result = "Modified";break;
- case keyCollection: result = "Collection";break;
- case keyCollectionItem: result = "Collection item";break;
- case keyLanguage: result = "Language";break;
- case keyRating: result = "Rating";break;
- case keyYear: result = "Year";break;
- }
- return tr(result);
-}
-
-mgKeyTypes
-ktValue(const char * name)
-{
- for (int kt=int(mgKeyTypesLow);kt<=int(mgKeyTypesHigh);kt++)
- if (!strcmp(name,ktName(mgKeyTypes(kt))))
- return mgKeyTypes(kt);
- mgError("ktValue(%s): unknown name",name);
- return mgKeyTypes(0);
-}
-
-static vector<int> keycounts;
-
-unsigned int
-mgOrder::keycount(mgKeyTypes kt) const
-{
- if (keycounts.size()==0)
- {
- for (unsigned int ki=int(mgKeyTypesLow);ki<=int(mgKeyTypesHigh);ki++)
- {
- keycounts.push_back(-1);
- }
- }
- int& count = keycounts[int(kt-mgKeyTypesLow)];
- if (count==-1)
- {
- mgKey* k = ktGenerate(kt);
- struct mgmySql db;
- if (k->Enabled(db))
- count = db.exec_count(k->Parts(db,true).sql_count());
- else
- count = 0;
- delete k;
- }
- return count;
-}
-
-
-bool
-mgOrder::UsedBefore(const mgKeyTypes kt,unsigned int level) const
-{
- if (level>=size())
- level = size() -1;
- for (unsigned int lx = 0; lx < level; lx++)
- if (getKeyType(lx)==kt)
- return true;
- return false;
-}
-
-vector <const char *>
-mgOrder::Choices(unsigned int level, unsigned int *current) const
-{
- vector<const char*> result;
- if (level>size())
- {
- *current = 0;
- return result;
- }
- for (unsigned int ki=int(mgKeyTypesLow);ki<=int(mgKeyTypesHigh);ki++)
- {
- mgKeyTypes kt = mgKeyTypes(ki);
- if (kt==getKeyType(level))
- {
- *current = result.size();
- result.push_back(ktName(kt));
- continue;
- }
- if (UsedBefore(kt,level))
- continue;
- if (kt==keyDecade && UsedBefore(keyYear,level))
- continue;
- if (kt==keyGenre1)
- {
- if (UsedBefore(keyGenre2,level)) continue;
- if (UsedBefore(keyGenre3,level)) continue;
- if (UsedBefore(keyGenres,level)) continue;
- }
- if (kt==keyGenre2)
- {
- if (UsedBefore(keyGenre3,level)) continue;
- if (UsedBefore(keyGenres,level)) continue;
- }
- if (kt==keyGenre3)
- {
- if (UsedBefore(keyGenres,level)) continue;
- }
- if (kt==keyFolder1)
- {
- if (UsedBefore(keyFolder2,level)) continue;
- if (UsedBefore(keyFolder3,level)) continue;
- if (UsedBefore(keyFolder4,level)) continue;
- }
- if (kt==keyFolder2)
- {
- if (UsedBefore(keyFolder3,level)) continue;
- if (UsedBefore(keyFolder4,level)) continue;
- }
- if (kt==keyFolder3)
- {
- if (UsedBefore(keyFolder4,level)) continue;
- }
- if (kt==keyCollection || kt==keyCollectionItem)
- result.push_back(ktName(kt));
- else if (keycount(kt)>1)
- result.push_back(ktName(kt));
- }
- return result;
-}
-
-bool
-mgKey::LoadMap() const
-{
- map<string,string>& idmap = map_ids[Type()];
- if (map_idfield().empty())
- {
- return false;
- }
- mgmySql db;
- map<string,string>& valmap = map_values[Type()];
- char *b;
- asprintf(&b,"select %s,%s from %s;",map_idfield().c_str(),map_valuefield().c_str(),map_table().c_str());
- MYSQL_RES *rows = db.exec_sql (string(b));
- free(b);
- if (rows)
- {
- MYSQL_ROW row;
- while ((row = mysql_fetch_row (rows)) != 0)
- {
- if (row[0] && row[1])
- {
- valmap[row[0]] = row[1];
- idmap[row[1]] = row[0];
- }
- }
- mysql_free_result (rows);
- }
- return true;
-}
-
-bool
-mgKeyMaps::loadvalues (mgKeyTypes kt) const
-{
- if (map_ids.count(kt)>0)
- return true;
- mgKey* k = ktGenerate(kt);
- bool result = k->LoadMap();
- delete k;
- return result;
-}
-
-string
-mgKeyMaps::value(mgKeyTypes kt, string idstr) const
-{
- if (loadvalues (kt))
- {
- map<string,string>& valmap = map_values[kt];
- map<string,string>::iterator it;
- it = valmap.find(idstr);
- if (it!=valmap.end())
- {
- string r = it->second;
- if (!r.empty())
- return r;
- }
- map_ids[kt].clear();
- loadvalues(kt);
- it = valmap.find(idstr);
- if (it!=valmap.end())
- return valmap[idstr];
- }
- return idstr;
-}
-
-string
-mgKeyMaps::id(mgKeyTypes kt, string valstr) const
-{
- if (loadvalues (kt))
- {
- map<string,string>& idmap = map_ids[kt];
- string v = idmap[valstr];
- if (kt==keyGenre1) v=v.substr(0,1);
- if (kt==keyGenre2) v=v.substr(0,2);
- if (kt==keyGenre3) v=v.substr(0,3);
- return v;
- }
- return valstr;
-}