prisma introspect generate invalid model - sql

Prisma version : ^2.26.0
Prisma/client : ^2.26.0
#relation error msg in : Error parsing attribute "#relation": The type of the field userId in the model posts is not matching the type of the referenced field id in model users.
Why prisma created invalid model or something wrong with my code after i run npx prisma introspect?
It cause cannot to enter the prisma studio since those error in my code.
Any solution or thought could share to make me know better for this?
Below is my sql:
-- Create a custom type
CREATE TYPE "user_role_enum" AS ENUM ('user', 'admin', 'superadmin');
-- Create a table
CREATE TABLE "users"(
"id" BIGSERIAL PRIMARY KEY NOT NULL,
"name" VARCHAR(255) NOT NULL,
"email" VARCHAR(255) UNIQUE NOT NULL,
"role" user_role_enum NOT NULL DEFAULT('user')
);
-- Create a table
CREATE TABLE "posts"(
"id" BIGSERIAL PRIMARY KEY NOT NULL,
"title" VARCHAR(255) NOT NULL,
"body" TEXT,
"userId" INTEGER NOT NULL,
FOREIGN KEY ("userId") REFERENCES "users"("id")
);
-- Create data
INSERT INTO "users" ("name", "email", "role")
VALUES('John Doe', 'john#email.com', 'admin'),
('jane Doe', 'jane#email.com', 'admin'),
('Ahmed Hadjou', 'ahmed#hadjou.com', 'user');
INSERT INTO "posts" ("title", "body", "userId")
VALUES('Hello World!!', 'Hey guys, I see a rainbow through this prisma :D', 1),
('So do I', 'It looks cooool!!!', 2),
('It does', 'Yeahhh', 1);
Generate for model from prisma introspect
model posts {
id BigInt #id #default(autoincrement())
title String #db.VarChar(255)
body String?
userId Int
users users #relation(fields: [userId], references: [id]) // Error parsing attribute "#relation": The type of the field `userId` in the model `posts` is not matching the type of the referenced field `id` in model `users`.
}
model users {
id BigInt #id #default(autoincrement())
name String #db.VarChar(255)
email String #unique #db.VarChar(255)
role user_role_enum #default(user)
posts posts[] // error in here
}
enum user_role_enum {
user
admin
superadmin
}

Just change Int to BigInt userId in Post Model , it will work

Related

How do we design schema for user settings table for postgresql?

