mysql_query gibt unterschiedliches aus

mysql_query gibt unterschiedliches aus

am 28.03.2006 11:46:21 von Thomas Rachel

Hallo,

ich gehe mal davon aus, daß Fragen zur C-API von MySQL ebenfalls hier
ontopic sind.

Ich habe folgendes Problem: das (etwas komplizierte) SQL-Skript


create temporary table a (timestamp timestamp,typ
enum('Typ1','Typ2','Typ3'),wert double) engine=heap;
insert into a values(20030101,1,10.35),(20040625,3,30.54);
create temporary table b engine=heap select * from a;

select
concat(
max(typ),'-',
max(wert)-min(wert),'++++',
concat((max(wert)-min(wert))*86400/
(unix_timestamp(max(timestamp))-
unix_timestamp(min(timestamp))),'/d'),
'-Ente'
) as x
from a
union
select
concat(
max(typ),'/',
(max(wert)-min(wert)),'*',
concat((max(wert)-min(wert))*86400/
(unix_timestamp(max(timestamp))-
unix_timestamp(min(timestamp))),'/d'),
'-Ende'
) as y
from b


zeigt unterschiedliches Verhalten, je nachdem, ob ich den
Kommandozeilen-Client verwende oder dieeinzelnen Befehle per mysql_query
absende. Auch die Verwendung von mysql_real_query hat nichts geholfen.

mysql gibt folgendes aus:
+---------------------------------+
| x |
+---------------------------------+
| Typ3-20.19++++0.037322652699684 |
| Typ3/20.19*0.037322652699684/d- |
+---------------------------------+

Mein Programm hingegen ergibt folgendes:
Spalte 0 ist 30 Bytes lang: 'Typ3-20.19++++0.03732265269968' (30 nach
strlen).
Spalte 0 ist 30 Bytes lang: 'Typ3/20.19*0.037322652699684/d' (30 nach
strlen).

Die Strings sind also alle jeweils eine Stelle kürzer; aber strlen() und
mysql_fetch_lengths() waren sich über die angegebenen Längen einig.

In anderen, komplizierteren Varianten des Skriptes waren die Unterschiede
noch etwas gravierender.


Mir ist klar, daß die Queries alles andere als optimal sind[1], und daß die
Verwendung der geschachtelten concat()s in Verbindung mit union wohl auch
nicht so problemlos ist, aber gibt es einen Grund, daß das C-Interface was
anderes zurückgibt als der Kommandozeilenclient?

