GeoDjango: editing the standard PostGIS template to include OSGB36 - postgresql

I've just installed GeoDjango (yay) and now I'm trying to follow these instructions to set up an existing GeoDjango project, which needs OSGB36:
After you've installed and got a PostGIS template, log
in to it and update the proj4text column of SRID 27700 to include
+datum=OSGB36, and update SRID 29902 to have +datum=ire65.
However. If I connect to the postgis_template created as part of the GeoDjango install, it doesn't appear to have any rows or columns at all:
domesday=# \c template_postgis
psql (8.4.4)
You are now connected to database "template_postgis".
template_postgis=# \d
No relations found.
How do I make the edits necessary to update SRID 27700 and SRID 29902 as described here? Have I created template_postgis wrong? I didn't see any errors during install.

What you should see is:
template_postgis=# \d
List of relations
Schema | Name | Type | Owner
--------+------------------+-------+----------
public | geometry_columns | table | postgres
public | spatial_ref_sys | table | postgres
(2 rows)
Since you're not, you probably had a problem running:
$ psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql
On my (Ubuntu+PG8.3) system, that file is actually called lwpostgis.sql. I had similar issues when installing the first time.

Related

PostGIS type "geometry" doesn't exist when pg_dump copying database to server

Similar question to many that have already been asked, but I have yet to find a solution.
I'm copying a Postgres db from my local machine to a server using:
pg_dump -C -h localhost -U localuser dbname | psql -h remotehost -U remoteuser dbname
However, whenever I try to execute this, any tables with PostGIS geography columns are skipped and not copied over, and I'm left with the following error:
ERROR: type "<mydb>.geography" does not exist
Attempted solutions:
On this server, I have successfully installed PostGIS and created the relevant extensions:
mydb=# select postgis_version();
postgis_version
---------------------------------------
2.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
(1 row)
Additionally, geometry is a recognized data type:
mydb=# \dT *.geometry
List of data types
Schema | Name | Description
--------+----------+-----------------------------------------
public | geometry | postgis type: Planar spatial data type.
(1 row)
My search_path includes everything relevant:
mydb=# show search_path;
search_path
------------------------
mydb, public, postgis
and
mydb=# SELECT r.rolname, d.datname, rs.setconfig
FROM pg_db_role_setting rs
LEFT JOIN pg_roles r ON r.oid = rs.setrole
LEFT JOIN pg_database d ON d.oid = rs.setdatabase
WHERE r.rolname = 'mydb' OR d.datname = 'mydb';
rolname | datname | setconfig
---------+---------+----------------------
| mydb | {search_path=public}
(1 row)
My only guess as to what might be causing this headache is that the superuser on my local machine isn't the same name as the remote superuser. I.e., localuser and remoteuser don't match.
The rest of the answer assumes that the error you quote is the first error while restoring the dump. If not, it might be the consequence of an earlier error (e.g., failure to CREATE EXTENSION postgis).
If PostGIS is installed on both servers, the message suggests that it is installed in different schemas on both databases.
Examine the result of
\dx postgis
on both databases to check.
Since PostGIS is not a relocatable extension, you have to drop and re-create it to move it to a different schema.

could not access file "$libdir/plpgsql" while creating template_postgis

