Fehler in class.genericdb.php

devils.fist
Beiträge: 24
Registriert: Fr 5. Aug 2005, 10:20
Wohnort: Wolfsburg
Kontaktdaten:

Fehler in class.genericdb.php

Beitrag von devils.fist » Mo 15. Aug 2005, 10:24

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.")";
		}

emergence
Beiträge: 10641
Registriert: Mo 28. Jul 2003, 12:49
Wohnort: Austria
Kontaktdaten:

Beitrag von emergence » Do 18. Aug 2005, 10:44

punkt 1 kann ich bestätigen

bei punkt 2 und 3 muss ich nachhaken...

hast du da ein beispiel das man das testen kann ?
*** make your own tools (wishlist :: thx)

devils.fist
Beiträge: 24
Registriert: Fr 5. Aug 2005, 10:20
Wohnort: Wolfsburg
Kontaktdaten:

Beitrag von devils.fist » Do 18. Aug 2005, 11:04

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.

devils.fist
Beiträge: 24
Registriert: Fr 5. Aug 2005, 10:20
Wohnort: Wolfsburg
Kontaktdaten:

Beitrag von devils.fist » Do 18. Aug 2005, 12:10

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));
	}

emergence
Beiträge: 10641
Registriert: Mo 28. Jul 2003, 12:49
Wohnort: Austria
Kontaktdaten:

Beitrag von emergence » Do 18. Aug 2005, 12:13

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...
*** make your own tools (wishlist :: thx)

devils.fist
Beiträge: 24
Registriert: Fr 5. Aug 2005, 10:20
Wohnort: Wolfsburg
Kontaktdaten:

Beitrag von devils.fist » Do 18. Aug 2005, 12:14

die innergroupcondition muss nicht gesetzt sein. Das ist im Quelltext nur historisch bedingt, die gruppe war mal größer.

emergence
Beiträge: 10641
Registriert: Mo 28. Jul 2003, 12:49
Wohnort: Austria
Kontaktdaten:

Beitrag von emergence » Sa 20. Aug 2005, 10:08

devils.fist hat geschrieben:die innergroupcondition muss nicht gesetzt sein. Das ist im Quelltext nur historisch bedingt, die gruppe war mal größer.
ok...
*** make your own tools (wishlist :: thx)

timo
Beiträge: 6284
Registriert: Do 15. Mai 2003, 18:32
Wohnort: Da findet ihr mich nie!
Kontaktdaten:

Beitrag von timo » Fr 26. Aug 2005, 13:39

also den Schreibfehler sowie die Klammern um die Gruppe habe ich korrigiert

Bei Punkt 3 komme ich nicht dahinter was du meinst ;)

emergence
Beiträge: 10641
Registriert: Mo 28. Jul 2003, 12:49
Wohnort: Austria
Kontaktdaten:

Beitrag von emergence » Sa 27. Aug 2005, 14:15

@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...
*** make your own tools (wishlist :: thx)

devils.fist
Beiträge: 24
Registriert: Fr 5. Aug 2005, 10:20
Wohnort: Wolfsburg
Kontaktdaten:

Beitrag von devils.fist » Mo 29. Aug 2005, 11:29

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?

timo
Beiträge: 6284
Registriert: Do 15. Mai 2003, 18:32
Wohnort: Da findet ihr mich nie!
Kontaktdaten:

Beitrag von timo » Mo 29. Aug 2005, 12:26

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...

devils.fist
Beiträge: 24
Registriert: Fr 5. Aug 2005, 10:20
Wohnort: Wolfsburg
Kontaktdaten:

Beitrag von devils.fist » Mo 29. Aug 2005, 12:45

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

emergence
Beiträge: 10641
Registriert: Mo 28. Jul 2003, 12:49
Wohnort: Austria
Kontaktdaten:

Beitrag von emergence » Mo 29. Aug 2005, 12:49

ich glaub ich habs verstanden...
*** make your own tools (wishlist :: thx)

timo
Beiträge: 6284
Registriert: Do 15. Mai 2003, 18:32
Wohnort: Da findet ihr mich nie!
Kontaktdaten:

Beitrag von timo » Mo 29. Aug 2005, 12:56

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.

timo
Beiträge: 6284
Registriert: Do 15. Mai 2003, 18:32
Wohnort: Da findet ihr mich nie!
Kontaktdaten:

Beitrag von timo » Mo 29. Aug 2005, 13:43

devils.fist, kannst du mal nachsehen welche Contenido-Version (bzw welcher Snapshot) das ist?

Gesperrt