postgres create an index - postgresql

I am going from mysql to postgres and I am having a problem creating an index.
CREATE INDEX pointsloc ON table USING gist (point_col);
This is the response I get back:
ERROR: data type point has no default operator class for access method "gist"
HINT: You must specify an operator class for the index or define a default operator class for the data type.
I have seen I need to specify the operator class for the index, different classes can be used depending upon the type of operators you wish to use on the column. I wish to use the #> or ~ to find if a point is within a polygon.
How do i specify the operator class?? help please has to be a simple thing but I am stumped!
EDIT
Below is a print screen of me trying to add an index to the branch table:
Table "public.branch"
Column | Type | Modifiers
------------------+------------------+-----------------------------------------------------
id | integer | not null default nextval('branch_id_seq'::regclass)
name | character(120) |
center_point_lat | double precision |
center_point_lng | double precision |
center_point | point |
Indexes:
"branch_pkey" PRIMARY KEY, btree (id)
paul=# create index pt_idx on branch using gist (center_point);
ERROR: data type point has no default operator class for access method "gist"
HINT: You must specify an operator class for the index or define a default operator class for the data type.

Seems to be working fine when I try:
test=# create table test (pt point);
CREATE TABLE
test=# create index pt_idx on test using gist (pt);
CREATE INDEX
Are you sure your point_col actually is of type point? Because, if it's a varchar, than it will indeed miserably fail without the btree_gist contrib - and even then it won't be very useful.

Related

Size of a GIN index in postgreSQL

I have created a model in Django.
class MyModel(models.Model):
features = TextField(blank=True, default='')
There are several possible ways to store the data in the feature field. Some examples below.
feature1;feature2
feature1, feature2
feature1,feature2
And so on. I created a GIN index for that field using migrations.RunSQL() (thanks to the following answer). The postgreSQL command looks as follows
CREATE INDEX features_search_idx ON "mymodel" USING gin (regexp_split_to_array("mymodel"."features", '[,;\\s]+'));
Now I need to check the size of the created index in my database. I tried to do it with the following commands
SELECT pg_size_pretty (pg_indexes_size("mymodel"."features_search_idx"));
SELECT pg_size_pretty(pg_indexes_size("features_search_idx")) FROM "mymodel";
The latter one failed with ERROR: column "features_search_idx" does not exist and the former one failed with ERROR: missing FROM-clause entry for table "mymodel".
How can I check the index size?
pg_indexes_size takes an argument of type regclass, that is an object ID that is represented as a string that is the object name. So if you don't supply an object ID, you have to supply a string (single quotes) that is the name of the table:
SELECT pg_size_pretty (pg_indexes_size('mymodel.features_search_idx'));

In Postgresql, is there a way to restrict a column's values to be an enum?

In postgresql, I can create a table documenting which type of vehicle people have.
CREATE TABLE IF NOT EXISTS person_vehicle_type
( id SERIAL NOT NULL PRIMARY KEY
, name TEXT NOT NULL
, vehicle_type TEXT
);
This table might have values such as
id | name | vehicle_type
----+---------+---------
1 | Joe | sedan
2 | Sue | truck
3 | Larry | motorcycle
4 | Mary | sedan
5 | John | truck
6 | Crystal | motorcycle
7 | Matt | sedan
The values in the car_type column are restricted to the set {sedan, truck, motorcycle}.
Is there a way to formalize this restriction in postgresql?
Personally I would use foreign key and lookup table.
Anyway you could use enums. I recommend to read article PostgreSQL Domain Integrity In Depth:
A few RDBMSes (PostgreSQL and MySQL) have a special enum type that
ensures a variable or column must be one of a certain list of values.
This is also enforcible with custom domains.
However the problem is technically best thought of as referential
integrity rather than domain integrity, and usually best enforced with
foreign keys and a reference table. Putting values in a regular
reference table rather than storing them in the schema treats those
values as first-class data. Modifying the set of possible values can
then be performed with DML (data manipulation language) rather than
DDL (data definition language)....
However when the possible enumerated values are very unlikely to
change, then using the enum type provides a few minor advantages.
Enums values have human-readable names but internally they are simple integers. They don’t take much storage space. To compete with
this efficiency using a reference table would require using an
artificial integer key, rather than a natural primary key of the value
description. Even then the enum does not require any foreign key
validation or join query overhead.
Enums and domains are enforced everywhere, even in stored procedure arguments, whereas lookup table values are not. Reference
table enumerations are enforced with foreign keys, which apply only to
rows in a table.
The enum type defines an automatic (but customizable) order relation:
CREATE TYPE log_level AS ENUM ('notice', 'warning', 'error', 'severe');
CREATE TABLE log(i SERIAL, level log_level);
INSERT INTO log(level)
VALUES ('notice'::log_level), ('error'::log_level), ('severe'::log_level);
SELECT * FROM log WHERE level >= 'warning';
DBFiddle Demo
Drawback:
Unlike a restriction of values enforced by foreign key, there is no way to delete a value from an existing enum type. The only workarounds are messing with system tables or renaming the enum, recreating it with the desired values, then altering tables to use the replacement enum. Not pretty.

Using postgresql gin or gist index with bigint column

i am trying to create gin index on bigint column and getting an error (PostgreSQL 9.1.9 / Debian 7).
CREATE TABLE test (id bigint CONSTRAINT test_pkey PRIMARY KEY, field bigint);
CREATE INDEX idx_test_field ON test using GIN(field);
ERROR: data type bigint has no default operator class for access method "gin"
HINT: You must specify an operator class for the index or define a default operator class for the data type.
Is there no default support for int8 gin,gist indexes ?
There's generally no reason to create a GiST or GIN index on a primitive type.
If you do require this - say, if you want a composite index that includes both some primitive types and some more complex GiST / GIN-only index types - then you will want the btree_gist or btree_gin modules, as appropriate.
CREATE EXTENSION btree_gin;

Equivalent to exclusion constraint composed of integer and range

I need to have something equivalent to this exclusion constraint
drop table if exists t;
create table t (
i int,
tsr tstzrange,
exclude using gist (i with =, tsr with &&)
);
ERROR: data type integer has no default operator class for access method "gist"
HINT: You must specify an operator class for the index or define a default operator class for the data type.
I guess the problem is obvious from the error message. How to do it?
You need to install the additional module btree_gist to make it work. The module installs the missing operator class.
Details in this related answer:
Exclusion constraint on a bitstring column with bitwise AND operator
More at this answer on dba.SE:
PostgreSQL EXCLUDE USING error: Data type integer has no default operator class

Keeping a table column empty when it is indexed as unique

Is it possible to keep a table column empty if it's defined as unique?
Table schema
Column | Type | Modifiers | Description
-------------------+------------------------+---------------+-------------
id | integer | not null |
name | character varying(64) | |
Indexes
Indexes:
"clients_pkey" PRIMARY KEY, btree (id)
"clients_name_idx" UNIQUE, btree (name)
Has OIDs: yes
Due to modifications to the application sometimes the name column needs to be empty, is this possible at all?
If the column can contain NULL values, then that is OK, as NULL is not included in the index.
Note that some databases don't implement the standard properly (some versions of SQL Server only allowed one NULL value per unique constraint, but I'm sure if that is still the case).
Using NULL is the better option, but you could also use a conditional unique index:
CREATE UNIQUE INDEX unique_clients_name ON clients (name) WHERE name <> '';
And avoid oid's, these are useless and obsolete.