Indexing over composite types in Postgres - postgresql

Given the following, what can I expect of the resulting index?
CREATE TYPE instant AS (
epoch_seconds timezonetz,
nanos integer
);
CREATE TABLE event AS (
label text,
occurrence instant
);
CREATE INDEX idx_event_occurrence ON event (occurrence);
Will postgres automatically create a composite index over all the fields in instant? Would this index then use the left field as the primary and the right as the secondary? Would there be any reason to do the following instead?
CREATE INDEX idx_event_occurrence ON event (
(occurrence).epoch_seconds,
(occurrence).nanos
);

Related

Kafka/KsqlDb : Why is PRIMARY KEY appending chars?

I intend to create a TABLE called WEB_TICKETS where the PRIMARY KEY is equal to the key->ID value. For some reason, when I run the CREATE TABLE instruction the PRIMARY KEY value is appended with the chars 'JO' - why is this happening?
KsqlDb Statements
These work as expected
CREATE STREAM STREAM_WEB_TICKETS (
ID_TICKET STRUCT<ID STRING> KEY
)
WITH (KAFKA_TOPIC='web.mongodb.tickets', FORMAT='AVRO');
CREATE STREAM WEB_TICKETS_REKEYED
WITH (KAFKA_TOPIC='web_tickets_by_id') AS
SELECT *
FROM STREAM_WEB_TICKETS
PARTITION BY ID_TICKET->ID;
PRINT 'web_tickets_by_id' FROM BEGINNING LIMIT 1;
key: 5d0c2416b326fe00515408b8
The following successfully creates the table but the PRIMARY KEY value isn't what I expect:
CREATE TABLE web_tickets (
id_pk STRING PRIMARY KEY
)
WITH (KAFKA_TOPIC = 'web_tickets_by_id', VALUE_FORMAT = 'AVRO');
select id_pk from web_tickets EMIT CHANGES LIMIT 1;
|ID_PK|
|J05d0c2416b326fe00515408b8
As you can see the ID_PK value has the characters JO appended to it. Why is this?
It appears as though I wasn't properly setting the KEY FORMAT. The following command produces the expected result.
CREATE TABLE web_tickets_test_2 (
id_pk VARCHAR PRIMARY KEY
)
WITH (KAFKA_TOPIC = 'web_tickets_by_id', FORMAT = 'AVRO');

How to use existing index to create conditional constraint

I have following index:
op.create_index(
op.f("ix_order_company_id_email_lower"),
"order",
["company_id", sa.text("lower(email)")],
unique=False,
postgresql_concurrently=True
)
Now I want to create a check constraint that is going to create sort of a 'unique' constraint for only specific type of orders.
op.execute(
"""ALTER TABLE order
ADD CONSTRAINT check_order_company_id_email_lower_type
CHECK (type = 'AH01')
NOT VALID"""
)
How can I add additional check to only apply to records in ix_order_company_id_email_lower?
EDIT: Basically this type of order can only be submitted once per email in a specific company.
You need a partial unique index:
CREATE INDEX ON order (company_id, lower(email))
WHERE type = 'AH01';

key size exceeds implementation restriction for index on expression with UDF call

Firebird allows indexing on expressions since version 2.0. That includes using calls to user defined functions (UDF).
Currently, I am trying to add an expression index to this table:
CREATE TABLE M_ADSN_STRING_DATA (
ID DMN_AUTOINC NOT NULL /* DMN_AUTOINC = INTEGER NOT NULL */,
CLTREF DMN_REFID /* DMN_REFID = INTEGER NOT NULL */,
ATTRIBUTEDATA DMN_AFT_STRING /* DMN_AFT_STRING = VARCHAR(320) NOT NULL */
);
/******************************************************************************/
/**** Unique constraints ****/
/******************************************************************************/
ALTER TABLE M_ADSN_STRING_DATA ADD CONSTRAINT UNQ_M_ADSN_STRING_DATA UNIQUE (CLTREF, ATTRIBUTEDATA);
/******************************************************************************/
/**** Primary keys ****/
/******************************************************************************/
ALTER TABLE M_ADSN_STRING_DATA ADD CONSTRAINT PK_M_ADSN_STRING_DATA PRIMARY KEY (ID);
/******************************************************************************/
/**** Foreign keys ****/
/******************************************************************************/
ALTER TABLE M_ADSN_STRING_DATA ADD CONSTRAINT FK_M_ADSN_STRING_DATA_CLT FOREIGN KEY (CLTREF) REFERENCES M_CLIENT (ID) ON DELETE CASCADE ON UPDATE CASCADE;
/******************************************************************************/
/**** Indices ****/
/******************************************************************************/
CREATE INDEX M_ADSN_STRING_DATA_AD_UC ON M_ADSN_STRING_DATA COMPUTED BY (UPPER(ATTRIBUTEDATA));
Note, that it already has an expression index called M_ADSN_STRING_DATA_AD_UC.
The index I want to use should look like this:
CREATE INDEX M_ADSN_STRING_DATA_AD_DIG
ON M_ADSN_STRING_DATA
COMPUTED BY (F_DIGITS(ATTRIBUTEDATA));
Unfortunately, this gives me an error message.
Unsuccessful metadata update
key size exceeds implementation restriction for index "M_ADSN_STRING_DATA_AD_DIG"
I read Firebird FAQ entrys #213 and #211, and this SO question as well.
F_DIGITS is a UDF of FreeAdhocUDF library. Initially, it was declared as
DECLARE EXTERNAL FUNCTION F_DIGITS
CSTRING(32760)
RETURNS CSTRING(32760) FREE_IT
ENTRY_POINT 'digits' MODULE_NAME 'FreeAdhocUDF';
As my maximum input and output length is only 320 chars, I changed it to
DECLARE EXTERNAL FUNCTION F_DIGITS
CSTRING(320)
RETURNS CSTRING(320) FREE_IT
ENTRY_POINT 'digits' MODULE_NAME 'FreeAdhocUDF';
to fit the index size requirements. My databases pagesize is 16384. So, I'd think, my key can be up to 4096 bytes.
The domain DMN_AFT_STRING of column ATTRIBUTEDATA is declared as
CREATE DOMAIN DMN_AFT_STRING AS
VARCHAR(320) CHARACTER SET ISO8859_1
NOT NULL
COLLATE DE_DE_CS_SF;
Why does the key size exceed?
Long story short: Have you tried to turn it off and on again?
It looks like one has to disconnect and connect after changing the UDF declaration and before adding the expression index.
Now, it works properly. The key size does not exceed anymore.

