Thread

  1. Re: Remaining dependency on setlocale()

    Jeff Davis <pgsql@j-davis.com> — 2025-12-16T20:04:54Z

    On Tue, 2025-12-16 at 09:32 +0800, Chao Li wrote:
    > I have re-reviewed 0003-0005 last week, they all look good to me.
    > 
    > I have no comment on backport 0003.
    
    Committed 0003 and backported to 14.
    
    Committing 0004 also. For the archives, the bug in that case is:
    
      -- generate some randomly-cased non-ASCII data
      CREATE DATABASE i TEMPLATE template0 LOCALE 'C'
        LOCALE_PROVIDER 'icu' ICU_LOCALE 'en';
      \c i
      CREATE EXTENSION ltree;
      CREATE TABLE test(path ltree);
      CREATE FUNCTION gen() RETURNS TEXT LANGUAGE plpgsql AS $$
        declare
          s TEXT;
        begin
          s := '';
          for i in 1..5 loop
            s := s || case when random() > 0.5 then lower(U&'\00C1') else
    U&'\00C1' end;
            s := s || case when random() > 0.5 then lower(U&'\00C9') else
    U&'\00C9' end;
            s := s || case when random() > 0.5 then lower(U&'\00CD') else
    U&'\00CD' end;
            s := s || case when random() > 0.5 then lower(U&'\00D3') else
    U&'\00D3' end;
            s := s || case when random() > 0.5 then lower(U&'\00DA') else
    U&'\00DA' end;
          end loop;
          return s;
        end;
      $$;
      INSERT INTO test select ('a.'||gen()||'.z')::ltree
        FROM generate_series(1,10000);
      CREATE INDEX test_idx ON test USING gist (path);
      -- returns 10000
      SET enable_seqscan = true;
      SET enable_indexscan = false;
      SET enable_bitmapscan = false;
      SELECT COUNT(*) FROM test
        WHERE path ~ U&'a.áéíóúáéíóúáéíóúáéíóúáéíóú@.z'::lquery;
      -- returns fewer tuples when using index scan
      SET enable_seqscan = false;
      SET enable_indexscan = true;
      SET enable_bitmapscan = true;
      SELECT COUNT(*) FROM test
        WHERE path ~ U&'a.áéíóúáéíóúáéíóúáéíóúáéíóú@.z'::lquery;
    
    Probably a smaller case would do, but I think it requires page splits
    to hit the bug. 0004 fixes the bug.
    
    > The old code didn’t create a locale object and store in result, thus
    > it didn’t have a logic to free the created locale. This patch now
    > dose that, but I don’t see where the created locale object is free-
    > ed. I suppose newlocale() will allocate memory from the OS, so I
    > guess the memory should be free-ed somewhere.
    
    The pg_locale_t objects are cached for the life of the backend, and
    never freed. We may want to change that eventually, but in practice
    it's not much of a problem.
    
    Regards,
    	Jeff Davis