Обсуждение: bytea question
hi all, in the pg_trigger table the tgargs column is defined as type "BYTEA". i can split this up in perl, once retrieved, but can't figure out how to "substring" it in sql. is there an SQL way to select pieces of a column of this type? any help is appreciated, mikeo
Try
substr(text,int4) or
substr(text, int4, int4)
For example,
% select substr('hi there',4,3);
substr
--------
the
(1 row)
Morey Parang
ORNL
On Tue, Aug 15, 2000 at 03:34:27PM -0400, mikeo wrote:
> hi all,
> in the pg_trigger table the tgargs column is defined
> as type "BYTEA". i can split this up in perl, once
> retrieved, but can't figure out how to "substring"
> it in sql. is there an SQL way to select pieces of
> a column of this type?
>
> any help is appreciated,
>
> mikeo
thanks anyway but that doesn't work. i should've mentioned that i'd
already tried that in SQL. my apologies.
tig4=# \d x
Table "x"
Attribute | Type | Modifier
-----------+-------+----------
tgargs | bytea |
tig4=# select substr(tgargs,1,5) from x;
ERROR: Function 'substr(bytea, int4, int4)' does not exist
Unable to identify a function that satisfies the given argument types
You may need to add explicit typecasts
tig4=# select substr(tgargs::text,1,5) from x;
ERROR: Cannot cast type 'bytea' to 'text'
and other things like varchar, etc.
tig4=# select * from x;
tgargs
------------------------------------------------------------------------------
fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
what i'm looking to do here is to get the table names and column names out
using sql. i can do it in perl with a split command on '\' but was curious
as to how to "SQL" split up a BYTEA type field.
mikeo
At 04:38 PM 8/15/00 -0400, mjp@ornl.gov wrote:
>Try
>
>substr(text,int4) or
>substr(text, int4, int4)
>
>For example,
>
>
>% select substr('hi there',4,3);
> substr
>--------
> the
>(1 row)
>
>Morey Parang
>ORNL
Well, I don't think you're going to be able to without resorting to
something other than straight sql (a c function would probably work).
You can get the value of a particular byte using get_byte(bytea,int)
but I can't think of a good way outside of some sort of function to
turn that into a split.
Also, get_byte elogs if the int is outside the range of octets on
the bytea. I would have expected it to work closer to substr on
text.
Stephan Szabo
sszabo@bigpanda.com
On Tue, 15 Aug 2000, mikeo wrote:
> thanks anyway but that doesn't work. i should've mentioned that i'd
> already tried that in SQL. my apologies.
>
>
> tig4=# \d x
> Table "x"
> Attribute | Type | Modifier
> -----------+-------+----------
> tgargs | bytea |
>
> tig4=# select substr(tgargs,1,5) from x;
> ERROR: Function 'substr(bytea, int4, int4)' does not exist
> Unable to identify a function that satisfies the given argument types
> You may need to add explicit typecasts
>
> tig4=# select substr(tgargs::text,1,5) from x;
> ERROR: Cannot cast type 'bytea' to 'text'
>
> and other things like varchar, etc.
>
> tig4=# select * from x;
> tgargs
> ------------------------------------------------------------------------------
> fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
> fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
> fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
>
> what i'm looking to do here is to get the table names and column names out
> using sql. i can do it in perl with a split command on '\' but was curious
> as to how to "SQL" split up a BYTEA type field.
>
> mikeo
>
>
> At 04:38 PM 8/15/00 -0400, mjp@ornl.gov wrote:
> >Try
> >
> >substr(text,int4) or
> >substr(text, int4, int4)
> >
> >For example,
> >
> >
> >% select substr('hi there',4,3);
> > substr
> >--------
> > the
> >(1 row)
> >
> >Morey Parang
> >ORNL
>
Oops! You have to write a function for it. Here is a
sample quick C function:
typedef struct
{ int len;
char data[1];
} string;
string *byteatostr(bytea *arg)
{
char buf[1024];
int ln,i;
string *res;
ln = VARSIZE(arg) - VARHDRSZ;
memmove(buf, VARDATA(arg), ln);
for(i=0; i < ln; i++)
if( buf[i] < 32 ) buf[i]='?';
res = (string *) palloc(VARHDRSZ + ln);
memset(res, 0, VARHDRSZ + ln);
res->len = VARHDRSZ + ln;
memmove(res->data, buf, (int) ln);
return res;
}
where all non-printable chars are replaced with '?'. Optionally,
the chars can be escaped (prefixed with '\') - adjusting ln as neccessry.
now you get:
# select byteatostr(col) from test2;
byteatostr
------------------------------------------------------------
fk_uste_wu_id?us_states?web_users?UNSPECIFIED?wu_id?wu_id?
(1 rows)
On Tue, Aug 15, 2000 at 05:23:38PM -0400, mikeo wrote:
> thanks anyway but that doesn't work. i should've mentioned that i'd
> already tried that in SQL. my apologies.
>
>
> tig4=# \d x
> Table "x"
> Attribute | Type | Modifier
> -----------+-------+----------
> tgargs | bytea |
>
> tig4=# select substr(tgargs,1,5) from x;
> ERROR: Function 'substr(bytea, int4, int4)' does not exist
> Unable to identify a function that satisfies the given argument types
> You may need to add explicit typecasts
>
> tig4=# select substr(tgargs::text,1,5) from x;
> ERROR: Cannot cast type 'bytea' to 'text'
>
> and other things like varchar, etc.
>
> tig4=# select * from x;
> tgargs
> ------------------------------------------------------------------------------
> fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
> fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
> fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
>
> what i'm looking to do here is to get the table names and column names out
> using sql. i can do it in perl with a split command on '\' but was curious
> as to how to "SQL" split up a BYTEA type field.
>
> mikeo
>
>
> At 04:38 PM 8/15/00 -0400, mjp@ornl.gov wrote:
> >Try
> >
> >substr(text,int4) or
> >substr(text, int4, int4)
> >
> >For example,
> >
> >
> >% select substr('hi there',4,3);
> > substr
> >--------
> > the
> >(1 row)
> >
> >Morey Parang
> >ORNL
>
Oops! You have to write a function for it. Here is a
sample quick C function:
typedef struct
{ int len;
char data[1];
} string;
string *byteatostr(bytea *arg)
{
char buf[1024];
int ln,i;
string *res;
ln = VARSIZE(arg) - VARHDRSZ;
memmove(buf, VARDATA(arg), ln);
for(i=0; i < ln; i++)
if( buf[i] < 32 ) buf[i]='?';
res = (string *) palloc(VARHDRSZ + ln);
memset(res, 0, VARHDRSZ + ln);
res->len = VARHDRSZ + ln;
memmove(res->data, buf, (int) ln);
return res;
}
where all non-printable chars are replaced with '?'. Optionally,
the chars can be escaped (prefixed with '\') - adjusting ln as neccessry.
now you get:
# select byteatostr(col) from test2;
byteatostr
------------------------------------------------------------
fk_uste_wu_id?us_states?web_users?UNSPECIFIED?wu_id?wu_id?
(1 rows)
'hope it works for you.
Morey Parang
ORNL
On Tue, Aug 15, 2000 at 05:23:38PM -0400, mikeo wrote:
> thanks anyway but that doesn't work. i should've mentioned that i'd
> already tried that in SQL. my apologies.
>
>
> tig4=# \d x
> Table "x"
> Attribute | Type | Modifier
> -----------+-------+----------
> tgargs | bytea |
>
> tig4=# select substr(tgargs,1,5) from x;
> ERROR: Function 'substr(bytea, int4, int4)' does not exist
> Unable to identify a function that satisfies the given argument types
> You may need to add explicit typecasts
>
> tig4=# select substr(tgargs::text,1,5) from x;
> ERROR: Cannot cast type 'bytea' to 'text'
>
> and other things like varchar, etc.
>
> tig4=# select * from x;
> tgargs
> ------------------------------------------------------------------------------
> fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
> fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
> fk_uste_wu_id\000us_states\000web_users\000UNSPECIFIED\000wu_id\000wu_id\000
>
> what i'm looking to do here is to get the table names and column names out
> using sql. i can do it in perl with a split command on '\' but was curious
> as to how to "SQL" split up a BYTEA type field.
>
> mikeo
>
>
> At 04:38 PM 8/15/00 -0400, mjp@ornl.gov wrote:
> >Try
> >
> >substr(text,int4) or
> >substr(text, int4, int4)
> >
> >For example,
> >
> >
> >% select substr('hi there',4,3);
> > substr
> >--------
> > the
> >(1 row)
> >
> >Morey Parang
> >ORNL
>
thanks, i already have a perl script that splits based on
the backslash. guess i'll just stick with that. thanks for
you time and suggestions.
mikeo
At 06:06 PM 8/15/00 -0400, mjp@ornl.gov wrote:
>Oops! You have to write a function for it. Here is a
>sample quick C function:
>
>typedef struct
>{ int len;
> char data[1];
>} string;
>
>string *byteatostr(bytea *arg)
>{
> char buf[1024];
> int ln,i;
> string *res;
> ln = VARSIZE(arg) - VARHDRSZ;
> memmove(buf, VARDATA(arg), ln);
> for(i=0; i < ln; i++)
> if( buf[i] < 32 ) buf[i]='?';
>
> res = (string *) palloc(VARHDRSZ + ln);
> memset(res, 0, VARHDRSZ + ln);
> res->len = VARHDRSZ + ln;
> memmove(res->data, buf, (int) ln);
> return res;
>}
>
>where all non-printable chars are replaced with '?'. Optionally,
>the chars can be escaped (prefixed with '\') - adjusting ln as neccessry.
>
>
>now you get:
>
># select byteatostr(col) from test2;
>
> byteatostr
>------------------------------------------------------------
> fk_uste_wu_id?us_states?web_users?UNSPECIFIED?wu_id?wu_id?
>(1 rows)