CakePHP ACL with UUID primary keys - postgresql

I am developing a CakePHP app, and I would like to use UUID as a primary keys, since the application will be distributed accross multiple databases and I would also like to take advantage of the integrated ACL framework in CakePHP 2.1
I am going according to the tutorial and I have modified DB scheme to following
CREATE TABLE acos (
id uuid NOT NULL,
parent_id uuid DEFAULT NULL,
model VARCHAR(255) DEFAULT '',
foreign_key uuid DEFAULT NULL,
alias VARCHAR(255) DEFAULT '',
lft uuid DEFAULT NULL,
rght uuid DEFAULT NULL,
PRIMARY KEY (id)
);
CREATE TABLE aros_acos (
id uuid NOT NULL,
aro_id uuid NOT NULL,
aco_id uuid NOT NULL,
_create CHAR(2) NOT NULL DEFAULT 0,
_read CHAR(2) NOT NULL DEFAULT 0,
_update CHAR(2) NOT NULL DEFAULT 0,
_delete CHAR(2) NOT NULL DEFAULT 0,
PRIMARY KEY(id)
);
CREATE TABLE aros (
id uuid NOT NULL,
parent_id uuid DEFAULT NULL,
model VARCHAR(255) DEFAULT '',
foreign_key uuid DEFAULT NULL,
alias VARCHAR(255) DEFAULT '',
lft uuid DEFAULT NULL,
rght uuid DEFAULT NULL,
PRIMARY KEY (id)
);
However now I am getting an error:
Error: SQLSTATE[42883]: Undefined function: 7 ERROR: function max(uuid) does not exist LINE 1: SELECT MAX("Aro"."rght") AS "rght" FROM "public"."aros" AS "... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts.
The version of CakePHP is 2.1.0-beta and I'm using PostgreSQL with UUID data type.
Have anyone succesfully used CakePHP ACL framework with UUID's? I would like to get this working with minimal modification in CakePHP framework, for future supportability of this app.

There is no aggregate function max() defined for the data type UUID. No UUID is considered "bigger" than another UUID.
Consider the following demo:
CREATE TEMP TABLE t(id uuid);
INSERT INTO t VALUES
('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11')
,('b0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11');
SELECT max(id) FROM t;
Yields:
ERROR: function max(uuid) does not exist
LINE 1: SELECT max(id) FROM t;
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
You can circumvent the problem. Cast the id to text if you want the alphabetically biggest value:
SELECT max(id::text) FROM t;
Yields:
b0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
But be aware that that is just the standard text representation of a UUID. The same UUID could be represented in many other forms.

Related

Postgres violates not null constraint, even when there isn't one

Hey I have a Postgres database that has a Schema with
CREATE TABLE Mentor (
mentor_ID serial unique,
person_ID serial not null unique,
career_history varchar(255) not null,
preferred_communication varchar(50) not null,
mentoring_preference varchar(50) not null,
linked_in varchar(100) not null,
capacity int not null,
feedback_rating int,
feeback_comment varchar(255),
PRIMARY KEY (mentor_ID),
CONSTRAINT fk_person FOREIGN KEY (person_ID) REFERENCES Person(person_ID)
);
CREATE TABLE Mentee(
mentee_ID integer not null unique,
mentor_ID serial references Mentor(mentor_ID),
person_ID serial not null unique,
study_year int,
motivation varchar(50),
interests varchar(255),
random_match boolean default false,
PRIMARY KEY (mentee_ID),
CONSTRAINT fk_person FOREIGN KEY (person_ID) REFERENCES Person(person_ID)
);
With this, i expect to be able to enter null values for mentor_ID in my database but when I enter the query
insert into mentee(mentee_ID, mentor_ID, person_ID) VALUES (12313, null, 1)
I get the violation
ERROR: null value in column "mentor_id" of relation "mentee" violates not-null constraint
I was wondering how I could make it so I can insert null values for mentor_ID? I dont have it as not null in the table but it still says violating not null constraint.
Thank you
Because serial is not null.
serial is...
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
Note the integer not null. This is because serial is to be used for primary keys, not foreign keys. Foreign keys are always assigned, they don't need to auto increment.
Use a plain integer.
mentor_ID integer references Mentor(mentor_ID)
Same for your other foreign keys.
Notes:
identity is the SQL standard way to do auto incremented primary keys.
You don't need to declare primary keys as unique, primary keys are already unique.
Unless there's a specific reason to constrain the size of a text field, use text. varchar and text only use the necessary amount of space for each row. "foo" will take the same amount of space in varchar(10) as in varchar(255). For example, there's no particular reason to limit the size of their linked in nor motivation.

with migration to fill slug with default value

