Обсуждение: Convert Datum* to char*

Поиск
Список
Период
Сортировка

Convert Datum* to char*

От
Masterprojekt Naumann1
Дата:
Hi,

I want to read an attribute value from a TupleTableSlot. When I try to convert an attribute of SQL type varchar from Datum* to char* with the help of the method TextDatumGetCString(...), sometimes there is a segmentation fault. The segmentation fault comes from the method TextDatumGetCString(...), which is defined in utils/builtins.h. Unfortunately, the fault is not always reproducible. I debugged the code and figured out that the value of result->tts_values[i] sometimes is random. It may be uninitialized memory. In other cases, the variable value is NULL. Then, I can just skip the conversion from Datum* to char*, so that there is no segmentation fault. I attached a patch with the code. The relevant line is:
char *value = TextDatumGetCString(result->tts_values[i]);
The SQL-Query is a simple "SELECT * from ..." on the TPC-H table customer. About every third execution leads to a segmentation fault.

Why is the memory of the variable uninitialized?
I am not very familiar with Postgres. Is there another method to get a varchar attribute out of a TupleTableSlot as string?

Best regards
Maria
Вложения

Re: Convert Datum* to char*

От
Heikki Linnakangas
Дата:
On 01/06/2014 03:09 PM, Masterprojekt Naumann1 wrote:
> I want to read an attribute value from a TupleTableSlot. When I try to
> convert an attribute of SQL type varchar from Datum* to char* with the help
> of the method TextDatumGetCString(...), sometimes there is a segmentation
> fault. The segmentation fault comes from the method
> TextDatumGetCString(...), which is defined in utils/builtins.h.
> Unfortunately, the fault is not always reproducible. I debugged the code
> and figured out that the value of result->tts_values[i] sometimes is
> random. It may be uninitialized memory. In other cases, the variable value
> is NULL. Then, I can just skip the conversion from Datum* to char*, so that
> there is no segmentation fault. I attached a patch with the code. The
> relevant line is:
> char *value = TextDatumGetCString(result->tts_values[i]);
> The SQL-Query is a simple "SELECT * from ..." on the TPC-H table customer.
> About every third execution leads to a segmentation fault.

Maybe the field is NULL? By convention, we normally set the Datum to 0 
on an SQL NULL, but you're supposed to check tts_isnull first, and 
ignore tts_values[x] when tts_isnull[x] is true.

- Heikki



Re: Convert Datum* to char*

От
Masterprojekt Naumann1
Дата:
Yes, in some cases, Datum is 0, which I test before conversion. Additionally, I looked at tts_isnull but it does not prevent the segmentation fault in some cases. The problem is. that sometimes the value is random, but I don't know why and how I can detect that case.


2014/1/6 Heikki Linnakangas <hlinnakangas@vmware.com>
On 01/06/2014 03:09 PM, Masterprojekt Naumann1 wrote:
I want to read an attribute value from a TupleTableSlot. When I try to
convert an attribute of SQL type varchar from Datum* to char* with the help
of the method TextDatumGetCString(...), sometimes there is a segmentation
fault. The segmentation fault comes from the method
TextDatumGetCString(...), which is defined in utils/builtins.h.
Unfortunately, the fault is not always reproducible. I debugged the code
and figured out that the value of result->tts_values[i] sometimes is
random. It may be uninitialized memory. In other cases, the variable value
is NULL. Then, I can just skip the conversion from Datum* to char*, so that
there is no segmentation fault. I attached a patch with the code. The
relevant line is:
char *value = TextDatumGetCString(result->tts_values[i]);
The SQL-Query is a simple "SELECT * from ..." on the TPC-H table customer.
About every third execution leads to a segmentation fault.

Maybe the field is NULL? By convention, we normally set the Datum to 0 on an SQL NULL, but you're supposed to check tts_isnull first, and ignore tts_values[x] when tts_isnull[x] is true.

- Heikki

Re: Convert Datum* to char*

От
Craig Ringer
Дата:
On 01/06/2014 09:09 PM, Masterprojekt Naumann1 wrote:

> Why is the memory of the variable uninitialized?

Are there any other patches you've made to the running PostgreSQL instance?

I'd want to run under Valgrind and see what turned up. This might be a
bit tricky with an intermittent fault during something like a TPC-H run,
though.

-- Craig Ringer                   http://www.2ndQuadrant.com/PostgreSQL Development, 24x7 Support, Training & Services



Re: Convert Datum* to char*

От
Masterprojekt Naumann1
Дата:
2014/1/6 Craig Ringer <craig@2ndquadrant.com>
On 01/06/2014 09:09 PM, Masterprojekt Naumann1 wrote:

> Why is the memory of the variable uninitialized?

Are there any other patches you've made to the running PostgreSQL instance?

I'd want to run under Valgrind and see what turned up. This might be a
bit tricky with an intermittent fault during something like a TPC-H run,
though.

--
 Craig Ringer                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services

I am on the latest commit of the master branch of the GitHub repository (commit 10a82cda67731941c18256e009edad4a784a2994) and I only applied the attached patch. I hope that you can reproduce the fault.
Thanks, Maria

Re: Convert Datum* to char*

От
Thomas Fanghaenel
Дата:
On Mon, Jan 6, 2014 at 8:09 AM, Masterprojekt Naumann1
<mpws2013n1@gmail.com> wrote:
> Why is the memory of the variable uninitialized?

Are you checking that "i <= slot->tts_nvalid" before accessing the
tts_values and tts_isnull arrays?



Re: Convert Datum* to char*

От
Masterprojekt Naumann1
Дата:
2014/1/6 Thomas Fanghaenel <tfanghaenel@salesforce.com>
On Mon, Jan 6, 2014 at 8:09 AM, Masterprojekt Naumann1
<mpws2013n1@gmail.com> wrote:
> Why is the memory of the variable uninitialized?

Are you checking that "i <= slot->tts_nvalid" before accessing the
tts_values and tts_isnull arrays?


Thanks for your ideas! I could fix the segmentation fault. I have to check both, slot->tts_isnull and 0 == slot->tts_values[i]. If both are false, I can convert the value with the method TextDatumGetCString(...).
Nevertheless, slot->tts_nvalid is always 0. I hope that there is no other problem.

Re: Convert Datum* to char*

От
Tom Lane
Дата:
Masterprojekt Naumann1 <mpws2013n1@gmail.com> writes:
> Nevertheless, slot->tts_nvalid is always 0. I hope that there is no other
> problem.

You should not be touching the tts_values/tts_isnull arrays without having
first called slot_getsomeattrs or slot_getallattrs.

See comments in src/include/executor/tuptable.h for some documentation.
        regards, tom lane



Re: Convert Datum* to char*

От
Robert Haas
Дата:
On Mon, Jan 6, 2014 at 11:34 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Masterprojekt Naumann1 <mpws2013n1@gmail.com> writes:
>> Nevertheless, slot->tts_nvalid is always 0. I hope that there is no other
>> problem.
>
> You should not be touching the tts_values/tts_isnull arrays without having
> first called slot_getsomeattrs or slot_getallattrs.
>
> See comments in src/include/executor/tuptable.h for some documentation.

Another problem is that TextDatumGetCString() is only the right thing
to do if the value is, in fact, of type text.  If you've got an
integer column, for example, TextDatumGetCString() is not your friend.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company