(Die Datei wird mittels (tr \\n ' ' | tr \; \\n | ./a.out verbrauch) entsprechend angepaßt, so daß die Abtrennung der einzelnen Queries korrekt
ist. Die Queries scheinen ja auch soweit zu stimmen - aber bei der Rückgabe
wird wohl was vermurkst.

Äh, ach so, ja. Version: 4.1.10a.


Hat jemand eine Idee, woran das liegen könnte?


TIA,

Thomas

[1] Hintergrund der Schachtelung von concat(): Debugging eines anderen
Programmes. Normalerweise macht das natürlich wenig Sinn. Aber
funktionieren sollte es doch trotzdem?

Re: mysql_query gibt unterschiedliches aus

am 28.03.2006 20:12:46 von Thomas Rachel

Thomas Rachel wrote:


> zeigt unterschiedliches Verhalten, je nachdem, ob ich den
> Kommandozeilen-Client verwende oder dieeinzelnen Befehle per
> mysql_query absende. Auch die Verwendung von mysql_real_query hat
> nichts geholfen.
>
> mysql gibt folgendes aus:
> +---------------------------------+
> | x |
> +---------------------------------+
> | Typ3-20.19++++0.037322652699684 |
> | Typ3/20.19*0.037322652699684/d- |
> +---------------------------------+
>
> Mein Programm hingegen ergibt folgendes:
> Spalte 0 ist 30 Bytes lang: 'Typ3-20.19++++0.03732265269968' (30 nach
> strlen).
> Spalte 0 ist 30 Bytes lang: 'Typ3/20.19*0.037322652699684/d' (30 nach
> strlen).
>
> Die Strings sind also alle jeweils eine Stelle kürzer; aber strlen()
> und mysql_fetch_lengths() waren sich über die angegebenen Längen einig.


Ich habe mir jetzt mal den Sourcecode von mysql runtergezogen und
angeschaut. Abgesehen davon, daß dort vorher noch
mysql_fetch_field(result) aufgerufen wird, habe ich keine Unterschiede
gemerkt, aber auch das selbst ebenfalls zu verwenden, hat
(erwartungsgemäß) nichts gebracht, ebensowenig das statische Linken von
libmysqlclient.a - naja, war zu erwarten, da ja beide Bibliotheken aus
demselben Paket stammen.

Vielleicht ist der Unterschied ja einfach darin zu sehen, daß der
Paketersteller irrtümlich eine andere Version der libmysqlclient.a
verwendet hat... Unwahrscheinlich, aber nicht ausgeschlossen, IMHO.


Naja, die Kaskadierung dieser concats fällt eh mit Ausbau der Anwendug
weg, von daher ist es nicht so tragisch, aber interessiert hätte es mich
schon... *schulterzuck*


Thomas

Re: mysql_query gibt unterschiedliches aus

am 29.03.2006 00:24:51 von Sven Paulus

Thomas Rachel wrote:
> concat(
> max(typ),'-',
> max(wert)-min(wert),'++++',
> concat((max(wert)-min(wert))*86400/
> (unix_timestamp(max(timestamp))-
> unix_timestamp(min(timestamp))),'/d'),
> '-Ente'
> ) as x
> mysql gibt folgendes aus:
> +---------------------------------+
> | x |
> +---------------------------------+
> | Typ3-20.19++++0.037322652699684 |

Ganz doofe Frage, ich glaube ich stehe voellig auf dem Schlauch: Wo
ist eigentlich das '-Ente' geblieben? Das muesste doch eigentlich
den zurueckgegebenen String beenden? Oder was uebersehe ich?

Re: mysql_query gibt unterschiedliches aus

am 29.03.2006 09:19:33 von Thomas Rachel

Sven Paulus wrote:

> Thomas Rachel wrote:
>> concat(
>> max(typ),'-',
>> max(wert)-min(wert),'++++',
>> concat((max(wert)-min(wert))*86400/
>> (unix_timestamp(max(timestamp))-
>> unix_timestamp(min(timestamp))),'/d'),
>> '-Ente'
>> ) as x
>> mysql gibt folgendes aus:
>> +---------------------------------+
>> | x |
>> +---------------------------------+
>> | Typ3-20.19++++0.037322652699684 |
>
> Ganz doofe Frage, ich glaube ich stehe voellig auf dem Schlauch: Wo
> ist eigentlich das '-Ente' geblieben? Das muesste doch eigentlich
> den zurueckgegebenen String beenden? Oder was uebersehe ich?

Das ist ein weiterer Punkt, der mich stutzig machte. Der gesamte Query
ist auch deshalb so länglich, weil der beschriebene Effekt nur auftritt,
wenn verschiedene Bedingungen verknüpft sind:

* typ ist hier ein enum, mit einem String sähe es nochmal anders aus
(besser).
* Es tritt nur auf, wenn ich, wie oben, die Funktion concat schachtele.
(Der Grund, weshalb ich das gemacht habe, ist der, daß ich
Teilausdrücke im aufrufenden Skript in Variablen ausgelagert hatte.)
* Und ich glaube, es muß noch eine gewisse Längendiskrepanz swischen den
beiden Union-Ergebnissen bestehen. (Daher das '++++'.)


Ich denke mal, daß das einfach ein Bug ist, der die auszugebende Länge im
Server falsch berechnet, weil, was weiß ich, die Länge berechnet wird,
bevor der String fertig ist oder so was.

Aber mein Hauptanliegen war, weshalb bekommen Programme wie mysql oder
php einen längeren String als andere? (Zwischendurch hatte ich auch mal
einen Query, der bei mysql und php die volle Länge zurückgab, in meinem
Programm jedoch nicht.)

Der relevante Programmausschnitt ist, unter der noch immer vorhandenen
Annahme der On-Topizität des C-APIS von MySQL:

[...]
MYSQL_ROW r;
while (r=mysql_fetch_row(res)) {
int i;
int anzahl_felder = mysql_num_fields(res);
unsigned long * lengths = mysql_fetch_lengths(res);
for(i = 0; i < anzahl_felder; i++) {
printf("Spalte %u ist %lu Bytes lang: '%s' (%d nach strlen).\n",
i, lengths[i],r[i],r[i]?strlen(r[i]):-1);
}
}
[...]

Zwar sollte ich vielleicht die Annahme rausstreichen, die Werte seien
nullterminiert (steht nichts davvon in der Funktionsbeschreibung), aber
wenn strlen und mysql_fetch_lengths in jedem Fall denselben Wert
anzeigen, ist es zumindest hier nicht die Ursache...

Danke jedenfalls für die Antwort - in habe
ich ja schn kurz angerissen, was ich mittlerweile selbst über mögliche
Ursachen des Fehlers denke - vermutlich ein Bug irgendwo in MySQL.
(Nein, Andreas, ich wechsele dennoch vorerst nicht zu PostgreSQL.)


Thomas
--
~~~~~~~Meersrauschen~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Meersrauschen~~~~~~~~~ ~~~~~~
~~~~~~~~~~~~~~~~~Meersrauschen~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Meersraus chen~~

Re: mysql_query gibt unterschiedliches aus

am 30.03.2006 10:54:40 von Thomas Rachel

Thomas Rachel wrote:

> mysql gibt folgendes aus:
> +---------------------------------+
> | x |
> +---------------------------------+
> | Typ3-20.19++++0.037322652699684 |
> | Typ3/20.19*0.037322652699684/d- |
> +---------------------------------+
>
> Mein Programm hingegen ergibt folgendes:
> Spalte 0 ist 30 Bytes lang: 'Typ3-20.19++++0.03732265269968' (30 nach
> strlen).
> Spalte 0 ist 30 Bytes lang: 'Typ3/20.19*0.037322652699684/d' (30 nach
> strlen).
>
> Die Strings sind also alle jeweils eine Stelle kürzer; aber strlen() und
> mysql_fetch_lengths() waren sich über die angegebenen Längen einig.

[und am Ende fehlt bei beiden Aufrufvarianten was.]


> Äh, ach so, ja. Version: 4.1.10a.

Nur zur Info (falls jemand später mal über diesen Thread stolpert): Bei
Version 4.0.15-Max tritt das Problem im übrigen nicht auf; da ist das
Ergebnis in beiden Aufrufvarianten korrekt - mit dem im OP angegebenen
Query: in beiden Fällen -En[dt]e am Schluß.

Fazit: Bug in der von mir verwendeten Version, kein Bug bei der Verwendung
des API...


Thomas