In my Laravel 5.6/PostgreSQL 10.5 application
I have 2 tables :
CREATE TABLE public.rt_genres (
id serial NOT NULL,
published bool NULL DEFAULT false,
created_at timestamp NOT NULL DEFAULT now(),
updated_at timestamp NULL,
CONSTRAINT rt_genres_pkey PRIMARY KEY (id)
)...
CREATE TABLE public.rt_genre_translations (
id serial NOT NULL,
genre_id int4 NOT NULL,
"name" varchar(100) NOT NULL,
description text NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
locale varchar(2) NOT NULL,
CONSTRAINT genre_translations_genre_id_locale_unique UNIQUE (genre_id, locale),
CONSTRAINT rt_genre_translations_pkey PRIMARY KEY (id),
CONSTRAINT genre_translations_genre_id_foreign FOREIGN KEY (genre_id) REFERENCES rt_genres(id) ON DELETE CASCADE
)
I need to add slug field in first rt_genres table
with migration rule:
$table->string('slug', 105)->unique();
and got error :
: Unique violation: 7 ERROR: could not create unique index "genres_slug_unique"
DETAIL: Key (slug)=(id) is duplicated.")
1)If there is a way to assign in migration some unique default value, like = id
->default('rt_genres.id')
?
2) That would be cool to assign to slug value from public.rt_genre_translations.name as I use
"cviebrock/eloquent-sluggable": "^4.5" plugin in my app ? Can I do it ?
Thank you!
You can only get the default value from a different column with a trigger (SO answer).
You can make the column nullable:
$table->string('slug', 105)->nullable()->unique();
Or you create the column, insert unique values and then create the index:
Schema::table('rt_genres', function($table) {
$table->string('slug', 105);
});
DB::table('rt_genres')->update(['slug' => DB::raw('"id"')]);
Schema::table('rt_genres', function($table) {
$table->unique('slug');
});

Error while creating table in PostgreSQL while migrating from MySQL

I am Migrating my database from MySQL to PostgreSQL.While creating table I got an error which I can't resolve.My MySQL Query is like this.
MYSQL Query
CREATE TABLE `configuration` (
`Name` varchar(300) NOT NULL,
`Value` varchar(300) default NULL,
`CType` char(1) default NULL,
`Size` int(11) default NULL,
`CGroup` varchar(50) default NULL,
`RestartReq` char(1) NOT NULL default 'Y',
`Display` char(1) NOT NULL default 'Y',
PRIMARY KEY (`Name`),
KEY `CType` (`CType`),
CONSTRAINT `configuration_ibfk_1` FOREIGN KEY (`CType`) REFERENCES `conftype` (`CType`)
)ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin`
PostgreSQL Query
CREATE TABLE configuration (
Name varchar(300) PRIMARY KEY,
Value varchar(300) default NULL,
CType char(1) default NULL,
Size integer default NULL,
CGroup varchar(50) default NULL,
RestartReq char(1) NOT NULL default 'Y',
Display char(1) NOT NULL default 'Y',
KEY CType (CType),
CONSTRAINT `configuration_ibfk_1` FOREIGN KEY (CType) REFERENCES conftype (CType)
)
Running File with
psql -h localhost -p 5432 -U postgres -f ps.sql testdb
Error getting
psql:ps.sql:40: ERROR: syntax error at or near "(" at character 287
psql:ps.sql:40: LINE 9: KEY CType ('CType'),
From the MySQL documentation:
KEY is normally a synonym for INDEX.
In PostgreSQL you have to create the index separately from the table:
CREATE TABLE configuration (
name varchar(300) PRIMARY KEY,
value varchar(300),
ctype char(1),
size integer,
cgroup varchar(50),
restartreq boolean NOT NULL DEFAULT true,
display boolean NOT NULL DEFAULT true,
CONSTRAINT configuration_ibfk_1 FOREIGN KEY (ctype) REFERENCES conftype (ctype)
);
CREATE INDEX conf_key ON configuration(ctype);
A few other points:
PostgreSQL identifiers (mainly table and column names) are case-insensitive except when double-quoted. The standard approach is to put identifiers in lower case and keywords in upper case.
Using a varchar(300) as a PRIMARY KEY is usually not a good idea for performance reasons. Consider adding a serial type.
The default value of a column is NULL when nothing is specified, so no need to specify DEFAULT NULL.
PostgreSQL has a boolean data type.

How can I write queries for the Bluemix SQL database

How can I create a table that includes auto increment and NOT NULL. I am using the sql database console that bluemix offers.
The following query gives me an error.
CREATE TABLE discounts (
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
expired_date DATE NOT NULL,
amount DECIMAL(10,2) NULL,
PRIMARY KEY (id)
);
The error is:
DDL failed with message
_ Exception. _ state = 42601; error code = -104; error Message = Error for batch element #1: An unexpected token "," was found following
"NULL AUTO_INCREMENT". Expected tokens may include: "".. _CODE=-104,
_STATE=42601, DRIVER=3.66.46
DB2 does not support the "AUTO_INCREMENT" statement.
You can use the "GENERATED ALWAYS AS IDENTITY" command instead.
CREATE TABLE discounts ( id INT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), title VARCHAR(255) NOT NULL, expired_date DATE NOT NULL, amount DECIMAL(10,2) NULL, PRIMARY KEY (id) );
Further details about creating automatic values are detailed here

How to insert value into a column with a default value? [PostgreSQL 9.1]

I have such table:
CREATE TABLE employee (
id INTEGER DEFAULT NEXTVAL('ids'::regclass) NOT NULL,
name CHARACTER VARYING NOT NULL,
employer INTEGER DEFAULT (-1)
);
And I want to insert sth into this table (I want to leave employer as default, -1):
INSERT INTO employee (name, id) VALUES('Doe', 2);
but my PostgreSQL 9.1 is complaining:
ERROR: insert or update on table "employee" violates foreign key constraint "FK_employer"
DETAIL: Key (employer)=(-1) is not present in table "employer".
I know that theres no employer with id = -1 but still, I want it that way. I want to set employer as -1 for this emplyee. Is it possible with postgreSQL?
Make the default null. Is it good?
employer INTEGER DEFAULT null