Now I understand the problem. You want to pass an expression where a value is expected. I do not believe we can support this. INSTR does not solve the problem because it would not be correct to looks for substrings. In fact paper.authors may contain '|12|13|' and it would incorrectly return that author '2' is one of authors because it is a substring.
You have to do it in two steps: person = db(db.person.name='....').select().first() papers = db.paper.authors.contains(person.id).select() Massimo On Jan 21, 2013, at 3:33 PM, pablo.ang...@uam.es wrote: > > > El lunes, 21 de enero de 2013 18:56:07 UTC+1, Massimo Di Pierro escribió: > Before we attempt to fix this. It works for me as it is with sqlite. Why does > doesn't it wirk with mysql? MySQL has a LIKE operator. Wat error do you get? > > execution of: > > db(db.paper.authors.contains(person.id))._select() > > gives: > > "SELECT person.id, paper.id, paper.title, paper.authors FROM person, paper > WHERE (paper.authors LIKE '%|person.id|%');" > > which I think tries to find those papers whose "authors" field contains the > literal "person.id", instead of the pairs (paper,person) such that the person > is one of the authors of the paper. > > With the modification I wrote before, it gets converted into: > > 'SELECT person.id, paper.id, paper.title, paper.authors FROM person, paper > WHERE INSTR(paper.authors, person.id);' > > with a different meaning. > > I can see why using the INSTR operator on MySQL may be better but do we know > it is faster? > > I haven't made any speed test, I'd go for anything that works in sqlite and > mysql/mariadb. > > Thanks for your attention! > > > Massimo > > On Monday, 21 January 2013 08:55:40 UTC-6, pablo....@uam.es wrote: > Hello: > I was getting incorrect SQL from statements like: > > db(db.paper.authors.contains(person.id)).select() > > where > > db.define_table('paper', > Field('title'), > Field('authors', 'list:reference person'), > ) > > > so I rewrote dal.MySQLAdapter.CONTAINS from: > > def CONTAINS(self, first, second): > if first.type in ('string', 'text'): > key = '%'+str(second).replace('%','%%')+'%' > elif first.type.startswith('list:'): > key = '%|'+str(second).replace('|','||').replace('%','%%')+'|%' > return '(%s LIKE %s)' % (self.expand(first),self.expand(key,'string')) > > into: > > def CONTAINS(self, first, second): > if first.type in ('string', 'text'): > key = '%'+str(second).replace('%','%%')+'%' > elif first.type.startswith('list:reference'): > return 'INSTR(%s, %s)'%(first, str(second)) > elif first.type.startswith('list:'): > key = '%|'+str(second).replace('|','||').replace('%','%%')+'|%' > return '(%s LIKE %s)' % (self.expand(first),self.expand(key,'string')) > > now the above query works, but that's in MySQL, not SQLite, which apparently > does not have a INSTR operation, despite the fact that it is advertised! > > https://www.sqlite.org/lang_corefunc.html > > Can anybody think of a solution that works in more databases --