Newsgroup: it.comp.www.php
Titolo: Sostituzione carattere in postgres

Siamo nel ng di php, ma credo qui ci sia la piu' alta densita'
di lettori con esperienza postgres, perdonatemi :).
Ho un campo text in postgres 7.1.3, devo sostituire la lettera
č (se non si leggesse e' e accentata grave) con &egrave;
Ho visto purtroppo che la funzione translate di postgres sostituisce
solo un numero uguale di caratteri rispetto a quelli cercati, cosi'
se faccio
update tabella set campo = translate(campo, 'č', '&egrave;');
mi ritrovo solo & dopo l'update. Qualche soluzione? Devo farmi
uno script php con 2*n query? (lettura + scrittura)
-- 
Ciao,           | Sostituisci "dontspam" con "softhome"
 Francesco      | nell'indirizzo email per avere quello corretto

 
prima di inserire traduci con htmlspecialchars($testo)
ciao

 prima di inserire traduci con htmlspecialchars($testo)
Ahem, quello lo so. Ma il problema era di altro tipo: ho dei campi
del db in cui ci dovrebbero essere solo caratteri html, ma dove
invece ci sono andate a finire delle accentate per un bug.
Ora, se io faccio htmlspecialchars di quei campi, viene fuori un
casino, perche' la funzione mi traduce anche i minore e maggiore
dei tag html.
Per questo ho bisogno di sistemare i campi, non da php, ma una volta
per tutte da db, visto che ho sistemato il bug


 del db in cui ci dovrebbero essere solo caratteri html, ma dove
Per caratteri html intendo &gt; &amp; e compagnia, giusto per specificare


per tutte da db, visto che ho sistemato il bug
E' una funzioncina interessante. Se ce la fai a reggere un paio di
giorni quasi quasi me la scrivo :-)
Leonardo

 giorni quasi quasi me la scrivo :-)
Per lei messere questo ed altro :).
In realta' con google l'ho trovata la funzione che cercavo, pero'
usa il linguaggio plperl che non ho nel mio postgres (sto sotto OS/2
e non sono attualmente in condizione di ricompilare)


 
se vuoi sostituire solo alcuni caratteri:
soluzione PHP:
<?
#in paths i caratteri che vuoi sostituire
$paths="айимтщ";
$stringa="lм и meglio di lа!";
for($i=0;$i<strlen($paths);$i++)
	{
	$stringa=ereg_replace($paths[$i],htmlentities($paths[$i]),$stringa);
	}
print $stringa;
?>
il brutto и che per ogni carattere da sostituire c'и un ciclo!
(и raffinabile, penso).
se vuoi una soluzione postgres devi scriverti una funzione plpgsql...
(magari la scrivo e in futuro la posto!)
ciao

 (magari la scrivo e in futuro la posto!)
Ecco e' appunto quella che cerco, vedete un po' voi chi ha voglia
di scriverla questa funzioncina :). Io non mi sono ancora addentrato
nel mondo della programmazione pgsql, indubbiamente in certi
casi risulta molto utile. Diciamo che una sostituzione di stringhe
invece che di caratteri potevano anche mettercela nelle funzioni
predefinite


 
la funzione che posto, creata on-the-fly, prende in input come prima 
stringa la stringa da elaborare e come seconda i caratteri da convertire...
purtroppo plpgsql non supporta varray, così anziché &amp; (esempio) diventa 
&#38; e così via.
funziona con qualsiasi carattere, anche gli alfanumerici normali.
es questo traduce <, > e ':
select html_translate ('minore < maggiore > apostrofo \'','<\'>');
               html_translate                
---------------------------------------------
 minore &#60; maggiore &#62; apostrofo &#39;
e questo traduce tutto:
test=# select html_translate ('minore'  ,  'minore');
            html_translate            
--------------------------------------
 &#109;&#105;&#110;&#111;&#114;&#101;
