Seite 1 von 2
Fehler in class.genericdb.php
Verfasst: Mo 15. Aug 2005, 10:24
von devils.fist
Hallo,
ich habe festgestellt, daß
1. ein Tippfehler in Zeile 621 ist (wjere statt where)
2. die Where Bedingungen nicht so erstellt werden, wie man annehmen sollte. Und zwar sind meiner Meinung nach, die Sachen die mittels setWhere angegeben werden allgemein gültig und unabhängig von den Gruppen. Ich habe deshalb um die Gruppenbedingungen nocheinmal eine Klammer gesetzt. (s. Code)
3. Wenn ich setGroupWhere setzte in der Form ('gruppe', 'spalte','wert','operand') und danach in der Form
('gruppe', '', '', 'xxx'), wobei xxx z.B. etwas wie 'MATCH x AGAINST y' ist,
setzt er, unabhängig von der Gruppe, den letzten 'wert' an die Bedingung.
D.h. MATCH x AGAINST y 'wert', was natürlich zum Fehler führt.
Hier der teilweise verbesserte Code
Zeile 619 - 628 (bei mir)
Code: Alles auswählen
if (count($parameters["wheres"]) > 0)
{
$wheres[] = implode(", ", $parameters["wheres"]);
}
if ($groupWhereStatements != "")
{
// Klammern um die Gruppenbedingungen, damit setWhere auch wirklich global gültig
$wheres[] = "(".$groupWhereStatements.")";
}
Verfasst: Do 18. Aug 2005, 10:44
von emergence
punkt 1 kann ich bestätigen
bei punkt 2 und 3 muss ich nachhaken...
hast du da ein beispiel das man das testen kann ?
Verfasst: Do 18. Aug 2005, 11:04
von devils.fist
Bsp. zu 2:
Anwendungsgebiet ist eine Standardsuche mit LIKE über mehrere Felder und eine Volltextsuche im binären Modus.
Hier die SQL Anweisung, die durchgeführt werden soll:
(Treffer entweder in den Feldern oder in der pdf_summary, aber auf jeden fall ist client = 16)
Code: Alles auswählen
SELECT papicategories.idpilit_category,
papilendings.idpilit_lending,
papiliteratures.idpilit_literature
FROM pilit_literature AS papiliteratures
LEFT JOIN pilit_category AS papicategories
ON papiliteratures.idpilit_category = papicategories.idpilit_category
LEFT JOIN pilit_lending AS papilendings
ON papiliteratures.idpilit_literature = papilendings.idpilit_literature
WHERE
(
(
MATCH (papiliteratures.pdf_summary)
AGAINST ('test' IN BOOLEAN MODE)
)
OR
(
papiliteratures.title LIKE '%test%'
OR papiliteratures.author LIKE '%test%'
OR papiliteratures.publisher LIKE '%test%'
OR papiliteratures.publisher_house LIKE '%test%'
OR papiliteratures.summary LIKE '%test%'
)
)
AND
(
papiliteratures.idclient = '16'
)
ORDER BY papiliteratures.idclient asc,
papicategories.term asc,
papiliteratures.title asc
Im Objekt in der die DBabfrage definiert wird sieht der _where Teil
wie folgt aus:
Code: Alles auswählen
[_where] => Array
(
[global] => Array
(
[papiliteratures.idclient] => Array
(
[operator] => =
[restriction] => 16
)
)
[groups] => Array
(
[fulltext] => Array
(
[] => Array
(
[operator] => MATCH (papiliteratures.pdf_summary) AGAINST ('test' IN BOOLEAN MODE)
[restriction] =>
)
)
[spec] => Array
(
[papiliteratures.title] => Array
(
[operator] => LIKE
[restriction] => %test%
)
[papiliteratures.author] => Array
(
[operator] => LIKE
[restriction] => %test%
)
[papiliteratures.publisher] => Array
(
[operator] => LIKE
[restriction] => %test%
)
[papiliteratures.publisher_house] => Array
(
[operator] => LIKE
[restriction] => %test%
)
[papiliteratures.summary] => Array
(
[operator] => LIKE
[restriction] => %test%
)
)
)
)
[_whereRestriction] =>
[_innerGroupConditions] => Array
(
[spec] => OR
[fulltext] => AND
)
[_groupConditions] => Array
(
[spec] => Array
(
[fulltext] => OR
)
)
Ohne meine Änderungen wird nun aber folgenes SQL erzeugt:
Code: Alles auswählen
SELECT papicategories.idpilit_category,
papilendings.idpilit_lending,
papiliteratures.idpilit_literature
FROM pilit_literature AS papiliteratures
LEFT JOIN pilit_category AS papicategories
ON papiliteratures.idpilit_category = papicategories.idpilit_category
LEFT JOIN pilit_lending AS papilendings
ON papiliteratures.idpilit_literature = papilendings.idpilit_literature
WHERE
(
MATCH (papiliteratures.pdf_summary) AGAINST ('test' IN BOOLEAN MODE)
)
OR
(
papiliteratures.title LIKE '%test%'
OR papiliteratures.author LIKE '%test%'
OR papiliteratures.publisher LIKE '%test%'
OR papiliteratures.publisher_house LIKE '%test%'
OR papiliteratures.summary LIKE '%test%'
)
AND papiliteratures.idclient = '16'
ORDER BY papiliteratures.idclient asc,
papicategories.term asc,
papiliteratures.title asc
Erzeugt wird das ganze so:
Code: Alles auswählen
$oLiteratures->setWhereGroup('fulltext', '', '', 'MATCH (papiliteratures.pdf_summary) AGAINST (\''.$__string.'\' IN BOOLEAN MODE)');
$oLiteratures->setWhereGroup('spec', 'papiliteratures.title', "%".$spec_search_string."%", 'LIKE');
$oLiteratures->setWhereGroup('spec', 'papiliteratures.author', "%".$spec_search_string."%", 'LIKE');
$oLiteratures->setWhereGroup('spec', 'papiliteratures.publisher', "%".$spec_search_string."%", 'LIKE');
$oLiteratures->setWhereGroup('spec', 'papiliteratures.publisher_house', "%".$spec_search_string."%", 'LIKE');
$oLiteratures->setWhereGroup('spec', 'papiliteratures.summary', "%".$spec_search_string."%", 'LIKE');
$oLiteratures->setWhere('pApiLiteratures.idclient', $client);
$oLiteratures->setInnerGroupCondition('spec', 'OR');
$oLiteratures->setInnerGroupCondition('fulltext', 'AND');
$oLiteratures->setGroupCondition('spec','fulltext', 'OR');
Zu 3.
Wenn ich im obigen code die whereGroup 'fulltext' unter die gruppe 'spec' setze, dann wird in der SQL Anweisung:
Code: Alles auswählen
...
MATCH (papiliteratures.pdf_summary) AGAINST ('test' IN BOOLEAN MODE) '%test%'
...
erzeugt.
Verfasst: Do 18. Aug 2005, 12:10
von devils.fist
wo ich grad dabei bin
Habe auch noch folgende Änderung gemacht, wobei ich nicht weiß, ob sowas allgemein gebraucht wird. Und zwar ist so alles was mit setWhere(x,y) erzeugt wird, auch nochmal eine Gruppe. Sprich man kann z.b. abfragen wie diese erzeugen:
Code: Alles auswählen
SELECT *
FROM tab
WHERE
(
(
Gruppenbedingungen 1
)
OR
(
Gruppenbedingungen 2
)
)
AND
(
GlobaleBedingung1
OR GlobaleBedingung2
...
)
Das ganze wird möglich durch ein zusätzliches Objektattribut, welches ich _globalWhereRestriction genannt habe.
Die Änderung an der class.genericdb.php sieht dann so aus, das die Funktion _biuldWhereStatements durch diese (leicht modifizierte) ersetzt wird:
Code: Alles auswählen
function _buildWhereStatements ()
{
$globalwhererestriction = (isset($this->_globalWhereRestriction)) ? $this->_globalWhereRestriction : "AND";
$wheres = array();
/* Build global where condition */
foreach ($this->_where["global"] as $field => $item)
{
$restriction = "'" . $this->_itemClassInstance->_inFilter($item["restriction"]) . "'";
$wheres[] = implode(" ", array($field, $item["operator"], $restriction));
}
//return (implode(" AND ", $wheres));
if (count($wheres) > 0)
return "(".(implode(" ".$globalwhererestriction." ", $wheres)).")";
else
return (implode(" AND ", $wheres));
}
Verfasst: Do 18. Aug 2005, 12:13
von emergence
punkt 2 ist logisch und nachvollziehbar
warum aber bei der ersten gruppe
Code: Alles auswählen
$oLiteratures->setInnerGroupCondition('fulltext', 'AND');
gesetzt werden muss, ist mir nicht so ganz klar... (auch wenn nur eine anweisung vorhanden ist, muss ein operator gesetzt werden ?)
zu punkt 3 kann ich (noch) nichts sagen... das weiss derjenige am besten der das teil geschrieben hat...
Verfasst: Do 18. Aug 2005, 12:14
von devils.fist
die innergroupcondition muss nicht gesetzt sein. Das ist im Quelltext nur historisch bedingt, die gruppe war mal größer.
Verfasst: Sa 20. Aug 2005, 10:08
von emergence
devils.fist hat geschrieben:die innergroupcondition muss nicht gesetzt sein. Das ist im Quelltext nur historisch bedingt, die gruppe war mal größer.
ok...
Verfasst: Fr 26. Aug 2005, 13:39
von timo
also den Schreibfehler sowie die Klammern um die Gruppe habe ich korrigiert
Bei Punkt 3 komme ich nicht dahinter was du meinst