How do we design schema for user settings/preferences table in a sql database like postgresql?
I am interested to know the proper way to design the schema of users_setting table where users are able to modify their settings. This seems to be a 1-to-1 relationship because each row of users table corresponds to a single row in the users_setting table
so this is like a 1-to-1 table relation between users and users_setting. Is this the wrong way to do this? I have searched online and could not really find any useful example schemas where users manage their settings. So here i am asking this question. I am certain this will help many people also
Here is what my current design looks like
DROP TABLE if exists users cascade;
DROP TABLE IF EXISTS "users";
DROP SEQUENCE IF EXISTS users_id_seq;
CREATE SEQUENCE users_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1;
CREATE TABLE "public"."users" (
"id" bigint DEFAULT nextval('users_id_seq') NOT NULL,
"email" text NOT NULL,
"password" text NOT NULL,
"full_name" text NOT NULL,
"status" text NOT NULL,
"is_verified" boolean NOT NULL,
"role" text NOT NULL,
"created_at" timestamptz NOT NULL,
"updated_at" timestamptz NOT NULL,
"verified_at" timestamptz NOT NULL,
CONSTRAINT "users_email_key" UNIQUE ("email"),
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
) WITH (oids = false);
DROP TABLE if exists users_setting cascade;
DROP TABLE IF EXISTS "users_setting";
DROP SEQUENCE IF EXISTS users_setting_id_seq;
CREATE SEQUENCE users_setting_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1;
CREATE TABLE "public"."users_setting" (
"id" bigint DEFAULT nextval('users_setting_id_seq') NOT NULL,
"default_currency" text NOT NULL,
"default_timezone" text NOT NULL,
"default_notification_method" text NOT NULL,
"default_source" text NOT NULL,
"default_cooldown" integer NOT NULL,
"updated_at" timestamptz NOT NULL,
"user_id" bigint,
CONSTRAINT "users_setting_pkey" PRIMARY KEY ("id")
) WITH (oids = false);
ALTER TABLE ONLY "public"."users_setting" ADD CONSTRAINT "users_setting_user_id_fkey" FOREIGN KEY (user_id) REFERENCES "users"(id) NOT DEFERRABLE;
begin transaction;
INSERT INTO "users" ("id", "email", "password", "full_name", "status", "is_verified", "role", "created_at", "updated_at", "verified_at") VALUES
(1, 'users1#email.com', 'password', 'users1', 'active', '1', 'superuser', '2022-07-05 01:05:50.22384+00', '0001-01-01 00:00:00+00', '2022-07-11 14:10:26.615722+00'),
(2, 'users2#email.com', 'password', 'users2', 'active', '0', 'user', '2022-07-05 01:05:50.22384+00', '0001-01-01 00:00:00+00', '2022-07-11 14:10:26.615722+00');
INSERT INTO "users_setting" ("id", "default_currency", "default_timezone", "default_notification_method", "default_source", "default_cooldown", "updated_at", "user_id") VALUES
(1, 'usd', 'utc', 'email', 'google', 300, '2022-07-13 01:05:50.22384+00', 2),
(2, 'usd', 'utc', 'sms', 'yahoo', 600, '2022-07-14 01:05:50.22384+00', 2);
commit;
so lets say i want to return a single row where a users.email is users1#email.com for example, here is query i can run
select * from users, users_setting where users.id = users_setting.user_id AND users.email = 'users1#email.com';
id email password full_name status is_verified role created_at updated_at verified_at id default_currency default_timezone default_notification_method default_source default_cooldown updated_at user_id
1 users1#email.com password users1 active 1 superuser 2022-07-05 01:05:50.22384+00 0001-01-01 00:00:00+00 2022-07-11 14:10:26.615722+00 1 usd utc email google 300 2022-07-13 01:05:50.22384+00 1
i can have a single table for this but the table will get really long row-wise as i add more and more thing. user settings is just one, there are other tables similar to this. So will be great to know how to design a situation like this properly
In your case a JSON could do the job:
ALTER TABLE public.users ADD user_settings jsonb NULL;
Update of settings will be something like:
UPDATE users
SET user_settings = '{"default_currency": "usd", "default_timezone" : "utc"}'
WHERE id = 1;
And select:
select * from users WHERE id = 1;
You will find:
Also consider in Postgresql you can index a JSON, for example to query on a particular setting. Se here: https://www.postgresql.org/docs/current/datatype-json.html#JSON-INDEXING
Specific:
Still, with appropriate use of expression indexes, the above query can
use an index. If querying for particular items within the "tags" key
is common, defining an index like this may be worthwhile:
CREATE INDEX idxgintags ON api USING GIN ((jdoc -> 'tags'));
With this solution you can avoid JSON. Drawback is that setting_value cannot be tailored to exact type you need, compared to your first idea.
For example you can create:
CREATE TABLE public.user_setting (
user_id bigint NOT NULL,
setting_name text NOT NULL,
setting_value text NULL,
CONSTRAINT user_setting_pk PRIMARY KEY (user_id,setting_name)
);
ALTER TABLE public.user_setting ADD CONSTRAINT user_setting_fk FOREIGN KEY (user_id) REFERENCES public.users(id);
At this point I suggest you to have 2 query, one for users and one for settings:
SELECT *
FROM user_setting us
where user_id = 1;

Is there any possible way to map the name of foreign key in reference table? (ManyToMany)