non è molto raffinata ma per certi versi può essere utile!!
(a vista non mi sembra che abbia bug o condizioni di non uscita. 
controllate anche voi!)
ciauz!
drop function html_translate(varchar, varchar);
create function html_translate(varchar, varchar) returns varchar as '
declare
	leninput integer;
	lenstringa integer;
	cinput integer;
	cstringa integer;
	stringa alias for $1;
	input alias for $2;
	ret varchar := '''';
	notfound integer;
begin
	select length(stringa) into lenstringa;
	if length(input) = 0 then
		return stringa;
	end if;
 
	cstringa := 0;
	-- ciclo per ogni carattere nella stringa
	loop
		select length(input) into leninput; 
		cinput := 0;
		notfound := leninput;
 
		-- ciclo per ogni carattere da tradurre
		loop
			if substr(stringa,cstringa+1,1) = 
substr(input,cinput+1,1)
			then
				ret := ret || ''&#'' || 
ascii(substr(stringa,cstringa+1,1)) || '';'';
			else
				notfound := notfound - 1;
			end if;
 
			cinput := cinput + 1;
 
			-- condizione di uscita
			if cinput >= leninput
			then 
				exit;
			end if;
 
		end loop;
		if notfound = 0 then
			ret := ret || substr(stringa,cstringa+1,1);
		end if;
		cstringa := cstringa + 1;
		-- coindizione di uscita
		if cstringa >= lenstringa
		then
			exit;
		end if;
	end loop;
	return ret;
end;
' LANGUAGE 'plpgsql';

e non sono attualmente in condizione di ricompilare)
Uhm. La mia idea era di scriverla in C. E magari con il supporto per le
espressioni regolari - quando si comincia a mastubbàssi, 'gna fallo per
benino.
As-is, niente garanzie, ohiqui ohili'.
/*
create function replace (text, text, text) returns text
                as '/usr/src/postgres-functions/replace.so'
                language 'c'
gcc -I../postgresql-7.1.3/src/backend -Iinclude -O3 -Wall -mpentiumpro  \
	-fPIC -shared 							\
	-o replace.so replace.c
Syntax: replace('source', 'list-src', 'list-dst');
Example:
select replace( 'The quick brown fox jumped over the lazy dog',
                'dog,jumped,lazy,over,fox,dog,quick,brown,quick,The,the',
                'database!,will run,closed source,circles around,system,
                 Bill Gates,open,source,Linus Torvalds,Any,a');
Shamelessly inspired to PHP's ereg_replace.
*/
#ifndef DEBUGGING 
#include "postgres.h"
#endif
#include <ctype.h>
#include <time.h>
#ifndef DEBUGGING
#include "fmgr.h"
#include "utils/builtins.h"
#include "utils/palloc.h"
#define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))
#define _textout(str) DatumGetPointer(DirectFunctionCall1(textout,
PointerGetDatum(str)))
#else
	#define	palloc		malloc
	#define	repalloc	realloc
#endif
// REPLACE('pippero', 'pi,pero', 's,in') = 'spin';
// Questa funzione ritorna una stringa allocata contenente
// la traduzione di 'una' serie di orig, in 'una' serie di
// repl. 'Source' e' distrutta.
inline char *replace_one(char *source, const char *orig, const char *repl)
{
	// Usiamo una macchina a stati
	short int st = 0;
	size_t i, j;
	char *rbuf = NULL;
	size_t rsiz, clen, xlen, predlen, maxlen;
	rsiz = 0;
	predlen= strlen(source)+1;
	clen = strlen(orig);
	xlen = strlen(repl);
	maxlen = predlen+2*( xlen > clen ? xlen-clen : 0);
	if (NULL==(rbuf = malloc(maxlen)))
		return source;
	for(i=0; source[i]!=0; i++)
	{
		if (source[i]!=orig[st])
		{
			for (j=0; j < st; j++)
				rbuf[rsiz++] = orig[j];
			st = 0;
		}
		if (source[i]==orig[st])
		{
			if (++st==clen)
			{
				predlen += (xlen > clen ? xlen-clen : 0);
				if (predlen > maxlen)
				{
					char *tbuf;
					maxlen = predlen + xlen;
					if (NULL==(tbuf=realloc(rbuf,
maxlen)))
					{
						free(rbuf);
						return source;
					}
					rbuf = tbuf;
				}
				for (st=0; st < xlen; st++)
					rbuf[rsiz++] = repl[st]; 
				st = 0;
			}
		}
		else
			rbuf[rsiz++] = source[i];
	}
	rbuf[rsiz] = 0;
	free(source);
	return rbuf;
}
char *replace_all(char *original, char *source, char *dest)
{
	char **src = NULL, **dst = NULL;
	char *tok;
	int  token, tokens, maxtokens = 0;
	char *result = NULL;
	// result will be destroyed (repeatedly) by replace_one.	
	result = strdup(original);
	for ( token = 0, tok = strtok(source,","); tok; tok=strtok(NULL,
","))
	{
		if (token >= maxtokens)
		{
			maxtokens += 16;
			src = realloc(src, maxtokens * sizeof(char *));
			dst = realloc(dst, maxtokens * sizeof(char *));
		}
		src[token++] = tok;
	}
	tokens = token;
	for (token = 0, tok = strtok(dest, ","); tok; tok=strtok(NULL,
","))
	{
		if (token > tokens)
			break;	// Too many tokens!
		dst[token++] = tok;
	}
	if (token != tokens)
	{
		free(dst);
		free(src);
		return result;
	}
	// result=malloc(256); sprintf(result, "Found %d dst tokens",
tokens); return result;
	for (token=0; token < tokens; token++)
	{
		if (src[token] && dst[token])
		{
			//printf("Replacing '%s' with '%s'\n", src[token],
dst[token]);
			result = replace_one(result, src[token],
dst[token]);
			//printf("Result is now:
'%s'\n------------------\n", result);
		}
	}
	free(dst);
	free(src);
	return result;
}
#ifdef DEBUGGING
// debugging source code, at no additional cost.
int main(int argc, char **argv)
{
	int i;
	char *pippo;
	char *s1, *s2;
	if (argc != 4)
	{
		fprintf(stderr, "Syntax: DEBUG original 'a,b,c'
'a1,b1,c1'\n");
		return -1;
	}
	pippo = strdup(argv[1]);
	s1 = strdup(argv[2]);
	s2 = strdup(argv[3]);
	// Profiling, the hard and tough-shit way.
	for (i=0; i < 1000000; i++)
	{
		strcpy(pippo, argv[1]);
		strcpy(s1, argv[2]);
		strcpy(s2, argv[3]);
		printf("\n\n-----------------\n%s\n----------------\n",
replace_all(pippo, s1, s2));
	}
	free(s2); free(s1); free(pippo);
	return 0;
}
#else
PG_FUNCTION_INFO_V1(replace);
Datum replace(PG_FUNCTION_ARGS)
{
	text		*arg[3];
	char		*buf[3];
	size_t		i;
	text	   *res;
	for (i=0; i < 3; i++)
	{
		unsigned len;
		if (PG_ARGISNULL(i))
		{
			size_t j;
			// Destroy allocated data.
			for (j=0; j < i; j++)
			{
				free(buf[j]);
				PG_FREE_IF_COPY(arg[j], j);
			}
			PG_RETURN_NULL();
		}
		arg[i] = PG_GETARG_TEXT_P(i);
		len = VARSIZE(arg[i]) - VARHDRSZ;
		buf[i] = malloc(len+1);
		memcpy(buf[i], VARDATA(arg[i]), len);
		buf[i][len] = 0x0;
	}
	// Now we may use buf[], which will return a malloc'ed pointer
*unsuitable* for returning to PostgreSQL.
	// We must free it, and return a palloc'ed value to PostgreSQL.
	buf[0] = replace_all(buf[0], buf[1], buf[2]);
	i = strlen(buf[0]);
	res = (text *) palloc(i + VARHDRSZ);
	VARATT_SIZEP(res) = i + VARHDRSZ;
	memcpy(VARDATA(res), buf[0], i); // Non-ASCIIZ
 
	for (i=0; i < 3; i++)
	{
		if (buf[i])
			free(buf[i]);
		PG_FREE_IF_COPY(arg[i], i);
	}
	PG_RETURN_TEXT_P(res);
}
#endif
Leonardo
-- 
And where the black and corkscrew towers climb
Lost and athirst the ragged pack abides,
Old as the aeons, trapped in tombs of time,
Sailing the tortuous temporal tides...

 wrote in
news:noe47u0e0623dh9ar...@L.Serni: 

mi sembra ottimo!!
ciao

 mi sembra ottimo!!
Non c'era comunque bisogno di riportarlo tutto.
Bye,
 Emmanuele.
-- 
Emmanuele Bassi (Zefram)           [ 
http://www.radiance.d2g.com/~zefram
 ]
GnuPG Key fingerprint = 4DD0 C90D 4070 F071 5738  08BD 8ECC DB8F A432 0FF4

 Non c'era comunque bisogno di riportarlo tutto.
c'hai ben ragione...
sono una bestia a tagliare i testi precedenti!!
cercherò di migliorare
(comunque era un post lodevole, il codicillo...)

mi sembra ottimo!!
Lo standard AOL prevede che dopo il quote integrale, se aggiungi meno di
due righe, tu debba SCRIVERE IN MAIUSCOLO.
Leonardo e la compliance con gli standards ;-)


 Leonardo e la compliance con gli standards ;-)
ALLORA TI PROPONGO DI SCRIVERE UN MANUALE DI SOPRAVVIVENZA PER I NG