Is it possible to create a DEFAULT clause with an incrementing identifier?

I would like to know whether it is possible to achieve something like the following in PostgreSQL:
I have a table named Dossier (means "folder" in English), with the the following table structure: name, taille,...
Now, what I'd like to have on my table is a condition such that each time a new instance of Dossier is created, the value in the name column is automatically supplemented with a self-incrementing identifier like so: ref00001, ref00002 etc. (To clarify, after the second insertion, the value for the name column should be ref00002 automatically...)
CREATE SEQUENCE seq_ref;
CREATE TABLE dossier
(
ref TEXT NOT NULL PRIMARY KEY DEFAULT 'ref' || NEXTVAL('seq_ref'),
value TEXT
);
If you want zero-padded numbers, use this:
CREATE SEQUENCE seq_ref;
CREATE TABLE dossier
(
ref TEXT NOT NULL PRIMARY KEY DEFAULT 'ref' || LPAD(NEXTVAL('seq_ref')::TEXT, 10, '0'),
value TEXT
);

an empty row with null-like values in not-null field

I'm using postgresql 9.0 beta 4.
After inserting a lot of data into a partitioned table, i found a weird thing. When I query the table, i can see an empty row with null-like values in 'not-null' fields.
That weird query result is like below.
689th row is empty. The first 3 fields, (stid, d, ticker), are composing primary key. So they should not be null. The query i used is this.
select * from st_daily2 where stid=267408 order by d
I can even do the group by on this data.
select stid, date_trunc('month', d) ym, count(*) from st_daily2
where stid=267408 group by stid, date_trunc('month', d)
The 'group by' results still has the empty row.
The 1st row is empty.
But if i query where 'stid' or 'd' is null, then it returns nothing.
Is this a bug of postgresql 9b4? Or some data corruption?
EDIT :
I added my table definition.
CREATE TABLE st_daily
(
stid integer NOT NULL,
d date NOT NULL,
ticker character varying(15) NOT NULL,
mp integer NOT NULL,
settlep double precision NOT NULL,
prft integer NOT NULL,
atr20 double precision NOT NULL,
upd timestamp with time zone,
ntrds double precision
)
WITH (
OIDS=FALSE
);
CREATE TABLE st_daily2
(
CONSTRAINT st_daily2_pk PRIMARY KEY (stid, d, ticker),
CONSTRAINT st_daily2_strgs_fk FOREIGN KEY (stid)
REFERENCES strgs (stid) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT st_daily2_ck CHECK (stid >= 200000 AND stid < 300000)
)
INHERITS (st_daily)
WITH (
OIDS=FALSE
);
The data in this table is simulation results. Multithreaded multiple simulation engines written in c# insert data into the database using Npgsql.
psql also shows the empty row.
You'd better leave a posting at http://www.postgresql.org/support/submitbug
Some questions:
Could you show use the table
definitions and constraints for the
partions?
How did you load your data?
You get the same result when using
another tool, like psql?
The answer to your problem may very well lie in your first sentence:
I'm using postgresql 9.0 beta 4.
Why would you do that? Upgrade to a stable release. Preferably the latest point-release of the current version.
This is 9.1.4 as of today.
I got to the same point: "what in the heck is that blank value?"
No, it's not a NULL, it's a -infinity.
To filter for such a row use:
WHERE
case when mytestcolumn = '-infinity'::timestamp or
mytestcolumn = 'infinity'::timestamp
then NULL else mytestcolumn end IS NULL
instead of:
WHERE mytestcolumn IS NULL