I have installed PostgreSQL and Postgis on my Mac before when it's 9.3 and 2.1 but never used.
After upgrading pg to 4.5_2 and postgis to 2.2 (the latest now), I try to build my first postgis based app and creating template_postgis like this:
createdb template_postgis
psql -d template_postgis -f /usr/local/share/postgis/postgis.sql
And got this error:
SET
BEGIN
psql:/usr/local/share/postgis/postgis.sql:77: ERROR: could not access file "$libdir/plpgsql": No such file or directory
...
So I run pg_config --libdir it says /usr/local/lib, and pg_config --pkglibdir returns /usr/local/lib/postgresql.
And I found plpgsql.so under pkglibdir not libdir,
so I create a symbol link named plpgsql.so and another plpgsql under libdir, but it still not works.
What really is the problem there? How can I fix this?
My Mac is running the newest OS X 10.11 and both of them are installed and upgraded by homebrew.
Update:
Inspired by #Stefan D. , I run psql -c "\dx" to list all the installed extensions which results:
Name | Version | Schema | Description
---------+---------+------------+---------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
postgis | 2.1.7 | public | PostGIS geometry, geography, and raster spatial types and functions
So I run ALTER EXTENSION postgis UPDATE TO "2.2.0"; to manually update the version of postgis, but got another error: could not open extension control file "/usr/local/Cellar/postgresql/9.4.5/share/postgresql/extension/postgis.control": No such file or directory.
This is wired as my PostgreSQL is installed in /usr/local/Cellar/postgresql/9.4.5_2/. And postgis.control is not listed in /usr/local/Cellar/postgresql/9.4.5_2/share/postgresql/extension/ either.
After locating, I find all the .control files have an symbol link in /usr/local/share/postgresql/extension/.
What a coinincidence: I just had a similar problem and were searching for a solution when I found your question.
I also updated my postgresql/postgis installation a couple of days ago, and when I wanted to use my database (which I created with before the update) it today I got an error similiar to yours (for me it was that the postgis 2.1 library could not be found)
Meanwhile I could fix it. Here is how I did it:
My problem was: The database was set up with the old Postgresql/postgis version. And it still looks for the old libraries. You can check this by listing all your extensions with the following command:
psql --username=gisuser --dbname=gis -c "\dx"
For me this gave me this output:
List of installed extensions
Name | Version | Schema | Description
------------------+---------+------------+---------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
postgis | 2.1.7 | public | PostGIS geometry, geography, and raster spatial types and functions
postgis_topology | 2.1.7 | topology | PostGIS topology spatial types and functions
(3 rows)
As you can see the postgis and postgis_topology extension versions (2.1.7) do not fit my installed versions (2.2.0)
To fix that I executed the following commands to update the extension versions:
psql --username=gisuser --dbname=gis -c "ALTER EXTENSION postgis UPDATE;"
psql --username=gisuser --dbname=gis -c "ALTER EXTENSION postgis_topology UPDATE;"
You will probably have to alter the command a bit (username, database, and the extension you want to update)
Check whether it worked again with:
psql --username=gisuser --dbname=gis -c "\dx"
Now the output is:
List of installed extensions
Name | Version | Schema | Description
------------------+---------+------------+---------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
postgis | 2.2.0 | public | PostGIS geometry, geography, and raster spatial types and functions
postgis_topology | 2.2.0 | topology | PostGIS topology spatial types and functions
(3 rows)
(Note the changed version number for postgis and postgis_topology)
Finally, I got out what caused this issue: Although there's only one postgres installed on my Mac, but there are TWO postgres exits!
What really happened is I have upgraded postgres program without shutting down, neither brew did, so I have a postgres 9.4.5_2 installed locally, and an old one in the memory!
So the solutions is really simple: Shutting down the old one and start the new installed postgres!
Anyway, thanks for your kind help!
Probably You have installed multipe instances of Postgres on Your Mac.
When you execute pg_config --pkglibdir, make sure it's the one associated with your installation. Run:
which pg_config

automation script for postgresql