Verfasst: Sa 27. Aug 2005, 14:15
von emergence
@timo
contenido-cvs-2005-08-26.tar , der fehler ist noch immer drinnen -> $wjeres[] sollte $wheres[] sein...
das mit den klammern hab ich jetzt nicht gecheckt, dürfte aber auch noch fehlen...
Verfasst: Mo 29. Aug 2005, 11:29
von devils.fist
Zu Punkt 3:
Wie im Codebeispiel zu sehen (Post vom 18.08.2005 10:04:28), ist
[groups][fulltext][][restriction] NULL. Der Spaltenname auch.
Es soll folgender Select erzeugt werden:
SELECT * FROM ... MATCH (pdf_summary) AGAINST ('test' IN BOOLEAN MODE)
So wie es für mich aussieht, ist sowas nicht vergesehen sondern nur "normale" Vergleiche.
Das Problem was es gibt ist, daß er beim erzeugen der query während er das array durchläuft operator und restriction nicht null setzt. Das führt dazu, daß er die restriction vom vorhergehenden übernimmt. Wenn also
in meinem Beispiel unter groups zuerst "spec" kommt und dann "fulltext" nimmt er als restriction für "fulltext" die von papiliteratures.summary, in diesem Fall '%test%'.
Das erzeugt dann sowas:
SELECT * FROM ... MATCH (pdf_summary) AGAINST ('test' IN BOOLEAN MODE) '%test%'
was natürlich nicht funktioniert.
Allerdings merke ich gerade das man es umgehen kann indem man das ganze so erzeugt:
$oLiteratures->setWhereGroup('fulltext', '', '(papiliteratures.pdf_summary) AGAINST (\''.$__string.'\' IN BOOLEAN MODE)', 'MATCH');
Ist glaube ich aber auch nicht so wichtig. Wer weiß wieviele das überhaupt so benutzen?
Verfasst: Mo 29. Aug 2005, 12:26
von timo
Also irgendwie komme ich nicht dahinter was du meinst
Kannst du ein Beispiel machen, in dem du einmal im Code ein setWhere (bzw setWhereGroup) verwendest und dann das resultierende SQL-Statement zeigst?
Mit dem Dump der _where-Teile kann ich im Moment nicht viel anfangen...
Verfasst: Mo 29. Aug 2005, 12:45
von devils.fist
Klar kann ich.
Beispiel bei dem es funktioniert:
Code: Alles auswählen
*snip*
$oLiteratures = new pApiLiteratures;
$oLiteratures->link('pApiLendings');
$oLiteratures->link('pApiCategories');
$oLiteratures->setWhereGroup('fulltext', '', '', 'MATCH (papiliteratures.pdf_summary) AGAINST (\''.$__string.'\' IN BOOLEAN MODE)');
$oLiteratures->setWhereGroup('spec', 'papiliteratures.title', "%".$spec_search_string."%", 'LIKE');
$oLiteratures->query();
*snip*
das resultierende SQL ist:
- SELECT papicategories.idpilit_category, papilendings.idpilit_lending, papiliteratures.idpilit_literature
FROM pilit_literature AS papiliteratures
LEFT JOIN pilit_category AS papicategories
ON papiliteratures.idpilit_category = papicategories.idpilit_category
LEFT JOIN pilit_lending AS papilendings
ON papiliteratures.idpilit_literature = papilendings.idpilit_literature
WHERE
(
MATCH (papiliteratures.pdf_summary) AGAINST ('test' IN BOOLEAN MODE)
)
AND
(
papiliteratures.title LIKE '%test%'
)
Soweit so gut. Das ist das was ich haben will. Vertausche ich die beiden setwheregroups folgendermaßen:
Code: Alles auswählen
$oLiteratures2 = new pApiLiteratures;
$oLiteratures2->link('pApiLendings');
$oLiteratures2->link('pApiCategories');
$oLiteratures2->setWhereGroup('spec', 'papiliteratures.title', "%test%", 'LIKE');
$oLiteratures2->setWhereGroup('fulltext', '', '', 'MATCH (papiliteratures.pdf_summary) AGAINST (\'test\' IN BOOLEAN MODE)');
$oLiteratures2->query();
wird dieses SQL erzeugt: (Das fette ist das Problem)
- SELECT papicategories.idpilit_category, papilendings.idpilit_lending, papiliteratures.idpilit_literature
FROM pilit_literature AS papiliteratures
LEFT JOIN pilit_category AS papicategories
ON papiliteratures.idpilit_category = papicategories.idpilit_category
LEFT JOIN pilit_lending AS papilendings
ON papiliteratures.idpilit_literature = papilendings.idpilit_literature
WHERE
(
papiliteratures.title LIKE '%test%'
)
AND
(
MATCH (papiliteratures.pdf_summary) AGAINST ('test' IN BOOLEAN MODE) '%test%'
)
Ich hoffe es wird klar
Verfasst: Mo 29. Aug 2005, 12:49
von emergence
ich glaub ich habs verstanden...
Verfasst: Mo 29. Aug 2005, 12:56
von timo
ah okay
naja die Methoden setWhere und setWhereGroup sind eigentlich nicht dafür ausgelegt, daß man solche "Hacks" verwendet. Ich prüfe aber gleich trotzdem nochmal nach, ob es sich da um Bugs handelt.
eigentlich sollte es viel eher so sein:
Code: Alles auswählen
$oLiteratures->setWhereGroup('papiliteratures.pdf_summary', 'test', 'MATCHBOOL');
Wobei setWhere und setWhereGroup den Operator MATCHBOOL in MATCH(<field>) AGAINST (<restriktion>) IN BOOLEAN MODE erweitern würde.
Ich bau mal da was ein.
Verfasst: Mo 29. Aug 2005, 13:43
von timo
devils.fist, kannst du mal nachsehen welche Contenido-Version (bzw welcher Snapshot) das ist?