-- Find thousand and decimal digits separators CREATE OR REPLACE FUNCTION CDB_DigitSeparator (rel REGCLASS, fld TEXT, OUT t CHAR, OUT d CHAR) as $$ DECLARE sql TEXT; rec RECORD; BEGIN -- We're only interested in rows with either "," or '.' sql := 'SELECT ' || quote_ident(fld) || ' as f FROM ' || rel::text || ' WHERE ' || quote_ident(fld) || ' ~ ''[,.]'''; FOR rec IN EXECUTE sql LOOP -- Any separator appearing more than once -- will be assumed to be thousand separator IF rec.f ~ ',.*,' THEN t := ','; d := '.'; RETURN; ELSIF rec.f ~ '\..*\.' THEN t := '.'; d := ','; RETURN; END IF; -- If both separator are present, rightmost -- will be assumed to be decimal separator IF rec.f ~ '\.' AND rec.f ~ ',' THEN rec.f = reverse(rec.f); IF strpos(rec.f, ',') < strpos(rec.f, '.') THEN t := '.'; d := ','; ELSE t := ','; d := '.'; END IF; RETURN; END IF; -- A separator NOT followed by 3 digits -- will be assumed to be decimal separator IF rec.f ~ ',' AND rec.f !~ '(,[0-9]{3}$)|(,[0-9]{3}[,.])' THEN t := '.'; d := ','; RETURN; ELSIF rec.f ~ '\.' AND rec.f !~ '(\.[0-9]{3}$)|(\.[0-9]{3}[,.])' THEN t := ','; d := '.'; RETURN; END IF; -- Otherwise continue looking END LOOP; END $$ LANGUAGE 'plpgsql' STABLE STRICT PARALLEL SAFE;