Doctrine 2 and postgresql, database schema is not in sync - postgresql

I'm using postgresql in a Symfony2 proyect with Postgis configured in Mac (not sure if that last one makes any difference).
The problem is that validating my schema AFTER running
doctrine:schema:update --force
will result on this error:
[Mapping] OK - The mapping files are correct.
[Database] FAIL - The database schema is not in sync with the current mapping file.
When updating again, Doctrine will try to add everything again, failing of course.
Thanks for the help.
EDIT:
result for app/console --ansi doctrine:schema:update --dump-sql
ALTER T
ABLE actions ADD id VARCHAR(255) NOT NULL;
ALTER TABLE actions ADD display VARCHAR(255) NOT NULL;
ALTER TABLE actions ADD description VARCHAR(255) DEFAULT NULL;
ALTER TABLE actions ADD PRIMARY KEY (id);
-- lots more tables..
ALTER TABLE subclassifications ADD PRIMARY KEY (id);
ALTER TABLE users ADD id INT NOT NULL;
ALTER TABLE users ADD company_id INT DEFAULT NULL;
ALTER TABLE users ADD profile_id INT DEFAULT NULL;
ALTER TABLE users ADD name VARCHAR(255) NOT NULL;
ALTER TABLE users ADD password VARCHAR(255) NOT NULL;
ALTER TABLE users ADD salt VARCHAR(255) NOT NULL;
ALTER TABLE users ADD email VARCHAR(255) NOT NULL;
ALTER TABLE users ADD state INT NOT NULL;
ALTER TABLE users ADD accessCode INT NOT NULL;
ALTER TABLE users ADD CONSTRAINT FK_1483A5E9979B1AD6 FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE;
ALTER TABLE users ADD CONSTRAINT FK_1483A5E9CCFA12B8 FOREIGN KEY (profile_id) REFERENCES profiles (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE;
CREATE INDEX IDX_1483A5E9979B1AD6 ON users (company_id);
CREATE INDEX IDX_1483A5E9CCFA12B8 ON users (profile_id);
ALTER TABLE users ADD PRIMARY KEY (id);
The point here is that the same dump will work the first time, but when making any change, the dump should be only the incremental changes, not the complete database.

There are a few things that might be wrong here.
First one: which version of Doctrine are you using? Up until 2.3 I had the same thing. Updating to 2.4 fixed it.
Second one: Do you have columnDefinition anywhere in your mapping? If you have it, that's the problem. columnDefinition breaks portability. It also breaks Doctrine Migrations.

Related

How to alter a foreign key in postgresql

I created a table in PostgreSQL with a foreign key constraint.
I dropped the table to which the foreign key belongs. Now how to alter the table or how to defer the foreign key present in the table?
To clarify:
I have a table named test. It has a column called subjectName, which is a foreign key of subject Table. Now I dropped subject table. How to remove the FK constaint on table test
Assuming the following tables:
create table subject
(
name varchar(10) primary key
);
create table test
(
some_column integer,
subject_name varchar(10) not null references subject
);
there are two scenarios what could have happened when you dropped the table subject:
1. you didn't actually drop it:
drop table subject;
ERROR: cannot drop table subject because other objects depend on it
Detail: constraint test_subject_name_fkey on table test depends on table subject
Hint: Use DROP ... CASCADE to drop the dependent objects too.
2. you did drop it, then the foreign key is gone as well.
drop table subject cascade;
NOTICE: drop cascades to constraint test_subject_name_fkey on table test
which tells you that the foreign key constraint was automatically dropped.
Perhaps your question in not exactly what you mean. Are you wanting to remove the which was a foreign key from the table. As amply indicated if you dropped the parent table then the FK is also dropped. However the column itself is not dropped from the child table. To remove that you need to alter the table.
alter table test drop column subject_name;
See demo here

“Error 42P01: relation does not exist” (non public schema in PostgreSQL)

I want to create a foreign key but I got Error 42P01: relation solicitantes does not exist.
I have to schemas: public and laboratorio.
My table is called procedencias. I want to create a foreign key to solicitantes table. Both belongs to laboratorio schema. Even the autocomplete of the target table field works and find the table.
I see that:
I can create the foreing key to any tables of the public schema.
I can't create the foreing key to any tables of the laboratorio schema.
Error when creating a foreign key.
I am using Jetbrains DataGrip software.
This is the DDL of the table called "solicitantes":
CREATE TABLE laboratorio.solicitantes
(
id_solicitante serial NOT NULL,
nombre_solicitante character varying(100) NOT NULL,
CONSTRAINT solicitantes_pkey PRIMARY KEY (id_solicitante)
)
WITH (
OIDS=FALSE
);
ALTER TABLE laboratorio.solicitantes
OWNER TO roby;
CREATE UNIQUE INDEX solicitantes_id_solicitante_uindex
ON laboratorio.solicitantes
USING btree
(id_solicitante);
CREATE UNIQUE INDEX solicitantes_nombre_solicitante_uindex
ON laboratorio.solicitantes
USING btree
(nombre_solicitante COLLATE pg_catalog."default");
I think I have to specify the schema name but I don't know where to do it in DataGrip.
I had the same issue with adding foreign keys to a table in a custom schema from the modify table window. Adding schema to the "Target table" field did not work either. Instead I selected "Open in editor" rather than "Execute in database" and added the schema to the table name in the generated statement and it ran fine.
have you tried to add the explicit schema to the table solicitantes?

Prevent updates to generated primary key column

In PostgreSQL I have created a table and with an id column defined as serial. I have inserted two rows, but I can still update the value of the id column.
But I need prevent updates to the generated value of the id column.
create table aas.apa_testtable
(
id serial primary key,
name text
)
insert into aas.apa_testtable(name) select ('test')
insert into aas.apa_testtable(name) select ('test2')
-- I want this to be impossible / result in an error:
update aas.apa_testtable set id=3 where id=2
You can revoke update on table and grant it on column(s):
REVOKE UPDATE ON TABLE aas.apa_testtable FROM some_role;
GRANT UPDATE (name) ON TABLE aas.apa_testtable TO some_role;
Remember about role public, superusers and other inheritance issues you might have in your setup.
--Do not try this, it will not work without revoking table level privileges:
REVOKE UPDATE (id) ON TABLE aas.apa_testtable FROM some_role;
Alternative is to create trigger that will check if old != new, but with details provided I don't see need for it.

Primary Key for Users per Module? PostgreSQL

I'm making a DB in PostgreSQL and I need a little help.
The user control work with LDAP, and I have a table called modules where I put all the information about the system modules,
Then I created a table called user_module where I put the username and the integer that references a module (in modules table), in this table, you can add/drop rows and I guess I don't need a primary Key for that or isn't it?
I'm using PgAdmin III and it said "I only can View data in this table, I need create a Primary for editing"
Table Code
CREATE TABLE public.adm_mod_usu
(
cusuario text NOT NULL,
cmodulo_det integer NOT NULL,
CONSTRAINT fk_adm_mod_usu_cmodulo_det FOREIGN KEY (cmodulo_det)
REFERENCES public.adm_mod_det (cmodulo_det) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT,
CONSTRAINT fk_adm_mod_usu_unique_cpermiso UNIQUE (cusuario, cpermiso)
USING INDEX TABLESPACE sistema_index
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.adm_mod_usu
OWNER TO postgres;
GRANT ALL ON TABLE public.adm_mod_usu TO public;
GRANT ALL ON TABLE public.adm_mod_usu TO postgres;
By the help from a_horse_with_no_name:
ALTER TABLE public.adm_mod_usu DROP CONSTRAINT fk_adm_mod_usu_unique_cpermiso;
ALTER TABLE public.adm_mod_usu
ADD CONSTRAINT fk_adm_mod_usu PRIMARY KEY (cusuario, cpermiso)
USING INDEX TABLESPACE sistema_index;
I change the unique constraint to primary.

Set column as primary key if the table doesn't have a primary key

I have a column in db which has 5 columns but no primary key.
One of the columns is named myTable_id and is integer.
I want to check if the table has a primary key column. If it doesn't, then make myTable_id a primary key column and make it identity column. Is there a way to do this?
I tried with this:
ALTER TABLE Persons
DROP CONSTRAINT pk_PersonID
ALTER TABLE Persons
ADD PRIMARY KEY (P_Id)
and I get syntax error in Management studio.
This checks if primary key exists, if not it is created
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = 'Persons'
AND TABLE_SCHEMA ='dbo')
BEGIN
ALTER TABLE Persons ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id)
END
ELSE
BEGIN
-- Key exists
END
fiddle: http://sqlfiddle.com/#!6/e165d/2
ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id)
An IDENTITY constraint can't be added to an existing column, so how you add this needs to be your initial thought. There are two options:
Create a new table including a primary key with identity and drop the existing table
Create a new primary key column with identity and drop the existing 'P_ID' column
There is a third way, which is a better approach for very large tables via the ALTER TABLE...SWITCH statement. See Adding an IDENTITY to an existing column for an example of each. In answer to this question, if the table isn't too large, I recommend running the following:
-- Check that the table/column exist and no primary key is already on the table.
IF COL_LENGTH('PERSONS','P_ID') IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = 'PERSONS')
-- Add table schema to the WHERE clause above e.g. AND TABLE_SCHEMA ='dbo'
BEGIN
ALTER TABLE PERSONS
ADD P_ID_new int IDENTITY(1, 1)
GO
ALTER TABLE PERSONS
DROP COLUMN P_ID
GO
EXEC sp_rename 'PERSONS.P_ID_new', 'P_ID', 'Column'
GO
ALTER TABLE PERSONS
ADD CONSTRAINT PK_P_ID PRIMARY KEY CLUSTERED (P_ID)
GO
END
Notes:
By explicitly using the CONSTRAINT keyword the primary key constraint is given a particular name rather than depending on SQL Server to auto-assign a name.
Only include CLUSTERED on the PRIMARY KEY if the balance of searches for a particular P_ID and the amount of writing outweighs the benefits of clustering the table by some other index. See Create SQL IDENTITY as PRIMARY KEY.
You can check if primary key exists or not using OBJECTPROPERTY Transact SQL, use 'TableHasPrimaryKey' for the second arguments.
DECLARE #ISHASPRIMARYKEY INT;
SELECT #ISHASPRIMARYKEY = OBJECTPROPERTY(OBJECT_ID('PERSONS'), 'TABLEHASPRIMARYKEY');
IF #ISHASPRIMARYKEY IS NULL
BEGIN
-- generate identity column
ALTER TABLE PERSONS
DROP COLUMN P_ID;
ALTER TABLE PERSONS
ADD P_ID INT IDENTITY(1,1);
-- add primary key
ALTER TABLE PERSONS
ADD CONSTRAINT PK_PERSONID PRIMARY KEY (P_ID);
END;
I don't think you can do that. For making a column into an identity column I think you have to drop the table entirely.