I tried to implement a reference table when it comes to ManyToMany relation in the context of DDD based on this article(https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates)
I have different naming for JdbcEntity because I have another Domain Entity named Book which handles domain logic. (I've decided to decouple Domain model and Persistence model which is JdbcEntity as below)
The problem is the class name BookJdbcEntity is mapped as a foreign key name in book_author automatically:
"PreparedStatementCallback; bad SQL grammar [SELECT `book_author`.`AUTHOR_ID` AS `AUTHOR_ID` FROM `book_author` WHERE `book_author`.`BOOK_JDBC_ENTITY` = ?]; nested exception is java.sql.SQLSyntaxErrorException: (conn=845) Unknown column 'book_author.BOOK_JDBC_ENTITY' in 'where clause'",
Is there any possible way to generate the below SQL statement? (book_id instead of BOOK_JDBC_ENTITY)
SELECT `book_author`.`AUTHOR_ID` AS `AUTHOR_ID` FROM `book_author` WHERE `book_author`.`book_id` = ?
Jdbc Entity:
#Table("book")
data class BookJdbcEntity(
#Id val id: Long,
val title: String,
val isbn: String,
val pages: Int,
val authors: Set<AuthorRef> = hashSetOf()
)
#Table("book_author")
data class AuthorRef(val authorId: Long)
Schema:
CREATE TABLE IF NOT EXISTS book
(
id bigint(20) NOT NULL,
title VARCHAR(100) NOT NULL,
isbn varchar(100) not null,
pages INTEGER not null,
PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS book_author
(
book_id bigint(20) NOT NULL,
author_id bigint(20) NOT NULL,
constraint book_id_fk foreign key (book_id) references book (id)
);
That's done with #MappedCollection
#Table("book")
data class BookJdbcEntity(
#Id val id: Long,
val title: String,
val isbn: String,
val pages: Int,
#MappedCollection(idColumn="book_id")
val authors: Set<AuthorRef> = hashSetOf()
)

How to manipulate objects with inheritance in sql (oracle)?

Supposing that i have that hierarchy, how can i manipulate (add, edit) an agent or a client ?
CREATE TYPE TPRENOM AS varray(3) OF VARCHAR2(20);
CREATE TYPE tadr as object(
cp int not null,
state varchar2(20),
city varchar2(20),
street varchar2(20),
doorNum int
);
create type tperson as object(
fname varchar2(20),
lname tprenom,
adress tadr,
phoneNum varchar2(10),
email varchar2(50)
)not final;
create type tutilisateur under tperson(
username varchar2(20),
password varchar2(20)
);
create table agent(
id_ag int not null,
infos tutilisateur not null
, CONSTRAINT agent_pk PRIMARY KEY
(
ID_ag
)
enable
);
create table client(
id_cl int not null,
infos tperson not null,
num_chec varchar2(30) not null,
CONSTRAINT client_pk PRIMARY KEY
(
ID_cl
)
enable
);
I've tried these, but it didn't work :
insert into agent values(1, tutilisateur( tperson( 'name', tprenom('bilel',
'dani','lastname3'), tadr(3,'state', 'miliana', 'hammama', 20),
'2140547854', 'email#gmail.com'), 'username', 'password'));
insert into client values(0, tperson('name', tprenom('bilel', 'dani',
'lastname3'), tadr(3,'state2','miliana','hammama',20)),'123456789');
That's the error displaying when excecuting the sql above :
Erreur SQL : ORA-02315: incorrect number of arguments for default constructor
00000 - "incorrect number of arguments for default constructor"
*Cause: The number of arguments specified for the default constructor
doesn't match the number of attributes of the object type.
*Action: Specify the correct number of arguments for the default
constructor and retry the operation.
I'm i doing inheritance wrong ?
Thanks for your response
Okay i found the solution, i can't beleive how easy it was,that's how to insert into agent table :
insert into agent
values(1,tutilisateur('name',tprenom('bilel','dani','lastname3'),tadr(3,'ain
delfa','miliana','hammama',20),'2140547854','email#gmail.com','username','password'));
That's how to insert into client table :
insert into client
values(0,tperson('name',tprenom('bilel','dani','lastname3'),tadr(3,'ain
delfa','miliana','hammama',20),'11225','email#gmail.com'),'123456789');

First DB - How to structure required information

I watched a few youtube videos about how to structure a database using tables and fields. I am a bit confused about how to strucuture my information.
I have put my attempt below:
// Identifier Table
// This is where we give each item a new unique identifier
UniqueID []
// Item Table
// This is where the main content goes which is displayed
UniqueID []
Title []
Description []
Date []
Location []
Coordinates []
Source []
Link []
// Misc Table
// This is additional useful information, but not displayed
geocoded []
country name []
By separating out the uniqueID when I delete a record I can make sure that new records still have a unique incrementing ID. Can I get some feedback on how I divided up my data into three tables.
you gave us no hint what you want to represent in your db.
For example: if location and coordinate describe a building or maybe room, than it could be useful to save that information in an extra table and have a relationship from item to it, as this would allow to easily fetch all items connected with on place.
Of course you should apply the same principle for country: a locations lays with-in a country.
BEGIN;
CREATE TABLE "country" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(255) NOT NULL
)
;
CREATE TABLE "location" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(255) NOT NULL,
"coordinate" varchar(255) NOT NULL,
"country_id" integer NOT NULL REFERENCES "country" ("id")
)
;
CREATE TABLE "item" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(25) NOT NULL,
"description" text NOT NULL,
"date" datetime NOT NULL,
"source" varchar(255) NOT NULL,
"link" varchar(255) NOT NULL,
"location_id" integer NOT NULL REFERENCES "location" ("id")
)
;
In the case stated above I would pack everything into one table since there is not enugh complexity to benfit from spliting the data into diferent tables.
When you have more metadata you can split it up into:
Item (For display data)
ItemMeta (For meta data)

Django, UserProfile inheritance nightmare?

I'm using both django-userena and django-facebook as my main registration apps.
Let's inherit my own UserProlfile from both of them:
from userena.models import UserenaBaseProfile
from django_facebook.models import FacebookProfileModel
class UserProfile(UserenaBaseProfile , FacebookProfileModel):
user = models.OneToOneField(User, unique=True, verbose_name=_('user'), related_name='user_profile')
department = models.ForeignKey('Department' , null = True , blank = True , related_name=_('user'))
name = models.CharField(max_length = 100)
birthday = models.DateField()
def __unicode__(self):
return self.name
class Student(UserProfile):
courses = models.ManyToManyField(Course , null = True, blank = True, related_name = _('student'))
Now, whenever I want go see the Student within the Django Admin, I get this error :
Exception Value: No such column: profiles_userprofile.about_me
But, it EXISTS !! this is the output of ./manage.py sqlall profiles :
BEGIN;
CREATE TABLE "profiles_userprofile" (
"id" integer NOT NULL PRIMARY KEY,
"mugshot" varchar(100) NOT NULL,
"privacy" varchar(15) NOT NULL,
"about_me" text, ## Her it is !!!
"facebook_id" bigint UNIQUE,
"access_token" text NOT NULL,
"facebook_name" varchar(255) NOT NULL,
"facebook_profile_url" text NOT NULL,
"website_url" text NOT NULL,
"blog_url" text NOT NULL,
"image" varchar(255),
"date_of_birth" date,
"gender" varchar(1),
"raw_data" text NOT NULL,
"user_id" integer NOT NULL UNIQUE REFERENCES "auth_user" ("id"),
"department_id" integer,
"name" varchar(100) NOT NULL,
"birthday" date NOT NULL
)
;
I'm so so confused .. can anybody gives me a hint please ??
sqlall only tells you the SQL that would be sent, if you were running syncdb for the first time. It does not give you the actual state of the database. You must actually run syncdb to have the tables created. Further, if any of the tables already existed, syncdb will not make any changes to the table(s); it only creates tables, never alters them.
If you need to alter the table, you will either have to manually run SQL on your database, or use something like South to do a migration.