= DatabaseCreation = == Опис == Во оваа фаза е имплементирана релационата база на податоци за VQEMS системот во PostgreSQL. Структурата на базата е дефинирана со DDL скриптата, додека податоците потребни за работа и тестирање на системот се генерираат со посебна скрипта. Основните датотеки се: * [attachment:ddl.sql ddl.sql] - дефиниција на табелите, клучевите и ограничувањата * [attachment:seed_generator.py seed_generator.py] - генерирање на податоци за пополнување на базата == DML - работа со податоците == По креирањето на структурата на базата, потребно е табелите да се пополнат со податоци кои ќе овозможат реално тестирање на системот. Поради големиот број на потребни записи, податоците не се внесуваат рачно со поединечни `INSERT` наредби. Наместо тоа, се користи Python скрипта која автоматски генерира податоци за сите табели. Скриптата користи `Faker` за генерирање на реалистични вредности како: * имиња и презимиња * компании * email адреси * URL адреси * текстови за reviews и disputes * датуми * буџети * договори и проекти За да може истиот сет на податоци повторно да се генерира, се користи фиксен seed: {{{#!python SEED = 42 fake = Faker() Faker.seed(SEED) random.seed(SEED) }}} == Редослед на внесување на податоците == Податоците се генерираат според зависностите помеѓу табелите, со цел да се почитуваат странските клучеви дефинирани во базата. Редоследот е приближно: 1. lookup табели (`Role`, `Permission`, `Industry`, `Project_Status`, `Technology`, ...) 2. `Vendor` и `Client` 3. `User` и неговите специјализации 4. `Vendor_Subscription` 5. `Client_Vendor_Contract` 6. `Project` 7. `Project_Technology` 8. `Project_Budget_Audit` 9. `Project_Status_History` 10. `Review` 11. `Review_Score` 12. `Dispute_Ticket` Со ова се обезбедува записите кои се референцираат преку foreign key да постојат пред да бидат употребени во зависните табели. == Пример - генерирање на Project записи == За табелата `Project` се генерираат записи со договор, статус, име, почетен и краен датум и буџет: {{{#!python NUM_PROJECTS = 1_400_000 with csv_writer( "project.csv", [ "project_id", "contract_id", "status_id", "project_name", "start_date", "end_date", "budget", ], ) as w: for i in range(NUM_PROJECTS): sd = rand_date(0, 4) ``` ed = ( sd + timedelta(days=random.randint(30, 730)) if random.random() > 0.2 else None ) w.writerow( { "project_id": i + 1, "contract_id": random.choice(contract_ids), "status_id": random.choice(status_ids), "project_name": fake.catch_phrase(), "start_date": sd, "end_date": ed, "budget": round(random.uniform(1_000, 250_000), 2), } ) ``` }}} При генерирањето, `contract_id` и `status_id` се избираат од веќе постоечките идентификатори, со што се задржува референцијалниот интегритет на податоците. == Пример - Reviews и Review Scores == За дел од проектите се генерира review: {{{#!python reviewed_pids = random.sample( range(1, NUM_PROJECTS + 1), k=int(NUM_PROJECTS * 0.70) ) }}} За секој review потоа се генерира оценка за секоја дефинирана димензија: {{{#!python for rid in review_ids: for did in dim_ids: w.writerow( { "review_id": rid, "dimension_id": did, "score_value": random.randint(1, 5), } ) }}} На овој начин еден review има повеќе оценки, согласно моделот `Review` - `Review_Score` - `Rating_Dimension`. == Пример - врски помеѓу проект и технологии == Еден проект може да користи повеќе технологии. За секој проект случајно се избираат од една до пет технологии: {{{#!python for pid in project_ids: for tid in random.sample(tech_ids, random.randint(1, 5)): w.writerow( { "project_id": pid, "technology_id": tid } ) }}} Со ова се пополнува many-to-many релацијата `Project_Technology`. == Генерирање на податоците == Скриптата може да се стартува со: {{{#!bash python3 seed_generator.py seed_data }}} Како резултат се генерираат CSV датотеки за табелите во базата, кои потоа се користат за нејзино пополнување. Поголемите табели содржат голем број записи за да се симулира реална употреба на апликацијата. На пример: || '''Табела''' || '''Број на записи''' || || Vendor || 5,000 || || Client || 20,000 || || User || 77,000 || || Client_Vendor_Contract || 250,000 || || Project || 1,400,000 || || Review || 980,000 || || Review_Score || 4,900,000 || Покрај нив, `Project_Technology` и `Project_Status_History` генерираат повеќе записи за секој проект, со што и тие достигнуваат многу голем број на редици. == Заклучок == Со DDL скриптата е дефинирана структурата на PostgreSQL базата, додека DML делот е поддржан преку автоматско генерирање на реалистични податоци за нејзино пополнување. Податоците ги следат врските и ограничувањата дефинирани во релациониот модел и обезбедуваат доволно голем dataset за понатамошно тестирање, работа со погледи и оптимизација на упити.