Is posible to get better error message when a domain check fail on postgresql? - postgresql

I create a domain to catch empty strings:
CREATE DOMAIN TEXTN AS TEXT
CONSTRAINT non_empty CHECK (length(VALUE) > 0);
Then I replace all text/varchars fields on the DB with TEXTN.
However, when I get a error, it not give much info:
DbError { severity: "ERROR", parsed_severity: Some(Error),
code: SqlState("23514"),
message: "value for domain textn violates check constraint \"non_empty\"",
detail: None, hint: None, position: None, where_: None,
schema: Some("libs"),
table: None,
column: None, datatype: Some("textn"),
constraint: Some("non_empty")}
It not even tell me in what table and field the check fail.
If is even possible to print the row to insert better, but at least table and field is possible?

PostgreSQL (I checked version 11) simply does not provide this information as part of the protocol. Consider these statements:
=> CREATE DOMAIN TEXTN AS TEXT CONSTRAINT non_empty CHECK (length(VALUE) > 0);
CREATE DOMAIN
=> CREATE TABLE test_table (test_column textn);
CREATE TABLE
=> INSERT INTO test_table VALUES ('');
ERROR: value for domain textn violates check constraint "non_empty"
The error message on the wire looks like this:
S ERROR
V ERROR
C 23514
M value for domain textn violates check constraint "non_empty\
s public
d textn
n non_empty
F execExprInterp.c
L 3494
R ExecEvalConstraintCheck
There is no trace of test_table or test_column.
If you have some control over how your framework creates tables, it may be possible to use named table constraints instead of domain types, like this:
CREATE TABLE test_table (
test_column text
CONSTRAINT test_column_check CHECK (length(test_column) > 0));
If you make sure that the constraint name uniquely identifies the column, you can use that to recover the problematic column.
Even for a CHECK constraint defined on the column, as in CREATE TABLE test_table (test_column text CHECK (length(test_column) > 0));, PostgreSQL does not report the column name. You only get the name of the constraint, which is autogenerated by PostgreSQL on table creation and usually starts with the column name, but this is not guaranteed.

Related

Column name in error text: value too long for type character

We have a table with 2 columns (both have the same type and size) and 2 constraints for them:
create table colors
(
color varchar(6)
constraint color_check check
((color)::text ~ '^[0-9a-fA-F]{6}$'::text),
color_secodandry varchar(6)
constraint color_secondary_check check
((color_secodandry)::text ~ '^[0-9a-fA-F]{6}$'::text),
);
In case of inserts with long values:
insert into colors (color, color_secondary) values ('ccaabb', 'TOO_LONG_TEXT');
insert into colors (color, color_secondary) values ('TOO_LONG_TEXT', 'ccaabb');
we'll get the same errors for two error cases:
ERROR: value too long for type character varying(6) (SQLSTATE 22001)
PostgreSQL validates length for that columns before make inserts, so our checks never run. Is there a way to understand, which column has an invalid data?
The issue you are having is the order of evaluation for the intended values. You told Postgres to not allow a length over 6 (character varying(6)) you also specified additional certain criteria those values have to satisfy. What is happening is Postgres validates the length criteria and throws an exception when the value fails, in that case the check constraint is not preformed as Postgres works on an exit on first failure. The check constraint is processed only after the length passes. Example:
create table test1( id integer generated always as identity
, color6 character varying (6)
constraint color6_check check (color6 ~ '^[0-9a-fA-F]{6}$')
, color60 character varying (60)
constraint color60_check check (color60 ~ '^[0-9a-fA-F]{6}$')
) ;
insert into test1( color6 ) values ('aabbccdd') ;
/* Result
SQL Error [22001]: ERROR: value too long for type character varying(6)
ERROR: value too long for type character varying(6)
*/
insert into test1( color60 ) values ('aabbccdd') ;
/* Result
SQL Error [23514]: ERROR: new row for relation "test1" violates check constraint "color60_check"
Detail: Failing row contains (3, null, aabbccdd).
ERROR: new row for relation "test1" violates check constraint "color60_check"
*/
Notice the only difference between them is the length specification for the column being inserted. Yet they fail, but for a different reasons. Since both the length specification and the check constraint enforce the length you need to decide now how you want to handle the 2 conditions: a separate error for each condition or a single error for both. (IMHO: separate messages)

