PostgreSQL Externe C-Funktion
-
Hö? Wie meinste jetzt?
-
sataide schrieb:
Hö? Wie meinste jetzt?
Der
const char *s
im code wurde auf das erste Zeichen nach einem Anführungszeichen gesetzt.
Weil der String so angenommen wurde:
Linestring('0 0,1 1,1 2')
Mittlerweile ist mir klar, dass der String so aussieht:
Linestring(0 0,1 1,1 2)
Und Du trimst weiterhin in SQL, dann kommt ja nur noch
0 0,1 1,1 2
an.
D.h. s muss auch gar nicht angepasst werden und kann direkt auf PG_GETARG_CSTRING(0) gesetzt werden.PG_FUNCTION_INFO_V1(FCT_Norm); PGDLLEXPORT Datum FCT_Norm(PG_FUNCTION_ARGS) { // ©Wutz (https://www.c-plusplus.net/forum/329834) int n=0; double d; double sum=0.0; const char *s=PG_GETARG_CSTRING(0); while( 1==sscanf(s+=n,"%lf%*1[ ,]%n",&d,&n) ) { sum += d*d; } PG_RETURN_FLOAT8(sqrt(sum)); }
-
Wird direkt ausprobiert
-
Interessant.
Bei der Abfrage :
select FCT_Norm(trim(')' from trim('LINESTRING(' from st_AsText (coordinates)))) from germany_.ttopology LIMIT 100 ;
Gibt er mir 100 Zeilen mit 0 aus.(In paar Ms)
Geb ich aber 1000 ein hört er gar nicht mehr auf. Bin jetzt schon bei 3 Minuten.
-
Evtl. ist die Frage mittlerweile besser im DB Subforum aufgehoben.
Ich selbst habe auch keine Erfahrung mit Postgresql.
Kannst Du es nicht mal testen mit einer Kommandozeile o.ä.?
SELECT FCT_Norm('0 0,1 1,1 2');
-
Da gibt er mir auch ne 0 aus.
Wir wissen aber das er die C-Funktion benutzt, da er mir die Werte als double precission zurückgibt. Die Frage ist nur warum er mir eine 0 zurückgibt und keinen berechneten Wert.
-
Ich überfliege gerade dies: http://www.postgresql.org/docs/9.4/static/xfunc-c.html
Demnach müssen wir das Ergebnispalloc()
en und einen pointer darauf zurückgeben.Das musst Du nochmal genauer lesen.
Insbesondere diesen Tipp: "Hence, the standard internal function library is a rich source of coding examples for user-defined C functions." Solltest Du berücksichtigen und Dir ein paar Beispiele anschauen.
-
Die Seite hab ich schon nebenbei auf
Problem ist das meine Programmierkenntnisse noch ziemlich klein sind und mir diese Zeigergeschichte überhaupt nicht liegt.
Ich versuchs mal und meld mich dann wieder
-
Btw.
Muss ich den String auch pallocen oder nur das Ergebnis?
-
sataide schrieb:
Muss ich den String auch pallocen oder nur das Ergebnis?
Ich bin mir nicht einmal mehr sicher, ob das Ergebnis alloziert werden muss.
Sorry: da musst Du jemanden fragen, der sich damit auskennt. Chancen sind im Datenbank-Subforum besser.
-
Ich hab den Fehler. Es war kein PG_GETARG_CSTRING sondern ein PG_GETARG_TEXT_P. Nach ein paar Änderungen im Code läuft es endlich einwandfrei und hat die Abfragezeit um mehr als die Hälfte verkürzt.
Wollte mich nur für die Hilfe bedankenWenns wieder Probleme gibt meld ich mich
-
Eine Frage hätte ich noch?
Wie kann ich diese Splitfunktion in eine eigene funktion aufteilen?
Zum Beispiel
void string_split(*hier kommt der String rein
und dann
meine eigene Funktion, die diese Hilfsfunktion anwendet
PG_Function...s*char string_split(*string*)
...
-
sataide schrieb:
Eine Frage hätte ich noch?
Wie kann ich diese Splitfunktion in eine eigene funktion aufteilen?
Wie Du Funktionen schreibst mit Parametern und Rückgabewerten?
Das sollte in jedem C Buch erklärt werden.
Oder ich verstehe die Frage miß...Dein Entwurf von weiter oben im Thread
double return_of_spl_string(const char*s);
sieht jedenfalls ganz vielversprechend aus.
Freut mich übrigens, dass Deine Arbeit wirklich zu einer Performanzsteigerung führt.
Allerdings ist mir die Lösung, stattPG_GETARG_CSTRING
einfachPG_GETARG_TEXT_P
zu nehmen nicht ganz geheuer...
-
Nene du verstehst mich falsch ^^
Ich will eine allgemeine Funktion, die mit scanf einen String nach einem beliebigen delimiter splittet und als char[] ausgibt.
Wenn du willst poste ich den fertigen Code
Wie gesagt bei der PL/pgSQL-Funktion hat die ganze Sache ca. 8 Minuten gedauert und die externe C-Funktion 2 1/2 Minuten, was bei größeren Operationen wohl einen immensen Unterschied macht.
-
sataide schrieb:
Ich will eine allgemeine Funktion, die mit scanf einen String nach einem beliebigen delimiter splittet und als char[] ausgibt.
Mit scanf() einen String splittet?! Was soll das bedeuten?
Eventuell hilft
strtok();
aus der Standard C Bibliothek.
Aber die Dokumentation genau lesen! Du wirst auf jeden Fall den gesamten String kopieren müssen, und erst auf dieser beschreibaren Kopie mitstrtok()
arbeiten können.
-
Ich hab voll vergessen, dass ich einen funktionierenden Splitter habe
// The Splitfunction char** split_string1(char* str, const char* delim) { char* tmp; char** t = (char**)malloc(sizeof(char*) * 1024); char** tokens = t; tmp = strtok(str, delim); while(tmp != NULL) { *tokens = (char*)malloc(sizeof(char) * strlen(tmp+1)); *tokens = strdup(tmp); tokens++; tmp = strtok(NULL, delim); } return t; }
Er splittet den String ja nur auf einen Delimiter(Wahlweise " "oder ","). Mein Problem besteht halt , dass Ergebnis dieser Funktion wieder zu splitten mit genau diesen Funktion. Also muss diese Funktion 2 mal bei mir in der Main-funktion auftauchen.
-
Das Ding ist Schrott.
Zuviel überflüssiges
malloc
,strdup
ohnefree
und ohne Verstand.Du kannst den Formatstring von sscanf auch selber zusammen bauen:
char formatstring[100]; char delimiter[] = " ,"; strcpy(formatstring, "%lf%*1["); strcat(formatstring,delimiter); strcat(formatstring,"]%n"); // formatstring ist jetzt "%lf%*1[ ,]%n" while( 1==sscanf(s+=n, formatstring, &d, &n) ) { sum += d*d; }
Allerdings muss man wissen was man als delimiter schreibt, da man Rücksicht auf die Eigenheiten vom Formatspecifier %[ nehmen muss.
-
Eine ehrliche Antwort
Aber vielen Dank