Could you please help how can I run automation script for postgresql after installing postgresql on Ubuntu? I need to automatize DB preparation before using it (create table, insert data, alter permissions).
I need to do it with the current rights of the user.
E.g., I have the only user admin_ubuntu. He has all rights to run psql.
All scripts are written but how can I run the script? usually, I need to edit configs ( I believe, /etc/postgresql/9.1/main/pg_hba.conf). But I do not want to do it.
So, what I need is just to run sql which will make a lot of things. How can I do it to run it? The problem is that I need to do a lot of things to allow to run sql when the OS is immaculate (empty).
It will be made every time when the Ubuntu will have been installed.
you should be able to run shell provisioning - following is example of what you can do:
# creating user
sudo -u postgres psql -c "CREATE USER admin WITH PASSWORD 'password';"
# creating new db if needed .. might need 2 (dev/test)
createdb -U vagrant mydevdb
# if you have more complex things you'll need to put that in a create_db.sql file and run the script as
sudo -u postgres psql < create_db.sql
The create_db.sql file can contain any CREATE TABLE statement
Sharing some scripts here that show how to create databases, roles, schemas and tables. Not meant to be taken as best practice or acceptable for production, but hopefully it will help with getting started with PostgreSQL. Any code fragment surrounded by _ e.g. _variable_, indicate a string that should be replaced accordingly. Standard shell commands begin with $.
PostgreSQL Installation
My environment is an Ubuntu server/container where PostgreSQL was installed and started with:
$ apt install postgresql-12
$ pg_ctlcluster 12 main start
This automatically adds a postgres Linux user, which has superuser privileges in PostgreSQL, allowing the installation to be tested with:
$ sudo su postgres
$ psql
Which should result in a prompt like postgres=#. If that's the case, you should be able to follow the steps below with the default /etc/postgresql/12/main/pg_hba.conf settings.
Database and Role Creation
After saving this to a setup.sql file, it can be run with $ sudo -u postgres psql < setup.sql:
CREATE ROLE testadmin WITH LOGIN CREATEDB PASSWORD 'secret5';
CREATE DATABASE testdb OWNER testadmin;
CREATE ROLE _current-linux-user_ WITH LOGIN CREATEDB INHERIT;
GRANT pg_read_server_files TO testadmin;
GRANT pg_read_server_files TO _current-linux-user_;
GRANT testadmin to _current-linux-user_;
While playing around, it was useful to start everything from scratch, running $ sudo -u postgres psql < teardown.sql:
DROP DATABASE testdb;
DROP ROLE testadmin;
DROP ROLE _current-linux-user_;
Loading the Database From CSV Files
There's a reason we created a role with the same login name as the current user. It allows us to connect to the database by simply doing $ psql testdb which shows a prompt like testdb=>.
First we'll need the CSV files to populate the testdb database, I used the two below for an example food database. Be careful to not leave blank lines at the end of the files, otherwise there will be an ERROR: missing data for column.
categories.csv:
Category ID,Category Name
1,Fruit
2,Nut
3,Vegetable
4,Grain
5,Fungus
6,Alga
7,Seed
items.csv:
Food Name,Category,Nutrition
Peach,1,"Vitamin A, C, Potassium, Magnesium, Iron"
Brazil nut,7,"Iron, Calcium, Protein"
Broccoli,3,"Vitamin C, Magnesium"
Bean,4,"Magnesium, Iron, Calcium, Protein"
Mushroom,5,"Iron, Magnesium, Sodium, Protein"
Now we can run $ psql testdb < schema.sql:
CREATE SCHEMA food
CREATE TABLE food.categories (category_id integer PRIMARY KEY, category text)
CREATE TABLE food.items (id serial, name text, category_id integer REFERENCES food.categories (category_id), nutrition text);
/* Load data from CSV files into tables */
COPY food.categories(category_id, category)
FROM '/path/to/categories.csv' WITH (FORMAT csv, HEADER ON);
COPY food.items(name, category_id, nutrition)
FROM '/path/to/items.csv' WITH (FORMAT csv, HEADER ON);
/* Test */
SELECT * FROM food.categories;
SELECT * FROM food.items;
SELECT name,category FROM food.items INNER JOIN food.categories
ON food.items.category_id = food.categories.category_id;
Which results in the following output:
CREATE SCHEMA
COPY 7
COPY 5
category_id | category
-------------+-----------
1 | Fruit
2 | Nut
3 | Vegetable
4 | Grain
5 | Fungus
6 | Alga
7 | Seed
(7 rows)
id | name | category_id | nutrition
----+------------+-------------+------------------------------------------
1 | Peach | 1 | Vitamin A, C, Potassium, Magnesium, Iron
2 | Brazil nut | 7 | Iron, Calcium, Protein
3 | Broccoli | 3 | Vitamin C, Magnesium
4 | Bean | 4 | Magnesium, Iron, Calcium, Protein
5 | Mushroom | 5 | Iron, Magnesium, Sodium, Protein
(5 rows)
name | category
------------+-----------
Peach | Fruit
Brazil nut | Seed
Broccoli | Vegetable
Bean | Grain
Mushroom | Fungus
(5 rows)
Specifying the CSV format allows us to enclose the default delimiter, which is , in quotes inside a data column. The default loading is text which could lead to an ERROR: extra data after last expected column. Another source of this error is forgetting to include all the fields in the COPY command, e.g. nutrition.
Login With New User
What about the testadmin user we just created? We can connect to the database with a password as follows:
$ psql -U testadmin -d testdb -h localhost
Password for user testadmin:
psql (12.8 (Ubuntu 12.8-0ubuntu0.20.04.1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
testdb=>
If you forget to use -h localhost you'll likely get a psql: error: FATAL: Peer authentication failed for user "testadmin".
There is excellent documentation for the above commands on the official site.

PostGIS only works with root user

I have a database and am trying to use PostGis with it.
When I run:
$ psql -h localhost -d $APP_DB_NAME -U $APP_DB_USER
# SELECT PostGIS_version();
I get the following error:
ERROR: function postgis_version() does not exist
LINE 1: SELECT PostGIS_version();
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
But when I enter the database as root:
$ sudo su postgres -c psql $APP_DB_NAME
# SELECT PostGIS_version();
It runs fine:
postgis_version
---------------------------------------
2.1 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
(1 row)
I am installing the PostGis extension as the root user, since my user doesn't have super_user access.
$ su - postgres -c psql $APP_DB_NAME
# CREATE EXTENSION postgis;
My guess is that the owner of the schema in which postgis is installed is not the user you're logging in as, but rather the "root" user (which is postgres).
$ psql postgres
postgres=# \dn
List of schemas
Name | Owner
--------------------+----------
public | postgres
pg_catalog | postgres
my_data | someuser
When connecting as postgres, postgis will work in this case, but if you connect as any other user, it will fail, and say it's not there, even though if you try to create extension postgis it will say it's installed already.
To correct this, make sure all the schemas are owned by the user you're actually connecting as:
ALTER SCHEMA public OWNER TO my_user;

Where are PostgreSQL database files in the cluster directory?

On OSX, I recently installed PostgreSQL via Homebrew:
brew install postgresql
I then created a new database cluster:
initdb /usr/local/var/postgres
I confirm that postgresql server is running with the expected database cluster:
$ ps auxwww | grep postgres
0:00.03 /usr/local/opt/postgresql/bin/postgres -D /usr/local/var/postgres
I create a new database:
createdb mynewdb
I see that it exists.
$ psql
<user>=# \l
mynewdb | <user> | UTF8 | en_US.UTF-8 | en_US.UTF-8
But, I see no obvious changes to the cluster directory (e.g., just by checking contents ls -lt).
Where is the database written / stored in the cluster directory (or sub-directories)?
as #ahorsewithnoname says they are in the base directory, (on some other platfotms data/base)
the numeric name is the OID of the database and in the directory will be files named for the OID of the table or index they relate to.
databse oids can be determined with this query. oid is like a hidden unique id column.
select oid,* from pg_catalog.pg_database;
table and index oids can be found like this,
select * from pg_catalog.pg_class;
column relifilenode for the base of the filename (thanks #jjames)