0

I am trying to convert a C String to character internal representation of PostgreSQL. I am using bpcharin function in varchar.c. This function requires two arguments : the C String Datum and the atttypmod. It is mentioned that atttypmod is the declared length of the type plus VARHDRSZ.

My conversion function is:

result = DirectFunctionCall2(bpcharin,
                        CStringGetDatum(str),
                        VARHDRSZ + ?);

My string str value will be one of the column datatype of my table. So, I require the declared column data type length. This information is stored in character_maximum_length of information_schema.columns view.

My question is, how do I get the character_maximum_length in C code?

Thank you.

1 Answer 1

1

Unless you're using the char data type, you don't need bpchar.

A simple CStringGetDatum (for cstring typed values) or CStringGetTextDatum (for text typed values) is sufficient.


It seems you are using char(n), i.e. bpchar. Frankly, the best thing to do is not to do that; it's a quirky type that should be replaced with a plain text or varchar in almost all cases.

If you must use it... well, lets take a look at pg_cast:

regress=> select c.*, tfrom.typname, f.proname 
              from pg_cast c 
              inner join pg_type tfrom on c.castsource = tfrom.oid 
              inner join pg_type tto on c.casttarget = tto.oid 
              left outer join pg_proc f on c.castfunc = f.oid
              where tto.typname = 'bpchar';
 castsource | casttarget | castfunc | castcontext | castmethod | typname | proname 
------------+------------+----------+-------------+------------+---------+---------
         25 |       1042 |        0 | i           | b          | text    | 
       1043 |       1042 |        0 | i           | b          | varchar | 
         18 |       1042 |      860 | a           | f          | char    | bpchar
         19 |       1042 |      408 | a           | f          | name    | bpchar
        650 |       1042 |      730 | a           | f          | cidr    | text
        869 |       1042 |      730 | a           | f          | inet    | text
         16 |       1042 |     2971 | a           | f          | bool    | text
        142 |       1042 |        0 | a           | b          | xml     | 
       1042 |       1042 |      668 | i           | f          | bpchar  | bpchar
(9 rows)

There are castmethod = 'b' entries for text and varchar. Per the manual, b means:

that the types are binary-coercible, thus no conversion is required

... so you can use CStringGetTextDatum to produce a bpchar. However, no length checking will be performed.

If you want type checking you must call the bpchar function, which is called on char-to-char casts. It'll do length checking/truncation. It takes three args - the text, the max length, and whether it's an implicit or explicit cast.

e.g. (untested):

DirectFunctionCall3( 
      CStringGetTextDatum(my_cstr), 
      Int32GetDatum(max_len),
      BoolGetDatum(false) 
    );

The last arg controls the truncation rules; see the comments on bpchar in src/backend/utils/adt/varchar.c for details.

Sign up to request clarification or add additional context in comments.

3 Comments

I am using a char datatype. What should be done in that case?
@user2761431 Blech - the best thing to do is not use bpchar. But see edit above.
Thanks for the answer. I think my issue was finding that max_len. Any suggestions there? And, I am using the TPCH database and almost every relation has a CHAR(n) datatype.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.