Postgres 9.3 gives ERROR: Array values must start with ... for hex bytea value - postgresql

Given a simple table:
PGresult *res = PQexec(usersconn, "CREATE TABLE userfiles (username
varchar[100] PRIMARY KEY, mydata bytea);");
I try to add a data with this:
PGresult *res = PQexec(usersconn, "INSERT into userfiles VALUES (
'peter' , '\\\\x1A' );" );
or this:
PGresult *res = PQexec(usersconn, "INSERT into userfiles VALUES ( 'peter' , '\x1A' );" );
and I get an error message about array values must start with ...
What am I doing wrong in trying to insert a simple hex constant into this record?

Hex values have to use escape syntax:
INSERT into userfiles VALUES ( 'peter' , e'\\x1A' );
See http://www.postgresql.org/docs/9.3/static/datatype-binary.html

Your problem isn't the bytea field, it's the username field.
varchar[100] is an array of 100 varchar elements, each of which is of unbounded length.
I think you probably meant varchar(100), a single varchar scalar of length 0-100.

Related

Generate value from columns in Postgres

I would like to have a generated column, which value will be the concated string from two other values:
CREATE TABLE public.some_data (
user_name varchar NULL,
domain_name serial NOT NULL,
email GENERATED ALWAYS AS (user_name ||'#'||domain_name) stored
);
But that gives SQL Error [42601]: ERROR: syntax error at or near "ALWAYS"
You need to provide the data type for the column as #Belayer commented.
And then you need to explicitly cast domain_name as text (or some varchar). Otherwise you'll get an error that the expression isn't immutable as #nbk commented. serial is translated to be basically an integer and for whatever reason implicit casts of an integer in concatenations are considered not immutable by the engine. We had that just recently here.
So overall, using the given types for the columns, you want something like:
CREATE TABLE public.some_data
(user_name varchar NULL,
domain_name serial NOT NULL,
email text GENERATED ALWAYS AS (user_name || '#' || domain_name::text) STORED);
But it's a little weird that a domain name is a serial? Shouldn't that be a text or similar? Then you wouldn't need the cast of course.
You need to create an IMMUTABLE function to achieve the generate column, for example:
CREATE OR REPLACE FUNCTION generate_email_concat(varchar,int) returns text as
$$
select $1 ||'#'||$2::text;
$$
LANGUAGE SQL IMMUTABLE ;
CREATE TABLE public.some_data (
user_name varchar NULL,
domain_name serial NOT NULL,
email text GENERATED ALWAYS AS (generate_email_concat(user_name,domain_name)) stored
);
INSERT into some_data(user_name) values ('hello');
You try to concatenate varchar and integer. You have to cast domain_name. This works for me
CREATE TABLE public.some_data (
user_name varchar NULL,
domain_name serial NOT NULL,
email varchar GENERATED ALWAYS AS (CASE WHEN user_name IS NULL THEN 'noname'||'#'||domain_name::text ELSE user_name ||'#'||domain_name::text END) STORED
);

insertion of nested array of custom in table for postgres

command = (
CREATE TYPE belongings AS (
item TEXT,
quantity INTEGER
)
CREATE TYPE student AS (
name TEXT,
id INTEGER,
bag belongings[]
)
CREATE TABLE studentclass(
date DATE NOT NULL,
time TIMESTAMPTZ NOT NULL,
PRIMARY KEY (date, time),
class student
)
)
Can i ask how to do insert for this in postgres psycog2? thank you.
When i put the insert as
insert_sql = "INSERT INTO studentclass (date, time, class) VALUES (%s,%s,%s)"
error output is
DETAIL: Cannot cast type text[] to belongings[] in column
I don't think i just cast it with "::belongings[]" in the INSERT statement as it is a nested.
My earlier asked question for a simpler table.
Unable to insert nested record in postgres

How to change a default separator for postgresql arrays?

I want to import csv with Postgres' arrays into a Postgres table.
This is my table:
create table dbo.countries (
id char(2) primary key,
name text not null,
elements text[]
CONSTRAINT const_dbo_countries_unique1 unique (id),
CONSTRAINT const_dbo_countries_unique2 unique (name)
);
and I want to insert into that a csv which looks like this:
AC,ac,{xx yy}
When I type copy dbo.mytable FROM '/home/file.csv' delimiter ',' csv; then the array is read as a one string: {"xx yy"}.
How to change a deafault separator for arrays from , to ?
You cannot to change array's separator symbol. You can read data to table, and later you can run a update on this table:
UPDATE dbo.countries
SET elements = string_to_array(elements[1], ' ')
WHERE strpos(elements[1], ' ') > 0;

insert string into text [] column

I have the following issue.
I will receive input as a text from a webservice to insert into a certain psql table. assume
create table test ( id serial, myvalues text[])
the recieved input will be:
insert into test(myvalues) values ('this,is,an,array');
I want to create a trigger before insert that will be able to convert this string to a text [] and insert it
first Idea that came in my mind was to create a trigger before insert
create function test_convert() returns trigger as $BODY%
BEGIN
new.myvalues = string_to_array(new.myvalues,',')
RETURNS NEW
END; $BODY$ language plpgsql
but this did not work
You can use the string_to_array function to convert your string into an string array within your insert query:
INSERT INTO test ( myvalues )
VALUES ( string_to_array( 'this,is,an,array', ',' ) );
Suppose you receive text in the following format this is an array and you want to convert it to this,is,an,array then you can use string_to_array('this is an array', ' ') and it will be converted. However if you are receiving comma separated then you can just used it.
Creating the Table Schema Like this,
CREATE TABLE expert (
id VARCHAR(32) NOT NULL,
name VARCHAR(36),
twitter_id VARCHAR(40),
coin_supported text[],
start_date TIMESTAMP,
followers BIGINT,
PRIMARY KEY (id)
);
Inserting values like this will help you to insert array,
insert into expert(id, name, twitter_id, coin_supported, start_date, followers) values('9ed1cdf2-564c-423e-b8e2-137eg', 'dev1', 'dev1#twitter', '{"btc","eth"}', current_timestamp, 12);

postgresql use column name value when quoted with single quotes

I'm trying to update hstore key value with another table reference column. Syntax as simple as
SET misc = misc || ('domain' => temp.domain)
But I get error because everything in parenthesis should be quoted:
SET misc = misc || ('domain=>temp.domain')::hstore
But this actually inserts temp.domain as a string and not its value. How can I pass temp.domain value instead?
You can concatenate text with a subquery, and cast the result to type hstore.
create temp table temp (
temp_id integer primary key,
domain text
);
insert into temp values (1, 'wibble');
select ('domain => ' || (select domain from temp where temp_id = 1) )::hstore as key_value
from temp
key_value
hstore
--
"domain"=>"wibble"
Updates would work in a similar way.