Mybatis Insert PK manually

I am trying to single insert data into table with assigned PK. Manually assiging PK.
XML file
<insert id = "insertStd" parameterType = "com.org.springboot.dao.StudentEntity" useGeneratedKeys = "false" keyProperty = "insertStd.id", keyColumn = "id">
INSERT INTO STUDENT (ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL )
VALUES (ID=#{insertStd.id}, NAME=#{insertStd.name}, BRANCH=#{insertStd.branch}, PERCENTAGE=#{insertStd.percentage}, PHONE=#{insertStd.phone}, EMAIL =#{insertStd.email});
</insert>
Service call method
public boolean saveStudent(Student student){
LOGGER.info("Student object save");
int savedId= studentMapper.insertStd(student);
}
Log file
org.springframework.jdbc.badsqlgrammarexception
### Error updating database Causes: cause org.postgresql.util.psqlexception error column id does not exist
HINT: There is a column named "id" in the table "student" but it can't be referenced from this part of the query.
Position 200
### Error may exist in file [c:\.....\StudentMapper.xml]
### Error may involve in com.org.springboot.dao.StudentMapper.insertStd-InLine
### The error occurred while setting parameters
### SQL INSERT INTO STUDENT (ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL )
VALUES (ID=?, NAME=?,BRANCH=?, PERCENTAGE=?, PHONE=?, EMAIL=?);
### cause org.postgresql.util.psqlexception ERROR column "id" doesn't exist. //It did worked with JPA id assigned manually.
### There is a column named "ID" in the table "STUDENT", Bbut it cannot be referenced from the part of the query.
The INSERT statement of malformed. The VALUES clause should not include the column names.
Also, since there's no primary auto-generation, you can remove all the other attributes. Just leave the mapper id.
Note: if you want to manually assign the PK value, you need to make sure the table does not have a GENERATED ALWAYS clause for the column. If this is the case, the table will ignore the value you are providing and will use its own rules to generate the PK.
Use:
<insert id="insertStd">
INSERT INTO STUDENT (ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL)
VALUES (
#{insertStd.id}, #{insertStd.name}, #{insertStd.branch},
#{insertStd.percentage}, #{insertStd.phone}, #{insertStd.email}
);
</insert>
Your error is easily reproduceable:
create table t (a int, b varchar(10));
insert into t (a, b) values (123, 'ABC'); -- succeeds
insert into t (a, b) values (a=123, b='ABC'); -- fails!
error: column "a" does not exist
See the Fiddle.

Why postgresql encount duplicate key when key not exists?

When I am inserting data into Postgresql(9.6),throw this error:
ERROR: duplicate key value violates unique constraint "book_intial_name_isbn_isbn10_key"
DETAIL: Key (name, isbn, isbn10)=(三銃士, , ) already exists.
SQL state: 23505
I add uniq constraint on columns name, isbn, isbn10.But when I check the distination table,it does not contains the record:
select * from public.book where name like '%三銃%';
How to fix?This is my insert sql:
insert into public.book
select *
from public.book_backup20190405 legacy
where legacy."name" not in
(
select name
from public.book
)
limit 1000
An educated guess, there may be more than one row in the source table book_backup20190405 which has the unique key tuple ('三銃', '', '').
Since the bulk INSERT INTO ... SELECT ... will be be transactional, you'll be none the wiser to the error, since all data will have been rolled back when the constraint fails.
You can verify this by running a dupe check on the source table:
SELECT name, isbn, isbn10, COUNT(*)
FROM public.book_backup20190405
WHERE name = '三銃'
GROUP BY name, isbn, isbn10
HAVING COUNT(*) > 1;
To see if there are duplicates.
Here's an example of how the source table can be the sole source of duplicates:
http://sqlfiddle.com/#!17/29ba3

ON UPDATE Rule For jsonb

In a PostgreSQL 9.5.1 database I have a table:
CREATE TABLE test.table01 (
pgid serial NOT NULL,
sample_id text NOT NULL,
all_data jsonb NOT NULL,
CONSTRAINT table01_pkey
PRIMARY KEY (pgid)
)
And a view of that table:
CREATE OR REPLACE VIEW test.test_view AS
SELECT table01.sample_id,
table01.all_data ->> 'technician'::text AS technician,
table01.all_data ->> 'depth'::text AS depth,
table01.all_data ->> 'colour'::text AS colour,
table01.all_data ->> 'duplicate of'::text AS dupe_of
FROM test.table01;
Finally, on that view, I have created a RULE that aims to correctly modify the underlying jsonb object on updates against the view:
CREATE OR REPLACE RULE upd_test_view AS
ON UPDATE TO test.test_view WHERE new.colour <> old.colour
DO INSTEAD
UPDATE test.table01 SET all_data = jsonb_set(table01.all_data, '{colour}'::text[], (('"'::text || new.colour) || '"'::text)::jsonb);
When I subsequently issue
UPDATE test.test_view SET colour = 'Purple' WHERE sample_id = '1234567';
I get back
ERROR: no relation entry for relid 2
********** Error **********
ERROR: no relation entry for relid 2
SQL state: XX000
I must be doing something wrong, but I can't quite get my head around it. Your expertise is very much appreciated. Thank you.
I am no expert in this at all, but I ran into the same error message, and in my case I could solve this by removing the WHERE part of the rule. This will make the rule trigger more frequently, but it solved this problem for me. See if it works for you as well if this is still relevant.

Postgres_erro --> ERROR: operator does not exist: double precision[] = numeric[]

I am trying to create a table in postgres for storing raster data.
I have 2 different environments: dev and prod.
if I execute the DDL statement in dev then it is creating the table without any problem.
But in prod I am getting the some strange error. How to solve this issue? I am not an admin person and currently facing difficulties with this.
DDL for the table
CREATE TABLE test_shema.test_table (
rid int4 NOT NULL,
rast raster NULL,
CONSTRAINT elevation_hi_pkey_test PRIMARY KEY (rid),
CONSTRAINT enforce_height_rast_test CHECK ((st_height(rast) = ANY (ARRAY[100, 92]))),
CONSTRAINT enforce_max_extent_rast_test CHECK ((st_envelope(rast) # '0103000020E61000000100000005000000A2221ECF131C64C07F55AF453F8C3240A2221ECF131C64C0FEE6DF13C4963640444672D5B14263C0FEE6DF13C4963640444672D5B14263C07F55AF453F8C3240A2221ECF131C64C07F55AF453F8C3240'::geometry)) NOT VALID,
CONSTRAINT enforce_nodata_values_rast_test CHECK ((_raster_constraint_nodata_values(rast) = '{32767.0000000000}'::numeric[])),
CONSTRAINT enforce_num_bands_rast_test CHECK ((st_numbands(rast) = 1)),
CONSTRAINT enforce_out_db_rast_test CHECK ((_raster_constraint_out_db(rast) = '{f}'::boolean[])),
CONSTRAINT enforce_pixel_types_rast_test CHECK ((_raster_constraint_pixel_types(rast) = '{16BSI}'::text[])),
CONSTRAINT enforce_same_alignment_rast_test CHECK (st_samealignment(rast, '01000000006A98816335DA4E3F6A98816335DA4EBFA2221ECF131C64C0FEE6DF13C496364000000000000000000000000000000000E610000001000100'::raster)),
CONSTRAINT enforce_scalex_rast_test CHECK ((round((st_scalex(rast))::numeric, 10) = round(0.000941539829921079, 10))),
CONSTRAINT enforce_scaley_rast_test CHECK ((round((st_scaley(rast))::numeric, 10) = round((-0.000941539829921079), 10))),
CONSTRAINT enforce_srid_rast_test CHECK ((st_srid(rast) = 4326)),
CONSTRAINT enforce_width_rast_test CHECK ((st_width(rast) = ANY (ARRAY[100, 15])))
);
Error that I am getting in prod environment
ERROR: operator does not exist: double precision[] = numeric[]
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Must be the third constraint. Compare with this instead:
'{32767.0000000000}'::double precision[]