├── 18S2 └── README.md ├── 19T2 ├── Assignments │ ├── COMP9315 19T2 - Assignment 1.pdf │ ├── COMP9315 19T2 - Assignment 2.pdf │ ├── ass1 │ │ ├── Makefile │ │ └── test │ │ │ ├── COMP9315 19T2 - Assignment 1 - TEST.pdf │ │ │ ├── COMP9315 19T2 - Assignment 1 - Testing.pdf │ │ │ ├── Testing Resources │ │ │ ├── queries.sql │ │ │ ├── schema.sql │ │ │ └── schema0.sql │ │ │ └── testing │ │ │ ├── check.php │ │ │ ├── email.data │ │ │ ├── lib │ │ │ └── db.php │ │ │ ├── queries1.sql │ │ │ ├── queries2.sql │ │ │ ├── queries3.sql │ │ │ ├── run-tests │ │ │ └── schema.sql │ └── ass2 │ │ ├── Makefile │ │ ├── R.data │ │ ├── R.info │ │ ├── R.ovflow │ │ ├── W.data │ │ ├── W.info │ │ ├── W.ovflow │ │ ├── bits.c │ │ ├── bits.h │ │ ├── bits.o │ │ ├── chvec.c │ │ ├── chvec.h │ │ ├── chvec.o │ │ ├── create │ │ ├── create.c │ │ ├── create.o │ │ ├── defs.h │ │ ├── dump │ │ ├── dump.c │ │ ├── dump.o │ │ ├── gendata │ │ ├── gendata.c │ │ ├── gendata.o │ │ ├── hash.c │ │ ├── hash.h │ │ ├── hash.o │ │ ├── insert │ │ ├── insert.c │ │ ├── insert.o │ │ ├── page.c │ │ ├── page.h │ │ ├── page.o │ │ ├── pages.c │ │ ├── query.c │ │ ├── query.h │ │ ├── query.o │ │ ├── reln.c │ │ ├── reln.h │ │ ├── reln.o │ │ ├── select │ │ ├── select.c │ │ ├── select.o │ │ ├── stats │ │ ├── stats.c │ │ ├── stats.o │ │ ├── tuple.c │ │ ├── tuple.h │ │ ├── tuple.o │ │ ├── util.c │ │ ├── util.h │ │ └── util.o ├── Course Notes │ ├── COMP9315 Introduction.pdf │ ├── COMP9315 Scan, Sort, Project.pdf │ ├── COMP9315 Selection on Multiple Attributes.pdf │ ├── COMP9315 Selection on One Attribute.pdf │ ├── COMP9315 Storage_ Devices, Files, Pages, Tuples, Buffers, Catalogs.pdf │ ├── Implementing Join.pdf │ ├── Query Processing.pdf │ ├── Similarity-based Selection.pdf │ └── Transaction Processing.pdf ├── Lecture Exercises │ ├── week01 │ │ ├── Ex1 │ │ │ └── sql.txt │ │ ├── Ex2 │ │ │ ├── Makefile.txt │ │ │ ├── big.txt │ │ │ ├── blocks.c │ │ │ └── small.txt │ │ ├── Ex3 │ │ │ └── relalg.txt │ │ ├── Ex4 │ │ │ └── pop.sql │ │ ├── Ex5 │ │ │ └── schema.sql │ │ ├── Ex6 │ │ │ └── enumType.txt │ │ ├── Ex7 │ │ │ ├── dataFiles.txt │ │ │ └── pizza.dump │ │ └── databases │ │ │ ├── pizza (1).dump │ │ │ └── uni.sql │ ├── week02 │ │ ├── Ex1 │ │ │ └── scan-cost.txt │ │ ├── Ex2 │ │ │ └── files.txt │ │ ├── Ex3 │ │ │ └── openFile.txt │ │ ├── Ex4 │ │ │ └── joinquery.txt │ │ └── Ex5 │ │ │ ├── Makefile.txt │ │ │ ├── bufpool.c │ │ │ ├── bufpool.h │ │ │ └── joinsim.c │ ├── week03 │ │ ├── Ex01 │ │ │ └── get_record.txt │ │ ├── Ex02 │ │ │ ├── schemas.txt │ │ │ └── tsize.sql │ │ ├── Ex03 │ │ │ ├── terminology.txt │ │ │ ├── withDict.c │ │ │ └── withXmax.c │ │ ├── Ex04 │ │ │ ├── insert1.c │ │ │ └── insert2.c │ │ ├── Ex05 │ │ │ └── spaceutil.txt │ │ ├── Ex06 │ │ │ ├── Relation.txt │ │ │ └── next_tuple.txt │ │ ├── Ex07 │ │ │ └── costs.txt │ │ ├── Ex08 │ │ │ └── field-desc.txt │ │ ├── Ex09 │ │ │ ├── hash-cost.txt │ │ │ └── sort-cost.txt │ │ ├── Ex1 │ │ │ └── get_record.txt │ │ ├── Ex10 │ │ │ └── copy-cost.txt │ │ ├── Ex11 │ │ │ └── visibility.txt │ │ ├── Ex2 │ │ │ ├── schemas.txt │ │ │ └── tsize.sql │ │ ├── Ex3 │ │ │ ├── terminology.txt │ │ │ ├── withDict.c │ │ │ └── withXmax.c │ │ ├── Ex4 │ │ │ ├── insert1.c │ │ │ └── insert2.c │ │ ├── Ex5 │ │ │ └── spaceutil.txt │ │ ├── pages │ │ │ ├── page.graffle │ │ │ ├── page.png │ │ │ ├── page0.graffle │ │ │ └── spaceutil.txt │ │ ├── schema.sql │ │ └── tuples │ │ │ └── makeTuple2.c │ ├── week04 │ │ ├── Ex01 │ │ │ └── copy-cost │ │ ├── Ex02 │ │ │ └── sort-cost │ │ ├── Ex03 │ │ │ └── sort-proj-cost │ │ ├── Ex04 │ │ │ └── hash-proj-cost │ │ ├── Ex05 │ │ │ └── query-types │ │ ├── Ex06 │ │ │ └── heap-deletion │ │ ├── Ex07 │ │ │ └── sorted-search │ │ ├── Ex08 │ │ │ └── optimisation │ │ ├── Ex09 │ │ │ └── static-hash │ │ ├── Ex10 │ │ │ ├── Makefile │ │ │ ├── bits.c │ │ │ ├── bits.h │ │ │ ├── bits.o │ │ │ ├── h │ │ │ ├── h.c │ │ │ ├── h.o │ │ │ ├── hash.c │ │ │ ├── hash.o │ │ │ ├── s │ │ │ ├── s.c │ │ │ ├── s.o │ │ │ ├── showBits.c │ │ │ └── showBits.o │ │ ├── Ex11 │ │ │ └── linear-hash │ │ └── bits │ │ │ ├── Makefile │ │ │ ├── bits.c │ │ │ ├── bits.h │ │ │ ├── h.c │ │ │ ├── hash.c │ │ │ ├── s.c │ │ │ └── showBits.c │ ├── week06 │ │ ├── Ex1 │ │ │ └── index-size │ │ ├── Ex10 │ │ │ └── kd-tree-search │ │ ├── Ex11 │ │ │ └── quad-tree-search │ │ ├── Ex12 │ │ │ └── r-tree-search │ │ ├── Ex2 │ │ │ └── multiple-indexes │ │ ├── Ex3 │ │ │ └── bitmap │ │ ├── Ex4 │ │ │ └── ma-hash-value │ │ ├── Ex5 │ │ │ └── ma-hashing │ │ ├── Ex6 │ │ │ └── bit-string │ │ ├── Ex7 │ │ │ └── mah-queries │ │ └── Ex8 │ │ │ └── mah-design │ ├── week08 │ │ ├── Ex1 │ │ │ └── join-order │ │ ├── Ex2 │ │ │ ├── sel-size2 │ │ │ └── selection-size │ │ ├── Ex3 │ │ │ └── join-size │ │ └── Ex4 │ │ │ └── query-plans │ └── week09 │ │ ├── Ex1 │ │ └── transfer │ │ ├── Ex2 │ │ └── number-of-schedules │ │ ├── Ex3 │ │ ├── recov.serial │ │ └── recoverable │ │ ├── Ex4 │ │ └── serializable │ │ ├── Ex5 │ │ └── deadlock │ │ └── Ex6 │ │ └── seat-alloc ├── Lectures │ ├── all-slides.pdf │ ├── week01.pdf │ ├── week02.pdf │ ├── week03.pdf │ ├── week04.pdf │ ├── week06.pdf │ ├── week08.pdf │ ├── week09.pdf │ └── week10.pdf ├── Prac Exercises │ ├── p01 │ │ ├── COMP9315 19T2 - Prac Exercise 01.pdf │ │ └── beer.dump │ ├── p02 │ │ ├── COMP9315 19T2 - Prac Exercise 02.pdf │ │ ├── schema.sql │ │ └── schema1.sql │ ├── p03 │ │ ├── COMP9315 19T2 - Prac Exercise 03.pdf │ │ ├── db.dump │ │ ├── load.out │ │ ├── pop.sql │ │ └── schema.sql │ ├── p04 │ │ ├── COMP9315 19T2 - Prac Exercise 04.pdf │ │ └── LogData │ └── p05 │ │ └── COMP9315 19T2 - Prac Exercise 05.pdf ├── README.md └── Theory Exercises │ ├── COMP9315 18s2 - Exercises 01.pdf │ ├── COMP9315 18s2 - Exercises 02.pdf │ ├── COMP9315 18s2 - Exercises 03.pdf │ ├── COMP9315 18s2 - Exercises 04.pdf │ ├── COMP9315 18s2 - Exercises 05.pdf │ ├── COMP9315 18s2 - Exercises 06.pdf │ ├── COMP9315 18s2 - Exercises 07.pdf │ ├── COMP9315 19T2 - Exercises 08.pdf │ ├── COMP9315 19T2 - Exercises 09.pdf │ └── COMP9315 19T2 - Exercises 10.pdf └── README.md /18S2/README.md: -------------------------------------------------------------------------------- 1 | # DBMS Implementation COMP9315 18s2 2 | 3 | ## Course Summary 4 | This course aims to introduce students to the detailed internal structure of database management systems (DBMSs) such as Oracle or SQL Server. DBMSs contain a variety of interesting data structures and algorithms that are also potentially useful outside the DBMS context; knowing about them is a useful way of extending your general programming background. While the focus is on relational DBMSs, given that they have the best-developed technological foundation, we will also consider more recent developments in the management of large data repositories. 5 | 6 | Relational DBMSs need to deal with a variety of issues: storage structures and management, implementation of relational operations, query optimisation, transactions, concurrency, recovery, security. The course will address most of these, along with a look at emerging database systems trends. The level of detail on individual topics will vary; some will be covered in significant detail, others will be covered relatively briefly. 7 | 8 | An important aim of this course is to give you a chance to undertake an in-depth exploration of the internals of a real DBMS: PostgreSQL. Lectures will discuss the general principles of how DBMSs are implemented, and will also illustrate them with extensive examples from PostgreSQL where possible. 9 | 10 | -------------------------------------------------------------------------------- /19T2/Assignments/COMP9315 19T2 - Assignment 1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/COMP9315 19T2 - Assignment 1.pdf -------------------------------------------------------------------------------- /19T2/Assignments/COMP9315 19T2 - Assignment 2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/COMP9315 19T2 - Assignment 2.pdf -------------------------------------------------------------------------------- /19T2/Assignments/ass1/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------- 2 | # 3 | # Makefile-- 4 | # Makefile for tutorial 5 | # 6 | # By default, this builds against an existing PostgreSQL installation 7 | # (the one identified by whichever pg_config is first in your path). 8 | # Within a configured source tree, you can say "make NO_PGXS=1 all" 9 | # to build using the surrounding source tree. 10 | # 11 | # IDENTIFICATION 12 | # src/tutorial/Makefile 13 | # 14 | #------------------------------------------------------------------------- 15 | 16 | MODULES = complex funcs email 17 | DATA_built = advanced.sql basics.sql complex.sql funcs.sql syscat.sql email.sql 18 | 19 | ifdef NO_PGXS 20 | subdir = src/tutorial 21 | top_builddir = ../.. 22 | include $(top_builddir)/src/Makefile.global 23 | include $(top_srcdir)/src/makefiles/pgxs.mk 24 | else 25 | PG_CONFIG = pg_config 26 | PGXS := $(shell $(PG_CONFIG) --pgxs) 27 | include $(PGXS) 28 | endif 29 | 30 | %.sql: %.source 31 | rm -f $@; \ 32 | C=`pwd`; \ 33 | sed -e "s:_OBJWD_:$$C:g" < $< > $@ 34 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/COMP9315 19T2 - Assignment 1 - TEST.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass1/test/COMP9315 19T2 - Assignment 1 - TEST.pdf -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/COMP9315 19T2 - Assignment 1 - Testing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass1/test/COMP9315 19T2 - Assignment 1 - Testing.pdf -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/Testing Resources/queries.sql: -------------------------------------------------------------------------------- 1 | -- How many users/sessions are there? 2 | 3 | select count(*) from Users; 4 | 5 | 6 | -- How many sessions has each user had? 7 | 8 | select username, count(*) 9 | from Sessions group by username having count(*) > 1; 10 | 11 | 12 | -- Produce a list of users' real names and session time 13 | 14 | select u.realname, s.loggedin 15 | from Users u join Sessions s using (username) 16 | order by s.loggedin; 17 | 18 | 19 | -- Some tuples with invalid email addresses 20 | -- Should cause an error message to be generated 21 | -- You should think of other cases to test 22 | 23 | insert into Users values 24 | ('x--@abc.com'::EmailAddr, 'Mister X'); 25 | insert into Users values 26 | ('123@abc.com'::EmailAddr,'Mister 123'); 27 | insert into Users values 28 | ('!$!$#!@abc.com'::EmailAddr,'Mister naughty'); 29 | insert into Users values 30 | ('jas@cse'::EmailAddr,'Mister JAS'); 31 | 32 | 33 | -- Test some of the comparison operators 34 | -- You should think of other cases to test 35 | 36 | -- should return true 37 | 38 | select 'jas@abc.com'::EmailAddr = 'JAS@aBc.CoM'::EmailAddr; 39 | select 'xx1@abc.com'::EmailAddr < 'xx2@abc.com'::EmailAddr; 40 | select 'xx2@abc.com'::EmailAddr < 'xx1@abd.com'::EmailAddr; 41 | 42 | -- should return false 43 | 44 | select 'jas@abc.com'::EmailAddr <> 'JAS@aBc.CoM'::EmailAddr; 45 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/Testing Resources/schema.sql: -------------------------------------------------------------------------------- 1 | create table Users ( 2 | username EmailAddr, 3 | realname text, 4 | primary key (username) 5 | ); 6 | 7 | create table Sessions ( 8 | sessionID integer, 9 | username EmailAddr references Users(username), 10 | loggedin timestamp, 11 | primary key (sessionID) 12 | ); 13 | 14 | 15 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/Testing Resources/schema0.sql: -------------------------------------------------------------------------------- 1 | create table Users ( 2 | username text, 3 | realname text, 4 | primary key (username) 5 | ); 6 | 7 | create table Sessions ( 8 | sessionID integer, 9 | username text references Users(username), 10 | loggedin timestamp, 11 | primary key (sessionID) 12 | ); 13 | 14 | 15 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/testing/check.php: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/testing/lib/db.php: -------------------------------------------------------------------------------- 1 | 0) db_error($sql); 155 | return $sql; 156 | } 157 | 158 | function truth_value($val) 159 | { 160 | if (!isset($val)) return null; 161 | if ($val === true) 162 | return 't'; 163 | elseif ($val === false) 164 | return 'f'; 165 | $val = strtolower(substr($val,0,1)); 166 | if ($val == 't' || $val == 'y') 167 | return 't'; 168 | elseif ($val == 'f' || $val == 'n') 169 | return 'f'; 170 | else 171 | return $val; 172 | } 173 | 174 | function db_error($msg) { fatal($msg); } 175 | 176 | function fatal($msg) 177 | { 178 | $msg .= "\n"; 179 | $trace = debug_backtrace(); 180 | foreach ($trace as $ref) { 181 | if (array_key_exists("file",$ref)) 182 | $msg .= "in '$ref[file]'"; 183 | if (array_key_exists("file",$ref)) 184 | $msg .= ", line $ref[line]"; 185 | if (array_key_exists("file",$ref)) 186 | $msg .= ", $ref[function]("; 187 | if (array_key_exists("args",$ref)) { 188 | $args = array(); 189 | foreach ($ref["args"] as $a) 190 | $arg[] = strval($a); 191 | $msg .= join(",",$args); 192 | } 193 | if (array_key_exists("file",$ref)) 194 | $msg .= ")"; 195 | $msg .= "\n"; 196 | } 197 | exit ("$msg\n"); 198 | } 199 | 200 | ?> 201 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/testing/queries1.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Some tuples with invalid email addresses 3 | -- Should cause an error message to be generated 4 | 5 | \echo 6 | \echo -- Checking invalid emails ... expect to see errors -- 7 | \echo 8 | 9 | insert into Users values ('x--@abc.com'::EmailAddr, 'Mister X'); 10 | insert into Users values ('x.@abc.com'::EmailAddr, 'Mister X'); 11 | insert into Users values ('123@abc.com'::EmailAddr,'Mister 123'); 12 | insert into Users values ('!$!$#!@abc.com'::EmailAddr,'Mister naughty'); 13 | insert into Users values ('jas@cse'::EmailAddr,'Mister JAS'); 14 | insert into Users values ('jas@cse.'::EmailAddr,'Mister Trailing Dot'); 15 | insert into Users values ('jas@cse@unsw'::EmailAddr,'Mister Two Ats'); 16 | 17 | -- should return true 18 | 19 | \echo 20 | \echo -- Checking relational operators ... tests below should all return True -- 21 | \echo 22 | 23 | select 'jas@abc.com'::EmailAddr = 'JAS@aBc.CoM'::EmailAddr; 24 | select 'jas@abc.com'::EmailAddr <= 'jas@abc.com'::EmailAddr; 25 | select 'xx1@abc.com'::EmailAddr < 'xx2@abc.com'::EmailAddr; 26 | select 'xx2@abc.com'::EmailAddr > 'xx1@abc.com'::EmailAddr; 27 | select 'xx2@abc.com'::EmailAddr < 'xx1@abd.com'::EmailAddr; 28 | select 'xx2@abc.com'::EmailAddr <> 'xx1@abd.com'::EmailAddr; 29 | 30 | -- should return false 31 | 32 | \echo 33 | \echo -- Checking relational operators ... tests below should all return False -- 34 | \echo 35 | 36 | select 'jas@abc.com'::EmailAddr <> 'JAS@aBc.CoM'::EmailAddr; 37 | select 'jas@abc.co'::EmailAddr = 'jas@abc.com'::EmailAddr; 38 | select 'jas@abc.com'::EmailAddr > 'jas@abc.com'::EmailAddr; 39 | select 'xx1@abc.com'::EmailAddr > 'xx2@abc.com'::EmailAddr; 40 | select 'xx2@abc.com'::EmailAddr > 'xx1@abd.com'::EmailAddr; 41 | 42 | \echo 43 | \echo -- Running some queries -- 44 | \echo 45 | \timing on 46 | 47 | \echo 48 | \echo -- Count users/sessions ... 49 | \echo -- There should be 68988 Users and 111002 Sessions 50 | \echo 51 | select count(*) from Users; 52 | \echo 53 | select count(*) from Sessions; 54 | 55 | \echo 56 | \echo -- Lookup on Users using EmailAddr 57 | \echo 58 | select * from Users 59 | where username='chang.lee@saintmarys.edu'::EmailAddr; 60 | 61 | \echo 62 | \echo -- Lookup on Sessions using EmailAddr 63 | \echo 64 | select * from Sessions 65 | where username='t.kawamura@a1b2c3.enit.fr'::EmailAddr; 66 | 67 | \echo 68 | \echo -- Check ordering based on domain, then user 69 | \echo 70 | select * from Sessions order by username limit 20; 71 | 72 | \echo 73 | \echo -- Check grouping based on email 74 | \echo 75 | select username, count(*) 76 | from Sessions group by username having count(*) > 3 77 | limit 20; 78 | 79 | \echo 80 | \echo -- Join on EmailAddres 81 | \echo 82 | select u.realname, s.loggedin 83 | from Users u join Sessions s on (u.username=s.username) 84 | where s.username = 'd.fleck@a1b2c3.enit.fr'; 85 | 86 | \timing off 87 | 88 | -- Check if it can generate and use indexes 89 | 90 | \echo 91 | \echo -- Check to see whether hash index works for Sessions.username -- 92 | \echo 93 | 94 | create index hash_file on Sessions using hash (username); 95 | 96 | explain (analyze, format yaml) 97 | select * from Sessions 98 | where username = 'p.toft@inbox.vsh.cz'::EmailAddr; 99 | 100 | drop index hash_file; 101 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/testing/queries2.sql: -------------------------------------------------------------------------------- 1 | -- Some tuples with bounday-case-sized values 2 | -- May cause server to crash 3 | 4 | \echo 5 | \echo -- Checking very long email addresses (bounday-cases) 6 | \echo 7 | 8 | insert into Users values 9 | ('aa2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234@a123456789.b23456789.c23456789.d23456789.e23456789.f23456789.g23456789.h23456789.i23456789.j23456789.k23456789.l23456789.m23456789.n23456789.o23456789.p23456789.q23456789.r23456789.s23456789.t23456789.u23456789.v23456789.w23456789.x23456789.y23456789.z234'::EmailAddr, 10 | 'Mister X1'); 11 | insert into Users values 12 | ('aa23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345@a123456789.b23456789.c23456789.d23456789.e23456789.f23456789.g23456789.h23456789.i23456789.j23456789.k23456789.l23456789.m23456789.n23456789.o23456789.p23456789.q23456789.r23456789.s23456789.t23456789.u23456789.v23456789.w23456789.x23456789.y23456789.z2345'::EmailAddr, 13 | 'Mister X2'); 14 | insert into Users values 15 | ('aa234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456@a123456789.b23456789.c23456789.d23456789.e23456789.f23456789.g23456789.h23456789.i23456789.j23456789.k23456789.l23456789.m23456789.n23456789.o23456789.p23456789.q23456789.r23456789.s23456789.t23456789.u23456789.v23456789.w23456789.x23456789.y23456789.z23456'::EmailAddr, 16 | 'Mister X3'); 17 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/testing/queries3.sql: -------------------------------------------------------------------------------- 1 | \echo 2 | \echo -- Check to see whether very long addresses were inserted 3 | \echo 4 | 5 | select * from Users where realname = 'Mister X1'; 6 | select * from Users where realname = 'Mister X2'; 7 | 8 | \echo 9 | \echo -- This tuple has a too-long email address 10 | \echo 11 | 12 | select * from Users where realname = 'Mister X3'; 13 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/testing/run-tests: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | 3 | SRVR=/srvr/$USER 4 | TSTDIR=$SRVR/testing 5 | PGDIR=$SRVR/pgsql 6 | SRCDIR=$SRVR/postgresql-11.3/src 7 | DB="email-test" 8 | source $SRVR/env 9 | 10 | OUT=$TSTDIR/testing.out 11 | echo "" > $OUT 12 | 13 | # clean up old database 14 | if [ -f "$PGDIR/data/.s.PGSQL.5432" ] 15 | then 16 | pg_ctl stop 17 | fi 18 | 19 | # clean up old code in tutorial directory 20 | cd $SRCDIR/tutorial/ 21 | if [ ! -f email.c ] 22 | then 23 | echo "Error: No email.c file in $SRCDIR/tutorial/" 24 | exit 1 25 | fi 26 | if [ ! -f email.source ] 27 | then 28 | echo "Error: No email.source file in $SRCDIR/tutorial/" 29 | exit 1 30 | fi 31 | 32 | echo >> $OUT 33 | echo === Cleaning src/tutorial directory before make === >> $OUT 34 | echo >> $OUT 35 | make clean >> $OUT 2>&1 36 | 37 | echo >> $OUT 38 | echo === Contents of src/tutorial directory before make === >> $OUT 39 | echo >> $OUT 40 | ls -l email.* >> $OUT 41 | 42 | echo >> $OUT 43 | echo === Making email.o and email.sql === >> $OUT 44 | echo >> $OUT 45 | make >> $OUT 2>&1 46 | 47 | echo >> $OUT 48 | echo === Starting PostgreSQL server === >> $OUT 49 | echo >> $OUT 50 | rm -f $TSTDIR/pg_log 51 | pg_ctl start -l $TSTDIR/pg_log >> $OUT 2>&1 52 | sleep 3 53 | 54 | echo >> $OUT 55 | echo === Checking PostgreSQL server === >> $OUT 56 | echo >> $OUT 57 | psql -l >> $OUT 2>&1 58 | dropdb --if-exists $DB >> $OUT 2>&1 59 | 60 | echo >> $OUT 61 | echo === Creating database === >> $OUT 62 | echo >> $OUT 63 | echo "(no output means no errors)" >> $OUT 64 | echo >> $OUT 65 | createdb $DB >> $OUT 66 | echo >> $OUT 67 | echo === Loading Email type === >> $OUT 68 | echo >> $OUT 69 | psql $DB -f email.sql >> $OUT 2>&1 70 | echo >> $OUT 71 | echo === Loading schema === >> $OUT 72 | echo >> $OUT 73 | psql $DB -e -f $TSTDIR/schema.sql >> $OUT 2>&1 74 | echo >> $OUT 75 | echo === Loading data === >> $OUT 76 | echo >> $OUT 77 | /usr/bin/time psql $DB -f $TSTDIR/email.data >> $OUT 2>&1 78 | echo >> $OUT 79 | echo === Checking file sizes === >> $OUT 80 | echo >> $OUT 81 | php $TSTDIR/check.php "$DB" "$PGDIR/data/base" >> $OUT 2>&1 82 | echo >> $OUT 83 | echo === Running tests === >> $OUT 84 | echo >> $OUT 85 | psql $DB -e -f $TSTDIR/queries1.sql >> $OUT 2>&1 86 | echo >> $OUT 87 | echo === Running more tests === >> $OUT 88 | echo >> $OUT 89 | psql $DB -e -f $TSTDIR/queries2.sql >> $OUT 2>&1 90 | psql $DB -e -f $TSTDIR/queries3.sql >> $OUT 2>&1 91 | -------------------------------------------------------------------------------- /19T2/Assignments/ass1/test/testing/schema.sql: -------------------------------------------------------------------------------- 1 | create table Users ( 2 | username EmailAddr, 3 | realname text 4 | -- primary key (username) 5 | ); 6 | 7 | create table Sessions ( 8 | sessionID integer, 9 | username EmailAddr, -- references Users(username), 10 | loggedin timestamp 11 | -- primary key (sessionID) 12 | ); 13 | 14 | 15 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for COMP9315 16s1 Assignment 2 2 | # 3 | # Note: 4 | # - there are no dependencies on *.h files 5 | # - these define interfaces, and interfaces don't change 6 | 7 | CC=gcc 8 | CFLAGS=-Wall -Werror -g -std=c99 9 | LIBS=query.o page.o reln.o tuple.o util.o chvec.o hash.o bits.o 10 | BINS=create dump insert select stats gendata 11 | 12 | all : $(BINS) 13 | 14 | create: create.o $(LIBS) 15 | dump: dump.o $(LIBS) 16 | insert: insert.o $(LIBS) 17 | select: select.o $(LIBS) 18 | stats: stats.o $(LIBS) 19 | gendata: gendata.o $(LIBS) 20 | 21 | create.o: create.c defs.h 22 | dump.o: dump.c defs.h reln.h page.h 23 | insert.o: insert.c defs.h reln.h tuple.h 24 | select.o: select.c defs.h query.h tuple.h reln.h chvec.h hash.h bits.h 25 | stats.o: stats.c defs.h reln.h 26 | gendata.o: gendata.c defs.h 27 | 28 | bits.o: bits.c bits.h 29 | chvec.o: chvec.c defs.h chvec.h reln.h 30 | hash.o: hash.c defs.h hash.h bits.h 31 | page.o: page.c defs.h bits.h 32 | query.o: query.c defs.h query.h reln.h tuple.h 33 | reln.o: reln.c defs.h reln.h page.h tuple.h chvec.h hash.h bits.h 34 | tuple.o: tuple.c defs.h tuple.h reln.h chvec.h hash.h bits.h 35 | util.o: util.c 36 | 37 | defs.h: util.h 38 | 39 | db: 40 | rm -f R.* 41 | ./create R 3 5 "" 42 | ./gendata 1000 3 1234 | ./insert R 43 | 44 | clean: 45 | rm -f $(BINS) *.o 46 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/R.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/R.data -------------------------------------------------------------------------------- /19T2/Assignments/ass2/R.info: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /19T2/Assignments/ass2/R.ovflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/R.ovflow -------------------------------------------------------------------------------- /19T2/Assignments/ass2/W.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/W.data -------------------------------------------------------------------------------- /19T2/Assignments/ass2/W.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/W.info -------------------------------------------------------------------------------- /19T2/Assignments/ass2/W.ovflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/W.ovflow -------------------------------------------------------------------------------- /19T2/Assignments/ass2/bits.c: -------------------------------------------------------------------------------- 1 | // bits.h, bits.c ... an ADT for bit-strings 2 | // bits.c ... functions on bit-strings 3 | // part of Multi-attribute Linear-hashed Files 4 | // Bit-strings are 32-bit unsigned quantities 5 | // Last modified by John Shepherd, July 2019 6 | 7 | #include 8 | #include "bits.h" 9 | 10 | // check if the bit at position is 1 11 | 12 | int bitIsSet(Bits val, int position) 13 | { 14 | assert(0 <= position && position <= 31); 15 | Bits mask = (1 << position); 16 | return ((val & mask) != 0); 17 | } 18 | 19 | // set the bit at position to 1 20 | 21 | Bits setBit(Bits val, int position) 22 | { 23 | assert(0 <= position && position <= 31); 24 | Bits mask = (1 << position); 25 | return (val | mask); 26 | } 27 | 28 | // set the bit at position to 0 29 | 30 | Bits unsetBit(Bits val, int position) 31 | { 32 | assert(0 <= position && position <= 31); 33 | Bits mask = (~(1 << position)); 34 | return (val & mask); 35 | } 36 | 37 | // extract just lower-order n bits 38 | 39 | Bits getLower(Bits b, int n) 40 | { 41 | assert(1 <= n && n <= 32); 42 | int i; Bits mask = 0; 43 | for (i = 0; i < n; i++) mask |= (1< 36 49 | 50 | void bitsString(Bits val, char *buf) 51 | { 52 | int i,j; char ch; 53 | Bits bit = 0x80000000; 54 | 55 | i = j = 0; 56 | while (bit != 0) { 57 | ch = ((val & bit) != 0) ? '1' : '0'; 58 | buf[i++] = ch; 59 | j++; 60 | if (j%8 == 0) buf[i++] = ' '; 61 | bit = bit >> 1; 62 | } 63 | buf[--i] = '\0'; 64 | } 65 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/bits.h: -------------------------------------------------------------------------------- 1 | // bits.h ... interface to functions on bit-strings 2 | // part of Multi-attribute Linear-hashed Files 3 | // See bits.c for details of functions 4 | // Last modified by John Shepherd, July 2019 5 | 6 | #ifndef BITS_H 7 | #define BITS_H 1 8 | 9 | typedef unsigned int Bits; 10 | 11 | int bitIsSet(Bits, int); 12 | Bits setBit(Bits, int); 13 | Bits unsetBit(Bits, int); 14 | Bits getLower(Bits, int); 15 | void bitsString(Bits, char *); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/bits.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/bits.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/chvec.c: -------------------------------------------------------------------------------- 1 | // chvec.h, chvec.c ... an ADT for choice vectors 2 | // chvec.c ... functions on ChoiceVectors 3 | // part of Multi-attribute Linear-hashed Files 4 | // A ChVec is an array of MAXCHVEC ChVecItems 5 | // Each ChVecItem is a pair (attr#,bit#) 6 | // See chvec.c for details on functions 7 | // Last modified by John Shepherd, July 2019 8 | 9 | #include "defs.h" 10 | #include "reln.h" 11 | #include "chvec.h" 12 | 13 | // convert a a,b:a,b:a,b:...:a,b" representation 14 | // of a choice vector into a ChVec 15 | // if string doesn't specify all 32 bits, then 16 | // cycle through attributes until reach 32 bits 17 | 18 | Status parseChVec(Reln r, char *str, ChVec cv) 19 | { 20 | Count i = 0, nattr = nattrs(r); 21 | char *c = str, *c0 = str; 22 | while (*c != '\0') { 23 | while (*c != ':' && *c != '\0') c++; 24 | Count a, b, n; 25 | if (*c == '\0') { 26 | n = sscanf(c0, "%d,%d", &a, &b); 27 | // is the (attr,bit) pair valid? 28 | // neither a nor b can be < 0 because they're unsigned 29 | if (n != 2 || a >= nattr || b >= 32) { 30 | printf("Invalid choice vector element: (att:%d,bit:%d)\n",a,b); 31 | return ~OK; 32 | } 33 | } 34 | else { 35 | *c = '\0'; 36 | n = sscanf(c0, "%d,%d", &a, &b); 37 | if (n != 2 || a >= nattr || b >= 32) { 38 | printf("Invalid choice vector element: (att:%d,bit:%d)\n",a,b); 39 | return ~OK; 40 | } 41 | *c = ':'; c++; c0 = c; 42 | } 43 | cv[i].att = a; cv[i].bit = b; 44 | printf("cv[%d] is (%d,%d)\n", i, cv[i].att, cv[i].bit); 45 | i++; 46 | } 47 | // get enough bits for a 32-bit choice vector 48 | // take new bits from top end of each hash, 49 | // so as to hopefully not conflict 50 | Count x; Count next[MAXCHVEC]; 51 | for (x = 0; x < MAXCHVEC; x++) next[x] = 31; 52 | x = 0; 53 | while (i < MAXCHVEC) { 54 | cv[i].att = x; cv[i].bit = next[x]; 55 | printf("cv[%d] is (%d,%d)\n", i, cv[i].att, cv[i].bit); 56 | next[x]--; 57 | i++; x = (x+1) % nattr; 58 | } 59 | return OK; 60 | } 61 | 62 | // print a choice vector (for debugging) 63 | 64 | void printChVec(ChVec cv) 65 | { 66 | int i; 67 | for (i = 0; i < MAXCHVEC; i++) { 68 | printf("%d,%d",cv[i].att, cv[i].bit); 69 | if (i < MAXCHVEC-1) putchar(':'); 70 | } 71 | printf("\n"); 72 | } 73 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/chvec.h: -------------------------------------------------------------------------------- 1 | // chvec.h ... interface to functions on ChoiceVectors 2 | // part of Multi-attribute Linear-hashed Files 3 | // A ChVec is an array of MAXCHVEC ChVecItems 4 | // Each ChVecItem is a pair (attr#,bit#) 5 | // See chvec.c for details on functions 6 | // Last modified by John Shepherd, July 2019 7 | 8 | #ifndef CHVEC_H 9 | #define CHVEC_H 1 10 | 11 | #include "defs.h" 12 | #include "reln.h" 13 | 14 | #define MAXCHVEC 32 15 | 16 | typedef struct _ChVecItem { Byte att; Byte bit; } ChVecItem; 17 | 18 | typedef ChVecItem ChVec[MAXCHVEC]; 19 | 20 | Status parseChVec(Reln r, char *str, ChVec cv); 21 | void printChVec(ChVec cv); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/chvec.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/chvec.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/create: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/create -------------------------------------------------------------------------------- /19T2/Assignments/ass2/create.c: -------------------------------------------------------------------------------- 1 | // create.c ... a main program that creates a new MALH relation 2 | // create.c ... create an empty Relation 3 | // part of Multi-attribute linear-hashed files 4 | // Ask a query on a named file 5 | // Usage: ./create [-v] RelName #attrs #pages ChoiceVector 6 | // where #attrs = # of attributes in each tuple 7 | // #pages = initial (empty) pages in File 8 | // ChoiceVector = attr,bit:attr,bit:... 9 | 10 | #include 11 | #include 12 | #include 13 | #include "util.h" 14 | #include "reln.h" 15 | 16 | #define USAGE "./create [-v] RelName #attrs #pages ChoiceVector" 17 | 18 | 19 | // Main ... process args, create relation 20 | 21 | int main(int argc, char **argv) 22 | { 23 | //Reln r; // handle on the data file 24 | int nattrs; // number of attributes in each tuple 25 | int npages; // initial number of pages 26 | char err[MAXERRMSG]; // buffer for error messages 27 | int verbose; // show extra info on query progress 28 | char *rname; // name of table/file 29 | char *attrs; // number of attributes in tuples 30 | char *pages; // number of pages in data file 31 | char *cv; // choice vector 32 | 33 | // Process command-line args 34 | 35 | if (argc < 2) fatal(USAGE); 36 | if (strcmp(argv[1], "-v") == 0) { 37 | if (argc < 6) fatal(USAGE); 38 | verbose = 1; rname = argv[2]; attrs = argv[3]; pages = argv[4]; cv = argv[5]; 39 | } 40 | else { 41 | if (argc < 5) fatal(USAGE); 42 | verbose = 0; rname = argv[1]; attrs = argv[2]; pages = argv[3]; cv = argv[4]; 43 | } 44 | 45 | // how many attributes in each tuple 46 | nattrs = atoi(attrs); 47 | if (nattrs < 2 || nattrs > 10) { 48 | sprintf(err, "Invalid #attrs: %d (must be 1 < # < 11)", nattrs); 49 | fatal(err); 50 | } 51 | 52 | // how many initally empty pages 53 | npages = atoi(pages); 54 | if (npages < 1 || npages > 64) { 55 | sprintf(err, "Invalid #pages: %d (must be 0 < # < 65)", nattrs); 56 | fatal(err); 57 | } 58 | // convert to least 2^d >= npages 59 | // d gives initial depth of file 60 | int d = 0, np = 1; 61 | while (np < npages) { d++; np <<= 1; } 62 | 63 | if (verbose) 64 | printf("#a=%d, #p=%d, d=%d\n", nattrs, np, d); 65 | 66 | // Open files for the Relation and initialise 67 | 68 | if (existsRelation(rname)) { 69 | sprintf(err, "Relation %s already exists", rname); 70 | fatal(err); 71 | } 72 | if (newRelation(rname, nattrs, np, d, cv) != OK) { 73 | sprintf(err, "Problems while creating relation %s", rname); 74 | fatal(err); 75 | } 76 | return OK; 77 | } 78 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/create.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/create.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/defs.h: -------------------------------------------------------------------------------- 1 | // defs.h ... global definitions 2 | // part of Multi-attribute Linear-hashed Files 3 | // Defines types and constants used throughout code 4 | // Last modified by John Shepherd, July 2019 5 | 6 | #ifndef DEFS_H 7 | #define DEFS_H 1 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "util.h" 14 | 15 | #define PAGESIZE 1024 16 | #define NO_PAGE 0xffffffff 17 | #define MAXERRMSG 200 18 | #define MAXTUPLEN 200 19 | #define MAXRELNAME 200 20 | #define MAXFILENAME MAXRELNAME+8 21 | #define MAXBITS 32 22 | #define OK 0 23 | #define TRUE 1 24 | #define FALSE 0 25 | 26 | typedef char Bool; 27 | typedef unsigned char Byte; 28 | typedef int Status; 29 | typedef unsigned int Offset; 30 | typedef unsigned int Count; 31 | typedef Offset PageID; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/dump -------------------------------------------------------------------------------- /19T2/Assignments/ass2/dump.c: -------------------------------------------------------------------------------- 1 | // dump.c ... a main program that lists all tuples in an MALH relation 2 | // dump.c ... show all tuples in a Relation 3 | // part of Multi-attribute linear-hashed files 4 | // Show tuples, bucket-by-bucket 5 | // Last modified by John Shepherd, July 2019 6 | // Usage: ./stats RelName 7 | 8 | #include "defs.h" 9 | #include "reln.h" 10 | #include "page.h" 11 | 12 | void showAllTuples(Page); 13 | 14 | #define USAGE "./dump RelName" 15 | 16 | // Main ... process args, scan data, show tuples 17 | 18 | int main(int argc, char **argv) 19 | { 20 | // process command-line args 21 | 22 | if (argc < 2) fatal(USAGE); 23 | char *relname = argv[1]; 24 | 25 | // open relation and show stats 26 | 27 | if (!existsRelation(relname)) 28 | fatal("No such relation"); 29 | Reln r = openRelation(relname,"r"); 30 | if (r == NULL) 31 | fatal("Can't open relation"); 32 | 33 | for (Offset pid = 0; pid < npages(r); pid++) { 34 | printf("Bucket[%d]\n",pid); 35 | // show tuples in data file 36 | Page pg = getPage(dataFile(r),pid); 37 | showAllTuples(pg); 38 | // show tuples in overflow pages 39 | Page ovpg; PageID ovp; 40 | ovp = pageOvflow(pg); 41 | while (ovp != NO_PAGE) { 42 | printf("Ovflow->\n"); 43 | ovpg = getPage(ovflowFile(r), ovp); 44 | showAllTuples(ovpg); 45 | ovp = pageOvflow(ovpg); 46 | free(ovpg); 47 | } 48 | free(pg); 49 | } 50 | closeRelation(r); 51 | 52 | return 0; 53 | } 54 | 55 | // scan all tuples in Page 56 | 57 | void showAllTuples(Page pg) 58 | { 59 | Count ntups = pageNTuples(pg); 60 | char *c = pageData(pg); 61 | for (int i = 0; i < ntups; i++) { 62 | printf("%s\n", c); 63 | c += strlen(c) + 1; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/dump.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/dump.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/gendata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/gendata -------------------------------------------------------------------------------- /19T2/Assignments/ass2/gendata.c: -------------------------------------------------------------------------------- 1 | // gendata.c ... a main program to generate random tuples 2 | // gendata.c ... generate random tuples 3 | // part of Multi-attribute linear-hashed files 4 | // Generates a list of K random tuples with N attributes 5 | // Usage: ./insert [-v] #attributes #tuples 6 | // Last modified by John Shepherd, July 2019 7 | 8 | #include "defs.h" 9 | 10 | #define USAGE "./insert #tuples #attributes [startID] [seed]" 11 | 12 | // Main ... process args, read/insert tuples 13 | 14 | int main(int argc, char **argv) 15 | { 16 | int natts; // number of attributes in each tuple 17 | int ntups; // number of tuples 18 | int startID; // starting ID 19 | char err[MAXERRMSG]; // buffer for error messages 20 | 21 | // process command-line args 22 | 23 | if (argc < 3) fatal(USAGE); 24 | 25 | // how many tuples 26 | ntups = atoi(argv[1]); 27 | if (ntups < 1 || ntups > 100000) { 28 | sprintf(err, "Invalid #tuples: %d (must be 0 < # < 10^6)", ntups); 29 | fatal(err); 30 | } 31 | 32 | // how many attributes in each tuple 33 | natts = atoi(argv[2]); 34 | if (natts < 2 || natts > 10) { 35 | sprintf(err, "Invalid #attrs: %d (must be 1 < # < 11)", natts); 36 | fatal(err); 37 | } 38 | 39 | // set starting ID 40 | if (argc < 4) 41 | startID = 1; 42 | else 43 | startID = atoi(argv[3]); 44 | 45 | // seed random # generator 46 | if (argc < 5) 47 | srand(0); 48 | else 49 | srand(atoi(argv[4])); 50 | 51 | // reflects distribution of letter usage in english ... somewhat 52 | // id ensures that all tuples are distinct 53 | int i, j, id=startID; 54 | char attr[MAXTUPLEN]; 55 | char tuple[MAXTUPLEN]; 56 | char *randWord(); 57 | for (i = 0; i < ntups; i++) { 58 | sprintf(tuple,"%d",id++); 59 | for (j = 0; j < natts-1; j++) { 60 | sprintf(attr,",%s",randWord()); 61 | strcat(tuple,attr); 62 | } 63 | printf("%s\n",tuple); 64 | } 65 | 66 | return OK; 67 | } 68 | 69 | // based on a word-list from 70 | // http://members.optusnet.com.au/charles57/Creative/Techniques/random_words.htm 71 | 72 | char *words[251] = 73 | { 74 | "adult", "aeroplane", "air", "aircraft", "airforce", "airport", "album", 75 | "alphabet", "apple", "arm", "army", "baby", "baby", "backpack", "balloon", 76 | "banana", "bank", "barbecue", "bathroom", "bathtub", "bed", "bed", "bee", 77 | "bird", "bomb", "book", "boss", "bottle", "bowl", "box", "boy", "brain", 78 | "bridge", "butterfly", "button", "cappuccino", "car", "car-race", "carpet", 79 | "carrot", "cat", "cave", "chair", "chess-board", "chief", "child", "chisel", 80 | "chocolates", "church", "circle", "circus", "circus", "clock", "clown", 81 | "coffee", "coffee-shop", "comet", "compact-disc", "compass", "computer", 82 | "crystal", "cup", "cycle", "database", "desk", "diamond", "dingbat", "dog", 83 | "double", "dress", "drill", "drink", "drum", "dung", "ears", "earth", "egg", 84 | "electricity", "elephant", "eraser", "explosive", "eyes", "family", "famine", 85 | "fan", "feather", "festival", "film", "fin", "finger", "fire", "floodlight", 86 | "flower", "foot", "fork", "freeway", "fruit", "fungus", "game", "garden", 87 | "gas", "gasp", "gate", "gemstone", "girl", "gloves", "grapes", "guitar", 88 | "hammer", "hat", "hieroglyph", "highway", "horoscope", "horse", "hose","hot", 89 | "ice", "ice-cream", "insect", "jet-fighter", "junk", "kaleidoscope", "key", 90 | "kitchen", "knife", "leather", "leg", "library", "liquid", "magnet", "man", 91 | "map", "maze", "meat", "meteor", "microscope", "milk", "milkshake", "mist", 92 | "money", "monster", "mosquito", "mouth", "mum", "nail", "navy", "necklace", 93 | "needle", "onion", "oodle", "paintbrush", "pants", "parachute", "passport", 94 | "pebble", "pendulum", "pepper", "perfume", "pillow", "pin", "pith", "plane", 95 | "planet", "pocket", "post", "potato", "printer", "prison", "pyramid", "radar", 96 | "rainbow", "record", "restaurant", "rib", "rifle", "ring", "robot", "rock", 97 | "rocket", "roof", "room", "rope", "saddle", "salt", "sandpaper", "sandwich", 98 | "satellite", "school", "set", "ship", "shoes", "shop", "shower", "signature", 99 | "skeleton", "slave", "snail", "software", "solid", "space", "spectrum", 100 | "sphere", "spice", "spiral", "spoon", "sports-car", "spotlight", "square", 101 | "staircase", "star", "stomach", "sun", "sunglasses", "surveyor", "swim", 102 | "sword", "table", "tapestry", "teeth", "telescope", "television", "tennis", 103 | "thermometer", "tiger", "toilet", "tongue", "torch", "torpedo", "train", 104 | "treadmill", "triangle", "tunnel", "typewriter", "umbrella", "vacuum", 105 | "vampire", "videotape", "vulture", "water", "weapon", "web", "wheelchair", 106 | "win", "window", "woman", "worm", "x-ray", "yawn", "yellow", "zebra", "zoo" 107 | }; 108 | 109 | char *randWord() 110 | { 111 | return words[rand()%251]; 112 | } 113 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/gendata.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/gendata.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/hash.c: -------------------------------------------------------------------------------- 1 | // hash.h, hash.c ... the PostgreSQL hash function 2 | // hash.c ... hash function (from PostgreSQL) 3 | // part of Multi-attribute Linear-hashed Files 4 | // Last modified by John Shepherd, July 2019 5 | 6 | #include "defs.h" 7 | #include "hash.h" 8 | #include "bits.h" 9 | 10 | #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) 11 | 12 | #define mix(a,b,c) \ 13 | { \ 14 | a -= c; a ^= rot(c, 4); c += b; \ 15 | b -= a; b ^= rot(a, 6); a += c; \ 16 | c -= b; c ^= rot(b, 8); b += a; \ 17 | a -= c; a ^= rot(c,16); c += b; \ 18 | b -= a; b ^= rot(a,19); a += c; \ 19 | c -= b; c ^= rot(b, 4); b += a; \ 20 | } 21 | 22 | #define final(a,b,c) \ 23 | { \ 24 | c ^= b; c -= rot(b,14); \ 25 | a ^= c; a -= rot(c,11); \ 26 | b ^= a; b -= rot(a,25); \ 27 | c ^= b; c -= rot(b,16); \ 28 | a ^= c; a -= rot(c, 4); \ 29 | b ^= a; b -= rot(a,14); \ 30 | c ^= b; c -= rot(b,24); \ 31 | } 32 | 33 | Bits 34 | hash_any(unsigned char *k, int keylen) 35 | { 36 | Bits a, b, c, len; 37 | /* set up the internal state */ 38 | len = keylen; 39 | a = b = 0x9e3779b9; 40 | c = 3923095; 41 | 42 | /* handle most of the key */ 43 | while (len >= 12) 44 | { 45 | #ifdef WORDS_BIGENDIAN 46 | a += (k[3] + ((Bits) k[2] << 8) + ((Bits) k[1] << 16) + ((Bits) k[0] << 24)); 47 | b += (k[7] + ((Bits) k[6] << 8) + ((Bits) k[5] << 16) + ((Bits) k[4] << 24)); 48 | c += (k[11] + ((Bits) k[10] << 8) + ((Bits) k[9] << 16) + ((Bits) k[8] << 24)); 49 | #else /* !WORDS_BIGENDIAN */ 50 | a += (k[0] + ((Bits) k[1] << 8) + ((Bits) k[2] << 16) + ((Bits) k[3] << 24)); 51 | b += (k[4] + ((Bits) k[5] << 8) + ((Bits) k[6] << 16) + ((Bits) k[7] << 24)); 52 | c += (k[8] + ((Bits) k[9] << 8) + ((Bits) k[10] << 16) + ((Bits) k[11] << 24)); 53 | #endif /* WORDS_BIGENDIAN */ 54 | mix(a, b, c); 55 | k += 12; 56 | len -= 12; 57 | } 58 | 59 | /* handle the last 11 bytes */ 60 | #ifdef WORDS_BIGENDIAN 61 | switch (len) /* all the case statements fall through */ 62 | { 63 | case 11: c += ((Bits) k[10] << 8); 64 | case 10: c += ((Bits) k[9] << 16); 65 | case 9: c += ((Bits) k[8] << 24); 66 | /* the lowest byte of c is reserved for the length */ 67 | case 8: b += k[7]; 68 | case 7: b += ((Bits) k[6] << 8); 69 | case 6: b += ((Bits) k[5] << 16); 70 | case 5: b += ((Bits) k[4] << 24); 71 | case 4: a += k[3]; 72 | case 3: a += ((Bits) k[2] << 8); 73 | case 2: a += ((Bits) k[1] << 16); 74 | case 1: a += ((Bits) k[0] << 24); 75 | /* case 0: nothing left to add */ 76 | } 77 | #else /* !WORDS_BIGENDIAN */ 78 | switch (len) /* all the case statements fall through */ 79 | { 80 | case 11: c += ((Bits) k[10] << 24); 81 | case 10: c += ((Bits) k[9] << 16); 82 | case 9: c += ((Bits) k[8] << 8); 83 | /* the lowest byte of c is reserved for the length */ 84 | case 8: b += ((Bits) k[7] << 24); 85 | case 7: b += ((Bits) k[6] << 16); 86 | case 6: b += ((Bits) k[5] << 8); 87 | case 5: b += k[4]; 88 | case 4: a += ((Bits) k[3] << 24); 89 | case 3: a += ((Bits) k[2] << 16); 90 | case 2: a += ((Bits) k[1] << 8); 91 | case 1: a += k[0]; 92 | /* case 0: nothing left to add */ 93 | } 94 | #endif /* WORDS_BIGENDIAN */ 95 | 96 | final(a, b, c); 97 | return c; 98 | } 99 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/hash.h: -------------------------------------------------------------------------------- 1 | // hash.h ... interface to hash function 2 | // part of Multi-attribute Linear-hashed Files 3 | // Hash function from PostgreSQL 4 | // Last modified by John Shepherd, July 2019 5 | 6 | #ifndef HASH_H 7 | #define HASH_H 1 8 | 9 | #include "bits.h" 10 | 11 | Bits hash_any(unsigned char *, int); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/hash.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/hash.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/insert: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/insert -------------------------------------------------------------------------------- /19T2/Assignments/ass2/insert.c: -------------------------------------------------------------------------------- 1 | // insert.c ... a main program that reads tuples and insert them 2 | // insert.c ... add tuples to a relation 3 | // part of Multi-attribute linear-hashed files 4 | // Reads tuples from stdin and inserts into Reln 5 | // Usage: ./insert [-v] RelName 6 | // Last modified by John Shepherd, July 2019 7 | 8 | #include "defs.h" 9 | #include "reln.h" 10 | #include "tuple.h" 11 | 12 | #define USAGE "./insert [-v] RelName" 13 | 14 | // Main ... process args, read/insert tuples 15 | 16 | int main(int argc, char **argv) 17 | { 18 | Reln r; // handle on the open relation 19 | Tuple t; // tuple buffer 20 | char err[2*MAXERRMSG]; // buffer for error messages 21 | char tup[MAXTUPLEN]; // buffer for printable tuples 22 | int verbose; // show extra info on query progress 23 | char *rname; // name of table/file 24 | 25 | // process command-line args 26 | 27 | if (argc < 2) fatal(USAGE); 28 | if (strcmp(argv[1], "-v") == 0) 29 | { verbose = 1; rname = argv[2]; } 30 | else 31 | { verbose = 0; rname = argv[1]; } 32 | 33 | 34 | // set up relation for writing 35 | 36 | if (!existsRelation(rname)) { 37 | sprintf(err, "No such relation: %s", rname); 38 | fatal(err); 39 | } 40 | if ((r = openRelation(rname,"r+")) == NULL) { 41 | sprintf(err, "Can't open relation: %s",argv[1]); 42 | fatal(err); 43 | } 44 | 45 | // read stdin and insert tuples 46 | 47 | while ((t = readTuple(r,stdin)) != NULL) { 48 | PageID pid; 49 | pid = addToRelation(r,t); 50 | 51 | tupleString(t,tup); // printable version 52 | if (pid == NO_PAGE) { 53 | sprintf(err, "Insert of %s failed\n", tup); 54 | fatal(err); 55 | } 56 | if (verbose) printf("%s -> %d\n",tup,pid); 57 | free(t); 58 | } 59 | 60 | // clean up 61 | 62 | closeRelation(r); 63 | 64 | return 0; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/insert.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/insert.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/page.c: -------------------------------------------------------------------------------- 1 | // page.h, page.c ... an ADT for data/overflow pages 2 | // page.c ... functions on Pages 3 | // part of Multi-attribute Linear-hashed Files 4 | // Reading/writing pages into buffers and manipulating contents 5 | // Last modified by John Shepherd, July 2019 6 | 7 | #include "defs.h" 8 | #include "page.h" 9 | 10 | // internal representation of pages 11 | struct PageRep { 12 | Offset free; // offset within data[] of free space 13 | Offset ovflow; // Offset of overflow page (if any) 14 | Count ntuples; // #tuples in this page 15 | char data[1]; // start of data 16 | }; 17 | 18 | // A Page is a chunk of memory containing PAGESIZE bytes 19 | // It is implemented as a struct (free, ovflow, data[1]) 20 | // - free is the offset of the first byte of free space 21 | // - ovflow is the page id of the next overflow page in bucket 22 | // - data[] is a sequence of bytes containing tuples 23 | // - each tuple is a sequence of chars terminated by '\0' 24 | // - PageID values count # pages from start of file 25 | 26 | // create a new initially empty page in memory 27 | Page newPage() 28 | { 29 | Page p = malloc(PAGESIZE); 30 | assert(p != NULL); 31 | p->free = 0; 32 | p->ovflow = NO_PAGE; 33 | p->ntuples = 0; 34 | Count hdr_size = 2*sizeof(Offset) + sizeof(Count); 35 | int dataSize = PAGESIZE - hdr_size; 36 | memset(p->data, 0, dataSize); 37 | return p; 38 | } 39 | 40 | // append a new Page to a file; return its PageID 41 | PageID addPage(FILE *f) 42 | { 43 | int ok = fseek(f, 0, SEEK_END); 44 | assert(ok == 0); 45 | int pos = ftell(f); 46 | assert(pos >= 0); 47 | PageID pid = pos/PAGESIZE; 48 | Page p = newPage(); 49 | ok = putPage(f, pid, p); 50 | assert(ok == 0); 51 | return pid; 52 | } 53 | 54 | // fetch a Page from a file; allocate a memory buffer 55 | Page getPage(FILE *f, PageID pid) 56 | { 57 | assert(pid >= 0); 58 | Page p = malloc(PAGESIZE); 59 | assert(p != NULL); 60 | int ok = fseek(f, pid*PAGESIZE, SEEK_SET); 61 | assert(ok == 0); 62 | int n = fread(p, 1, PAGESIZE, f); 63 | assert(n == PAGESIZE); 64 | return p; 65 | } 66 | 67 | // write a Page to a file; release allocated buffer 68 | Status putPage(FILE *f, PageID pid, Page p) 69 | { 70 | assert(pid >= 0); 71 | int ok = fseek(f, pid*PAGESIZE, SEEK_SET); 72 | assert(ok == 0); 73 | int n = fwrite(p, 1, PAGESIZE, f); 74 | assert(n == PAGESIZE); 75 | free(p); 76 | return 0; 77 | } 78 | 79 | // insert a tuple into a page 80 | // returns 0 status if successful 81 | // returns -1 if not enough room 82 | Status addToPage(Page p, Tuple t) 83 | { 84 | int n = tupLength(t); 85 | char *c = p->data + p->free; 86 | Count hdr_size = 2*sizeof(Offset) + sizeof(Count); 87 | // doesn't fit ... return fail code 88 | // assume caller will put it elsewhere 89 | if (c+n > &p->data[PAGESIZE-hdr_size-2]) return -1; 90 | strcpy(c, t); 91 | p->free += n+1; 92 | p->ntuples++; 93 | return OK; 94 | } 95 | 96 | // extract page info 97 | char *pageData(Page p) { return p->data; } 98 | Count pageNTuples(Page p) { return p->ntuples; } 99 | Offset pageOvflow(Page p) { return p->ovflow; } 100 | void pageSetOvflow(Page p, PageID pid) { p->ovflow = pid; } 101 | Count pageFreeSpace(Page p) { 102 | Count hdr_size = 2*sizeof(Offset) + sizeof(Count); 103 | return (PAGESIZE-hdr_size-p->free); 104 | } 105 | 106 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/page.h: -------------------------------------------------------------------------------- 1 | // page.h ... interface to functions on Pages 2 | // part of Multi-attribute Linear-hashed Files 3 | // See pages.c for descriptions of Page type and functions 4 | // Last modified by John Shepherd, July 2019 5 | 6 | #ifndef PAGE_H 7 | #define PAGE_H 1 8 | 9 | typedef struct PageRep *Page; 10 | 11 | #include "defs.h" 12 | #include "tuple.h" 13 | 14 | Page newPage(); 15 | PageID addPage(FILE *); 16 | Page getPage(FILE *, PageID); 17 | Status putPage(FILE *, PageID, Page); 18 | Status addToPage(Page, Tuple); 19 | char *pageData(Page); 20 | Count pageNTuples(Page); 21 | Offset pageOvflow(Page); 22 | void pageSetOvflow(Page, PageID); 23 | Count pageFreeSpace(Page); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/page.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/page.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/pages.c: -------------------------------------------------------------------------------- 1 | /* 2 | COMP9315 11s2 Final Exam 3 | 4 | Print a list of pages to read to answer given queries. 5 | 6 | Command line args give file parameters: 7 | * n = number of attributes in tuples 8 | * d = file depth (# bits used in hash) 9 | * cv = choice vector (e.g. 1,2,1,2,3,...) 10 | 11 | The main loop reads queries one per line from stdin. 12 | Each query is a list of space-separated items. 13 | Each item is either a value or a "?", where "?" means 'unknown'. 14 | 15 | On choice vectors (CV): 16 | Each number in the CV indicates an attribute (1..n). 17 | There must be at least d+1 numbers in the choice vector. 18 | Bits from each attribute are added to the CV from right-to-left. 19 | 20 | Example: 21 | 22 | n=4, d=5, cv=1,1,2,3,1,2,3 23 | 24 | The choice vector is as follows: 25 | * hash bit 0 comes from bit 0 of attribute 1 26 | * hash bit 1 comes from bit 1 of attribute 1 27 | * hash bit 2 comes from bit 0 of attribute 2 28 | * hash bit 3 comes from bit 0 of attribute 3 29 | * hash bit 4 comes from bit 2 of attribute 1 30 | * hash bit 5 comes from bit 1 of attribute 2 31 | * hash bit 6 comes from bit 1 of attribute 3 32 | 33 | Note: attribute 4 is not involved in the hash value at all. 34 | 35 | 36 | Example queries (for relation R(a,b,c,d)): 37 | 38 | ?,?,?,? represents select * from R 39 | 1,?,abc,? represents select * from R where a=1 and c='abc' 40 | ?,5,xyz,7 represents select * from R where b=5 and c='xyz' and d=7 41 | 42 | */ 43 | 44 | #include 45 | #include 46 | #include 47 | #include "bits.h" 48 | #include "hash.h" 49 | 50 | // Global constants 51 | 52 | #define MAX_ATTRS 8 53 | #define MAX_DEPTH 30 54 | #define MAX_CVLEN (MAX_DEPTH+2) 55 | 56 | // File parameters ... done as globals (tsk, tsk) 57 | 58 | typedef struct { int attr; int bit; } CVitem; 59 | typedef struct { int known; uint32 hash; } Qitem; 60 | 61 | int n; // number of attributes; 62 | int d; // file depth (use d or d+1 hash bits) 63 | CVitem cv[MAX_CVLEN]; // array of choice vector items 64 | int ncv; // number of items in choice vector 65 | Qitem q[MAX_ATTRS+1]; // parsed version of query 66 | 67 | // Functions (forward referenced) 68 | 69 | void usage(char *); 70 | int makeChoiceVector(char *); // sets "cv", "ncv" 71 | int parseQuery(char *); // reads "n", sets "q" 72 | 73 | // ===== Main ===== 74 | 75 | int main(int argc, char **argv) 76 | { 77 | char line[200]; // input line buffer 78 | 79 | // process command-lines args and set things up 80 | 81 | if (argc < 4) 82 | usage("Not enough parameters"); 83 | if (sscanf(argv[1], "%d", &n) != 1 || n > MAX_ATTRS) 84 | usage("Invalid number of attributes"); 85 | if (sscanf(argv[2], "%d", &d) != 1 || d > MAX_DEPTH) 86 | usage("Invalid file depth"); 87 | if (!makeChoiceVector(argv[3])) 88 | usage("Invalid choice vector"); 89 | 90 | // read queries and display required pages 91 | 92 | printf("query> "); 93 | while (fgets(line,200,stdin) != NULL) { 94 | if (strcmp(line,"quit\n") == 0) 95 | break; 96 | if (!parseQuery(line)) { 97 | fprintf(stderr, "Invalid query\n"); 98 | } 99 | else { 100 | // Hint: what your code should do ... 101 | // determine unknown bits from query and choice vector 102 | // set known bits from query hashes and choice vector 103 | // for each configuration of unknown bits 104 | // generate new page number 105 | 106 | 107 | // XXX your code goes here XXX 108 | } 109 | printf("query> "); 110 | } 111 | return 0; 112 | } 113 | 114 | // XXX your functions go here, if you need any XXX 115 | 116 | 117 | // ===== Supplied functions ===== 118 | 119 | // makeChoiceVector() 120 | // reads a string giving choice vector data 121 | // parses string and sets values of "cv" and "ncv" 122 | 123 | int makeChoiceVector(char *in) 124 | { 125 | char *w; 126 | int attr; 127 | int attrbit[MAX_ATTRS] = {0,0,0,0,0,0,0,0}; 128 | 129 | ncv = 0; 130 | for (w = strtok(in,","); w != NULL; w = strtok(NULL,",")) { 131 | if (sscanf(w,"%d",&attr) != 1) 132 | return 0; 133 | if (attr < 1 || attr > n) 134 | return 0; 135 | cv[ncv].attr = attr; 136 | cv[ncv].bit = attrbit[attr]++; 137 | ncv++; 138 | } 139 | if (ncv < d) usage("Choice vector too short"); 140 | #if 1 141 | // debugging: comment out if you don't need it 142 | int i; 143 | printf("CV = < "); 144 | for (i = 0; i < ncv; i++) 145 | printf("(%d,%d) ", cv[i].attr, cv[i].bit); 146 | printf(">\n"); 147 | #endif 148 | return 1; 149 | } 150 | 151 | // parseQuery() 152 | // reads a string giving query data 153 | // parses string and set value of "q" 154 | // checks that there are "n" items in string 155 | 156 | int parseQuery(char *in) 157 | { 158 | char *w; 159 | int attr; 160 | char buf[40]; // allows for 32 bits + spaces 161 | 162 | for (w = in; *w != '\n'; w++) /*skip*/; 163 | *w = '\0'; 164 | attr = 1; 165 | for (w = strtok(in,","); w != NULL; w = strtok(NULL,",")) { 166 | if (w[0] == '?') { 167 | q[attr].known = 0; 168 | q[attr].hash = 0; 169 | } 170 | else { 171 | q[attr].known = 1; 172 | q[attr].hash = hash_any((unsigned char *)w, strlen(w)); 173 | } 174 | attr++; 175 | if (attr > n+1) // too many values 176 | return 0; 177 | } 178 | if (attr < n+1) // not enough values 179 | return 0; 180 | #if 1 181 | // debugging: comment out if you don't need it 182 | int i; 183 | for (i = 1; i < attr; i++) { 184 | if (!q[i].known) 185 | printf("q[%d] = ??\n",i); 186 | else 187 | printf("q[%d] = %s\n",i,bitsString(q[i].hash,buf)); 188 | } 189 | #endif 190 | return 1; 191 | } 192 | 193 | 194 | void usage(char *message) 195 | { 196 | if (message[0] != '\0') 197 | fprintf(stderr, "%s\n", message); 198 | fprintf(stderr, "Usage: ./pages n d cv\n"); 199 | exit(1); 200 | } 201 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/query.c: -------------------------------------------------------------------------------- 1 | // query.h, query.c ... an ADT for query scanners 2 | // query.c ... query scan functions 3 | // part of Multi-attribute Linear-hashed Files 4 | // Manage creating and using Query objects 5 | // Last modified by John Shepherd, July 2019 6 | 7 | #include "defs.h" 8 | #include "query.h" 9 | #include "reln.h" 10 | #include "tuple.h" 11 | 12 | // A suggestion ... you can change however you like 13 | 14 | struct QueryRep { 15 | Reln rel; // need to remember Relation info 16 | Bits known; // the hash value from MAH 17 | Bits unknown; // the unknown bits from MAH 18 | PageID curpage; // current page in scan 19 | int is_ovflow; // are we in the overflow pages? 20 | Offset curtup; // offset of current tuple within page 21 | //TODO 22 | }; 23 | 24 | // take a query string (e.g. "1234,?,abc,?") 25 | // set up a QueryRep object for the scan 26 | 27 | Query startQuery(Reln r, char *q) 28 | { 29 | Query new = malloc(sizeof(struct QueryRep)); 30 | assert(new != NULL); 31 | // TODO 32 | // Partial algorithm: 33 | // form known bits from known attributes 34 | // form unknown bits from '?' attributes 35 | // compute PageID of first page 36 | // using known bits and first "unknown" value 37 | // set all values in QueryRep object 38 | return new; 39 | } 40 | 41 | // get next tuple during a scan 42 | 43 | Tuple getNextTuple(Query q) 44 | { 45 | // TODO 46 | // Partial algorithm: 47 | // if (more tuples in current page) 48 | // get next matching tuple from current page 49 | // else if (current page has overflow) 50 | // move to overflow page 51 | // grab first matching tuple from page 52 | // else 53 | // move to "next" bucket 54 | // grab first matching tuple from data page 55 | // endif 56 | // if (current page has no matching tuples) 57 | // go to next page (try again) 58 | // endif 59 | return NULL; 60 | } 61 | 62 | // clean up a QueryRep object and associated data 63 | 64 | void closeQuery(Query q) 65 | { 66 | // TODO 67 | } 68 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/query.h: -------------------------------------------------------------------------------- 1 | // query.h ... interface to query scan functions 2 | // part of Multi-attribute Linear-hashed Files 3 | // See query.c for details of Query type and functions 4 | // Last modified by John Shepherd, July 2019 5 | 6 | #ifndef QUERY_H 7 | #define QUERY_H 1 8 | 9 | typedef struct QueryRep *Query; 10 | 11 | #include "reln.h" 12 | #include "tuple.h" 13 | 14 | Query startQuery(Reln, char *); 15 | Tuple getNextTuple(Query); 16 | void closeQuery(Query); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/query.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/query.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/reln.c: -------------------------------------------------------------------------------- 1 | // reln.h, reln.c ... an ADT for relations 2 | // reln.c ... functions on Relations 3 | // part of Multi-attribute Linear-hashed Files 4 | // Last modified by John Shepherd, July 2019 5 | 6 | #include "defs.h" 7 | #include "reln.h" 8 | #include "page.h" 9 | #include "tuple.h" 10 | #include "chvec.h" 11 | #include "bits.h" 12 | #include "hash.h" 13 | 14 | #define HEADERSIZE (3*sizeof(Count)+sizeof(Offset)) 15 | 16 | struct RelnRep { 17 | Count nattrs; // number of attributes 18 | Count depth; // depth of main data file 19 | Offset sp; // split pointer 20 | Count npages; // number of main data pages 21 | Count ntups; // total number of tuples 22 | ChVec cv; // choice vector 23 | char mode; // open for read/write 24 | FILE *info; // handle on info file 25 | FILE *data; // handle on data file 26 | FILE *ovflow; // handle on ovflow file 27 | }; 28 | 29 | // create a new relation (three files) 30 | 31 | Status newRelation(char *name, Count nattrs, Count npages, Count d, char *cv) 32 | { 33 | char fname[MAXFILENAME]; 34 | Reln r = malloc(sizeof(struct RelnRep)); 35 | r->nattrs = nattrs; r->depth = d; r->sp = 0; 36 | r->npages = npages; r->ntups = 0; r->mode = 'w'; 37 | assert(r != NULL); 38 | if (parseChVec(r, cv, r->cv) != OK) return ~OK; 39 | sprintf(fname,"%s.info",name); 40 | r->info = fopen(fname,"w"); 41 | assert(r->info != NULL); 42 | sprintf(fname,"%s.data",name); 43 | r->data = fopen(fname,"w"); 44 | assert(r->data != NULL); 45 | sprintf(fname,"%s.ovflow",name); 46 | r->ovflow = fopen(fname,"w"); 47 | assert(r->ovflow != NULL); 48 | int i; 49 | for (i = 0; i < npages; i++) addPage(r->data); 50 | closeRelation(r); 51 | return 0; 52 | } 53 | 54 | // check whether a relation already exists 55 | 56 | Bool existsRelation(char *name) 57 | { 58 | char fname[MAXFILENAME]; 59 | sprintf(fname,"%s.info",name); 60 | FILE *f = fopen(fname,"r"); 61 | if (f == NULL) 62 | return FALSE; 63 | else { 64 | fclose(f); 65 | return TRUE; 66 | } 67 | } 68 | 69 | // set up a relation descriptor from relation name 70 | // open files, reads information from rel.info 71 | 72 | Reln openRelation(char *name, char *mode) 73 | { 74 | Reln r; 75 | r = malloc(sizeof(struct RelnRep)); 76 | assert(r != NULL); 77 | char fname[MAXFILENAME]; 78 | sprintf(fname,"%s.info",name); 79 | r->info = fopen(fname,mode); 80 | assert(r->info != NULL); 81 | sprintf(fname,"%s.data",name); 82 | r->data = fopen(fname,mode); 83 | assert(r->data != NULL); 84 | sprintf(fname,"%s.ovflow",name); 85 | r->ovflow = fopen(fname,mode); 86 | assert(r->ovflow != NULL); 87 | // Naughty: assumes Count and Offset are the same size 88 | int n = fread(r, sizeof(Count), 5, r->info); 89 | assert(n == 5); 90 | n = fread(r->cv, sizeof(ChVecItem), MAXCHVEC, r->info); 91 | assert(n == MAXCHVEC); 92 | r->mode = (mode[0] == 'w' || mode[1] =='+') ? 'w' : 'r'; 93 | return r; 94 | } 95 | 96 | // release files and descriptor for an open relation 97 | // copy latest information to .info file 98 | 99 | void closeRelation(Reln r) 100 | { 101 | // make sure updated global data is put in info 102 | // Naughty: assumes Count and Offset are the same size 103 | if (r->mode == 'w') { 104 | fseek(r->info, 0, SEEK_SET); 105 | // write out core relation info (#attr,#pages,d,sp) 106 | int n = fwrite(r, sizeof(Count), 5, r->info); 107 | assert(n == 5); 108 | // write out choice vector 109 | n = fwrite(r->cv, sizeof(ChVecItem), MAXCHVEC, r->info); 110 | assert(n == MAXCHVEC); 111 | } 112 | fclose(r->info); 113 | fclose(r->data); 114 | fclose(r->ovflow); 115 | free(r); 116 | } 117 | 118 | // insert a new tuple into a relation 119 | // returns index of bucket where inserted 120 | // - index always refers to a primary data page 121 | // - the actual insertion page may be either a data page or an overflow page 122 | // returns NO_PAGE if insert fails completely 123 | // TODO: include splitting and file expansion 124 | 125 | PageID addToRelation(Reln r, Tuple t) 126 | { 127 | Bits h, p; 128 | // char buf[MAXBITS+1]; 129 | h = tupleHash(r,t); 130 | if (r->depth == 0) 131 | p = 1; 132 | else { 133 | p = getLower(h, r->depth); 134 | if (p < r->sp) p = getLower(h, r->depth+1); 135 | } 136 | // bitsString(h,buf); printf("hash = %s\n",buf); 137 | // bitsString(p,buf); printf("page = %s\n",buf); 138 | Page pg = getPage(r->data,p); 139 | if (addToPage(pg,t) == OK) { 140 | putPage(r->data,p,pg); 141 | r->ntups++; 142 | return p; 143 | } 144 | // primary data page full 145 | if (pageOvflow(pg) == NO_PAGE) { 146 | // add first overflow page in chain 147 | PageID newp = addPage(r->ovflow); 148 | pageSetOvflow(pg,newp); 149 | putPage(r->data,p,pg); 150 | Page newpg = getPage(r->ovflow,newp); 151 | // can't add to a new page; we have a problem 152 | if (addToPage(newpg,t) != OK) return NO_PAGE; 153 | putPage(r->ovflow,newp,newpg); 154 | r->ntups++; 155 | return p; 156 | } 157 | else { 158 | // scan overflow chain until we find space 159 | // worst case: add new ovflow page at end of chain 160 | Page ovpg, prevpg = NULL; 161 | PageID ovp, prevp = NO_PAGE; 162 | ovp = pageOvflow(pg); 163 | while (ovp != NO_PAGE) { 164 | ovpg = getPage(r->ovflow, ovp); 165 | if (addToPage(ovpg,t) != OK) { 166 | prevp = ovp; prevpg = ovpg; 167 | ovp = pageOvflow(ovpg); 168 | } 169 | else { 170 | if (prevpg != NULL) free(prevpg); 171 | putPage(r->ovflow,ovp,ovpg); 172 | r->ntups++; 173 | return p; 174 | } 175 | } 176 | // all overflow pages are full; add another to chain 177 | // at this point, there *must* be a prevpg 178 | assert(prevpg != NULL); 179 | // make new ovflow page 180 | PageID newp = addPage(r->ovflow); 181 | // insert tuple into new page 182 | Page newpg = getPage(r->ovflow,newp); 183 | if (addToPage(newpg,t) != OK) return NO_PAGE; 184 | putPage(r->ovflow,newp,newpg); 185 | // link to existing overflow chain 186 | pageSetOvflow(prevpg,newp); 187 | putPage(r->ovflow,prevp,prevpg); 188 | r->ntups++; 189 | return p; 190 | } 191 | return NO_PAGE; 192 | } 193 | 194 | // external interfaces for Reln data 195 | 196 | FILE *dataFile(Reln r) { return r->data; } 197 | FILE *ovflowFile(Reln r) { return r->ovflow; } 198 | Count nattrs(Reln r) { return r->nattrs; } 199 | Count npages(Reln r) { return r->npages; } 200 | Count ntuples(Reln r) { return r->ntups; } 201 | Count depth(Reln r) { return r->depth; } 202 | Count splitp(Reln r) { return r->sp; } 203 | ChVecItem *chvec(Reln r) { return r->cv; } 204 | 205 | 206 | // displays info about open Reln 207 | 208 | void relationStats(Reln r) 209 | { 210 | printf("Global Info:\n"); 211 | printf("#attrs:%d #pages:%d #tuples:%d d:%d sp:%d\n", 212 | r->nattrs, r->npages, r->ntups, r->depth, r->sp); 213 | printf("Choice vector\n"); 214 | printChVec(r->cv); 215 | printf("Bucket Info:\n"); 216 | printf("%-4s %s\n","#","Info on pages in bucket"); 217 | printf("%-4s %s\n","","(pageID,#tuples,freebytes,ovflow)"); 218 | for (Offset pid = 0; pid < r->npages; pid++) { 219 | printf("[%2d] ",pid); 220 | Page p = getPage(r->data, pid); 221 | Count ntups = pageNTuples(p); 222 | Count space = pageFreeSpace(p); 223 | Offset ovid = pageOvflow(p); 224 | printf("(d%d,%d,%d,%d)",pid,ntups,space,ovid); 225 | free(p); 226 | while (ovid != NO_PAGE) { 227 | Offset curid = ovid; 228 | p = getPage(r->ovflow, ovid); 229 | ntups = pageNTuples(p); 230 | space = pageFreeSpace(p); 231 | ovid = pageOvflow(p); 232 | printf(" -> (ov%d,%d,%d,%d)",curid,ntups,space,ovid); 233 | free(p); 234 | } 235 | putchar('\n'); 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/reln.h: -------------------------------------------------------------------------------- 1 | // reln.h ... interface to functions on Relations 2 | // part of Multi-attribute Linear-hashed Files 3 | // See reln.c for details on Reln type and functions 4 | // Last modified by John Shepherd, July 2019 5 | 6 | #ifndef RELN_H 7 | #define RELN_H 1 8 | 9 | typedef struct RelnRep *Reln; 10 | 11 | #include "defs.h" 12 | #include "tuple.h" 13 | #include "page.h" 14 | #include "chvec.h" 15 | 16 | Status newRelation(char *name, Count nattr, Count npages, Count d, char *cv); 17 | Reln openRelation(char *name, char *mode); 18 | void closeRelation(Reln r); 19 | Bool existsRelation(char *name); 20 | PageID addToRelation(Reln r, Tuple t); 21 | FILE *dataFile(Reln r); 22 | FILE *ovflowFile(Reln r); 23 | Count nattrs(Reln r); 24 | Count npages(Reln r); 25 | Count depth(Reln r); 26 | Count splitp(Reln r); 27 | ChVecItem *chvec(Reln r); 28 | void relationStats(Reln r); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/reln.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/reln.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/select: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/select -------------------------------------------------------------------------------- /19T2/Assignments/ass2/select.c: -------------------------------------------------------------------------------- 1 | // select.c ... a main program that finds tuples matching a PMR query 2 | // select.c ... run queries 3 | // part of Multi-attribute linear-hashed files 4 | // Ask a query on a named relation 5 | // Usage: ./select [-v] RelName v1,v2,v3,v4,... 6 | // where any of the vi's can be "?" (unknown) 7 | 8 | #include "defs.h" 9 | #include "query.h" 10 | #include "tuple.h" 11 | #include "reln.h" 12 | #include "chvec.h" 13 | 14 | #define USAGE "./select [-v] RelName v1,v2,v3,v4,..." 15 | 16 | // Main ... process args, run query 17 | 18 | int main(int argc, char **argv) 19 | { 20 | Reln r; // handle on the open relation 21 | Query q; // processed version of query string 22 | Tuple t; // tuple pointer 23 | char err[MAXERRMSG]; // buffer for error messages 24 | int verbose; // show extra info on query progress 25 | char *rname; // name of table/file 26 | char *qstr; // query string 27 | 28 | // process command-line args 29 | 30 | if (argc < 3) fatal(USAGE); 31 | if (strcmp(argv[1], "-v") == 0) { 32 | verbose = 1; rname = argv[2]; qstr = argv[3]; 33 | } 34 | else { 35 | verbose = 0; rname = argv[1]; qstr = argv[2]; 36 | } 37 | 38 | if (verbose) { /* keeps compiler quiet */ } 39 | 40 | // initialise relation and scanning structure 41 | 42 | if (!existsRelation(rname)) { 43 | sprintf(err, "No such relation: %s",rname); 44 | fatal(err); 45 | } 46 | if ((r = openRelation(rname,"r")) == NULL) { 47 | sprintf(err, "Can't open relation: %s",rname); 48 | fatal(err); 49 | } 50 | if ((q = startQuery(r, qstr)) == NULL) { 51 | sprintf(err, "Invalid query: %s",qstr); 52 | fatal(err); 53 | } 54 | 55 | // execute the query (find matching tuples) 56 | 57 | char tup[MAXTUPLEN]; 58 | while ((t = getNextTuple(q)) != NULL) { 59 | tupleString(t,tup); 60 | printf("%s\n",tup); 61 | } 62 | 63 | // clean up 64 | 65 | closeQuery(q); 66 | closeRelation(r); 67 | 68 | return 0; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/select.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/select.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/stats: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/stats -------------------------------------------------------------------------------- /19T2/Assignments/ass2/stats.c: -------------------------------------------------------------------------------- 1 | // stats.c ... a main program that prints info about an MAH relation 2 | // stats.c ... show statistics for a Relation 3 | // part of Multi-attribute linear-hashed files 4 | // Show info and page stats for a Relation 5 | // Usage: ./stats RelName 6 | 7 | #include "defs.h" 8 | #include "reln.h" 9 | 10 | #define USAGE "./stats RelName" 11 | 12 | 13 | // Main ... process args, run query 14 | 15 | int main(int argc, char **argv) 16 | { 17 | // process command-line args 18 | 19 | if (argc < 2) fatal(USAGE); 20 | char *relname = argv[1]; 21 | 22 | // open relation and show stats 23 | 24 | if (!existsRelation(relname)) 25 | fatal("No such relation\n"); 26 | Reln r = openRelation(relname,"r"); 27 | if (r == NULL) fatal("No such relation"); 28 | 29 | relationStats(r); 30 | closeRelation(r); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/stats.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/stats.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/tuple.c: -------------------------------------------------------------------------------- 1 | // tuple.h, tuple.c ... an ADT for tuples 2 | // tuple.c ... functions on tuples 3 | // part of Multi-attribute Linear-hashed Files 4 | // Last modified by John Shepherd, July 2019 5 | 6 | #include "defs.h" 7 | #include "tuple.h" 8 | #include "reln.h" 9 | #include "hash.h" 10 | #include "chvec.h" 11 | #include "bits.h" 12 | 13 | // return number of bytes/chars in a tuple 14 | 15 | int tupLength(Tuple t) 16 | { 17 | return strlen(t); 18 | } 19 | 20 | // reads/parses next tuple in input 21 | 22 | Tuple readTuple(Reln r, FILE *in) 23 | { 24 | char line[MAXTUPLEN]; 25 | if (fgets(line, MAXTUPLEN-1, in) == NULL) 26 | return NULL; 27 | line[strlen(line)-1] = '\0'; 28 | // count fields 29 | // cheap'n'nasty parsing 30 | char *c; int nf = 1; 31 | for (c = line; *c != '\0'; c++) 32 | if (*c == ',') nf++; 33 | // invalid tuple 34 | if (nf != nattrs(r)) return NULL; 35 | return copyString(line); // needs to be free'd sometime 36 | } 37 | 38 | // extract values into an array of strings 39 | 40 | void tupleVals(Tuple t, char **vals) 41 | { 42 | char *c = t, *c0 = t; 43 | int i = 0; 44 | for (;;) { 45 | while (*c != ',' && *c != '\0') c++; 46 | if (*c == '\0') { 47 | // end of tuple; add last field to vals 48 | vals[i++] = copyString(c0); 49 | break; 50 | } 51 | else { 52 | // end of next field; add to vals 53 | *c = '\0'; 54 | vals[i++] = copyString(c0); 55 | *c = ','; 56 | c++; c0 = c; 57 | } 58 | } 59 | } 60 | 61 | // release memory used for separate attirubte values 62 | 63 | void freeVals(char **vals, int nattrs) 64 | { 65 | int i; 66 | for (i = 0; i < nattrs; i++) free(vals[i]); 67 | } 68 | 69 | // hash a tuple using the choice vector 70 | // TODO: actually use the choice vector to make the hash 71 | 72 | Bits tupleHash(Reln r, Tuple t) 73 | { 74 | char buf[MAXBITS+1]; 75 | Count nvals = nattrs(r); 76 | char **vals = malloc(nvals*sizeof(char *)); 77 | assert(vals != NULL); 78 | tupleVals(t, vals); 79 | Bits hash = hash_any((unsigned char *)vals[0],strlen(vals[0])); 80 | bitsString(hash,buf); 81 | printf("hash(%s) = %s\n", vals[0], buf); 82 | return hash; 83 | } 84 | 85 | // compare two tuples (allowing for "unknown" values) 86 | 87 | Bool tupleMatch(Reln r, Tuple t1, Tuple t2) 88 | { 89 | Count na = nattrs(r); 90 | char **v1 = malloc(na*sizeof(char *)); 91 | tupleVals(t1, v1); 92 | char **v2 = malloc(na*sizeof(char *)); 93 | tupleVals(t2, v2); 94 | Bool match = TRUE; 95 | int i; 96 | for (i = 0; i < na; i++) { 97 | // assumes no real attribute values start with '?' 98 | if (v1[i][0] == '?' || v2[i][0] == '?') continue; 99 | if (strcmp(v1[i],v2[i]) == 0) continue; 100 | match = FALSE; 101 | } 102 | freeVals(v1,na); freeVals(v2,na); 103 | return match; 104 | } 105 | 106 | // puts printable version of tuple in user-supplied buffer 107 | 108 | void tupleString(Tuple t, char *buf) 109 | { 110 | strcpy(buf,t); 111 | } 112 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/tuple.h: -------------------------------------------------------------------------------- 1 | // tuple.h ... interface to functions on Tuples 2 | // part of Multi-attribute Linear-hashed Files 3 | // A Tuple is just a '\0'-terminated C string 4 | // Consists of "val_1,val_2,val_3,...,val_n" 5 | // See tuple.c for details on functions 6 | // Last modified by John Shepherd, July 2019 7 | 8 | #ifndef TUPLE_H 9 | #define TUPLE_H 1 10 | 11 | typedef char *Tuple; 12 | 13 | #include "reln.h" 14 | #include "bits.h" 15 | 16 | int tupLength(Tuple t); 17 | Tuple readTuple(Reln r, FILE *in); 18 | Bits tupleHash(Reln r, Tuple t); 19 | void tupleVals(Tuple t, char **vals); 20 | void freeVals(char **vals, int nattrs); 21 | Bool tupleMatch(Reln r, Tuple t1, Tuple t2); 22 | void tupleString(Tuple t, char *buf); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/tuple.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/tuple.o -------------------------------------------------------------------------------- /19T2/Assignments/ass2/util.c: -------------------------------------------------------------------------------- 1 | // util.h, util.c ... utility functions 2 | // util.h ... interface to various useful functions 3 | // part of Multi-attribute Linear-hashed Files 4 | // Functions that don't fit into one of the 5 | // obvious data types like File, Query, ... 6 | // Last modified by John Shepherd, July 2019 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | void fatal(char *msg) 13 | { 14 | fprintf(stderr,"%s\n",msg); 15 | exit(1); 16 | } 17 | 18 | char *copyString(char *str) 19 | { 20 | char *new = malloc(strlen(str)+1); 21 | strcpy(new, str); 22 | return new; 23 | } 24 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/util.h: -------------------------------------------------------------------------------- 1 | // util.h ... interface to various useful functions 2 | // part of Multi-attribute Linear-hashed Files 3 | // Functions that don't fit into one of the 4 | // obvious data types like File, Query, ... 5 | // Last modified by John Shepherd, July 2019 6 | 7 | #ifndef UTIL_H 8 | #define UTIL_H 1 9 | 10 | void fatal(char *); 11 | char *copyString(char *); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /19T2/Assignments/ass2/util.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Assignments/ass2/util.o -------------------------------------------------------------------------------- /19T2/Course Notes/COMP9315 Introduction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Course Notes/COMP9315 Introduction.pdf -------------------------------------------------------------------------------- /19T2/Course Notes/COMP9315 Scan, Sort, Project.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Course Notes/COMP9315 Scan, Sort, Project.pdf -------------------------------------------------------------------------------- /19T2/Course Notes/COMP9315 Selection on Multiple Attributes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Course Notes/COMP9315 Selection on Multiple Attributes.pdf -------------------------------------------------------------------------------- /19T2/Course Notes/COMP9315 Selection on One Attribute.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Course Notes/COMP9315 Selection on One Attribute.pdf -------------------------------------------------------------------------------- /19T2/Course Notes/COMP9315 Storage_ Devices, Files, Pages, Tuples, Buffers, Catalogs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Course Notes/COMP9315 Storage_ Devices, Files, Pages, Tuples, Buffers, Catalogs.pdf -------------------------------------------------------------------------------- /19T2/Course Notes/Implementing Join.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Course Notes/Implementing Join.pdf -------------------------------------------------------------------------------- /19T2/Course Notes/Query Processing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Course Notes/Query Processing.pdf -------------------------------------------------------------------------------- /19T2/Course Notes/Similarity-based Selection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Course Notes/Similarity-based Selection.pdf -------------------------------------------------------------------------------- /19T2/Course Notes/Transaction Processing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Course Notes/Transaction Processing.pdf -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/Ex1/sql.txt: -------------------------------------------------------------------------------- 1 | -- Schema: 2 | -- Students(sid, name, degree, ...) 3 | -- Courses(cid, code, term, title, ...) 4 | -- Enrolments(sid, cid, mark, grade) 5 | -- sample data is avaiable in ../databases/uni.sql 6 | 7 | -- all students who passed COMP9315 in 18s2 (sid,name,mark) 8 | 9 | select s.sid, s.name, e.mark 10 | from Students s join Enrolments e join Courses c 11 | where c.code = 9315 and c.term = '18s2' and mark >= 50 12 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/Ex2/Makefile.txt: -------------------------------------------------------------------------------- 1 | blocks: blocks.c 2 | gcc -o blocks blocks.c 3 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/Ex2/blocks.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void giveUp(char *); 9 | 10 | int main(int argc, char **argv) 11 | { 12 | char *buf; 13 | int inf; // file descriptor 14 | int bufsize; 15 | ssize_t nread; 16 | int nblocks = 0, nbytes = 0; 17 | 18 | // process command line args 19 | 20 | if (argc < 3) giveUp("Insufficient args"); 21 | bufsize = atoi(argv[1]); 22 | if (bufsize < 100) giveUp("Invalid buffer size"); 23 | buf = malloc(bufsize * sizeof(char)); 24 | if (buf == NULL) giveUp("Can't create buffer"); 25 | 26 | // open file 27 | 28 | if ((inf = open(argv[2], O_RDONLY)) < 0) 29 | giveUp("Can't read file"); 30 | 31 | // read file and count blocks/bytes 32 | 33 | while ((nread = read(inf,buf,bufsize)) != 0) { 34 | nblocks++; 35 | nbytes += nread; 36 | printf("%ld bytes read in current block\n",nread); 37 | } 38 | 39 | // display results 40 | 41 | printf("Read %d blocks and %d bytes\n",nblocks,nbytes); 42 | 43 | exit(EXIT_SUCCESS); 44 | } 45 | 46 | void giveUp(char *msg) 47 | { 48 | fprintf(stderr, "Error: %s\n",msg); 49 | fprintf(stderr, "Usage: ./blocks BlockSize InputFile\n"); 50 | exit(EXIT_FAILURE); 51 | } 52 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/Ex2/small.txt: -------------------------------------------------------------------------------- 1 | A very small file. 2 | With not much text. 3 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/Ex3/relalg.txt: -------------------------------------------------------------------------------- 1 | -- Schema: 2 | -- Students(sid, name, degree, ...) 3 | -- Courses(cid, code, term, title, ...) 4 | -- Enrolments(sid, cid, mark, grade) 5 | 6 | One possibility: 7 | 8 | Tmp1 = sel[code=9315 and term=18s2]Courses 9 | Tmp2 = join[cid](Tmp1,Enrolments) 10 | Tmp3 = sel[mark >= 50]Tmp2 11 | Tmp4 = join[sid](Tmp2,Students) 12 | Res = proj[sid,name,mark]Tmp4 13 | 14 | 15 | Another possibility: 16 | 17 | Tmp1 = join[sid](Students,Enrolments) 18 | Tmp2 = join[cid](Tmp1,Courses) 19 | Tmp3 = sel[code=9315 and term=18s2 and mark >=50]Tmp2 20 | Res = proj[sid,name,mark]Tmp3 21 | 22 | 23 | The second version has less operations but it likely to 24 | be way more costly 25 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/Ex4/pop.sql: -------------------------------------------------------------------------------- 1 | -- Assumes: create type TableInfo as ("table" text, ntuples int); 2 | 3 | create or replace 4 | function pop() returns setof TableInfo 5 | as $$ 6 | declare 7 | r record; -- result tuples from out query 8 | nr integer; -- count of tuples 9 | res TableInfo; -- output tuple 10 | begin 11 | for r in select tablename 12 | from pg_tables 13 | where schemaname = 'public' 14 | order by tablename 15 | loop 16 | -- create a query via string concatentation and execute it 17 | -- store result of query in a local variable (nr) 18 | execute 'select count(*) from ' ||quote_ident(r.tablename) 19 | into nr; 20 | -- set values of attributesin output tuple 21 | res."table" := r.tablename; res.ntuples := nr; 22 | -- add output tuple to results 23 | return next res; 24 | end loop; 25 | end; 26 | $$ language plpgsql; 27 | 28 | -- Execute this function as: select * from pop(); 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/Ex5/schema.sql: -------------------------------------------------------------------------------- 1 | -- get DB schema as a sequence of strings 2 | -- each string contains TableName(Attr1Name, Attr2Name, ...) 3 | 4 | create or replace function schema() returns setof text 5 | as $$ 6 | declare 7 | rec record; -- current tuple from query 8 | rel text := ''; -- name of current table 9 | att text := ''; -- name of current attribute 10 | out text := ''; -- output string 11 | begin 12 | for rec in 13 | -- get (rel,attr,seq) for all attrs in all tables 14 | select t.relname, a.attname, a.attnum 15 | from pg_class t 16 | join pg_attribute a on (a.attrelid=t.oid) 17 | join pg_namespace n on (t.relnamespace=n.oid) 18 | where t.relkind='r' and n.nspname = 'public' 19 | and a.attnum > 0 20 | order by t.relname,a.attnum 21 | loop 22 | -- check for table name change 23 | if (rec.relname <> rel) then 24 | if (rel <> '') then 25 | -- "output" next table schema 26 | out := rel || '(' || att || ')'; 27 | return next out; 28 | end if; 29 | -- set up for new table 30 | rel := rec.relname; 31 | att := ''; 32 | end if; 33 | -- build list of attribute names 34 | -- fiddling around avoids extraneous "," 35 | if (att <> '') then 36 | att := att || ', '; 37 | end if; 38 | att := att || rec.attname; 39 | end loop; 40 | -- deal with last table 41 | -- if we don't do this, the last table is left out 42 | if (rel <> '') then 43 | out := rel || '(' || att || ')'; 44 | return next out; 45 | end if; 46 | end; 47 | $$ language plpgsql; 48 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/Ex6/enumType.txt: -------------------------------------------------------------------------------- 1 | What is the effect in the catalog of 2 | 3 | create type Mood as enum ('sad', 'happy'); 4 | 5 | Result: 6 | - adds a tuple for the type itself in the pg_type table 7 | - adds two tuples in the pg_enum table, one for each value 8 | 9 | Here's what they look like in my DB. Your OIDs will be different. 10 | 11 | jas=# select oid, typname, typlen, typtype from pg_type where typname='mood'; 12 | oid | typname | typlen | typtype 13 | -------+---------+--------+--------- 14 | 16605 | mood | 4 | e 15 | (1 row) 16 | 17 | jas=# select oid, * from pg_enum where enumtypid=16605; 18 | oid | enumtypid | enumsortorder | enumlabel 19 | -------+-----------+---------------+----------- 20 | 16606 | 16605 | 1 | sad 21 | 16608 | 16605 | 2 | happy 22 | (2 rows) 23 | 24 | Note that names are mapped to all lower-case in the PostgreSQL catalog. 25 | Using typname='Mood' in the first query will produce no results. 26 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/Ex7/dataFiles.txt: -------------------------------------------------------------------------------- 1 | First, we assume that you've loaded pizza.dump 2 | Second, you will not see the same oid's in your database 3 | 4 | The following two queries will give you the oid's 5 | 6 | pizza=# select oid, datname from pg_database where datname='pizza'; 7 | oid | datname 8 | -------+--------- 9 | 16473 | pizza 10 | (1 row) 11 | 12 | pizza=# select oid, relname from pg_class where relname in ('pizzas','people'); 13 | oid | relname 14 | -------+--------- 15 | 16480 | people 16 | 16483 | pizzas 17 | (2 rows) 18 | 19 | I can find the data files in /srvr/jas/pgsql/data/base/16473 20 | 21 | The data file for Pizzas is 16483 22 | The command "ls -l 16483" gives 23 | -rw------- 1 jas jas 8192 Jun 11 12:06 16480 24 | The command "strings 16483" gives the names of some pizza types, e.g. 25 | Beef Mia 26 | Pepperoni Mia 27 | Chicken Mia 28 | Margherita 29 | ... 30 | 31 | The data file for People is 16480 32 | The command "ls -l 16480" gives 33 | -rw------- 1 jas jas 73728 Jun 11 12:06 16480 34 | The command "strings 16480" gives the names of some people, e.g. 35 | Andrew 36 | Pak 37 | Alex 38 | Vicki 39 | StewartO 40 | Daniel 41 | Jason 42 | 43 | You won't necessarily see the strings in exactly the same order. 44 | 45 | 46 | The sizes of the files have something in common. What is it? 47 | (apart from the file update time) 48 | There is another file for People called 16480_fsm. What is this? 49 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week01/databases/uni.sql: -------------------------------------------------------------------------------- 1 | create table Students ( 2 | sid integer, 3 | name text, 4 | degree text, 5 | primary key (sid) 6 | ); 7 | create table Courses ( 8 | cid integer, 9 | code char(8), 10 | term char(4), 11 | title text, 12 | primary key (cid) 13 | ); 14 | create table Enrolments ( 15 | sid integer references Students(sid), 16 | cid integer references Courses(cid), 17 | mark integer, 18 | grade char(2) 19 | ); 20 | 21 | copy Students(sid,name,degree) from stdin; 22 | 3322111 John Smith MEngSc 23 | 3335555 Joe Blow BSc 24 | 5012345 John Smith MIT 25 | 5123456 Jack Black MEngSc 26 | 5176543 Jane Smith BSc 27 | \. 28 | 29 | copy Courses(cid, code, term, title) from stdin; 30 | 1622 COMP9315 16s1 DBMS Implementation 31 | 1732 COMP9311 18s1 Database Systems 32 | 1733 COMP3311 18s1 Database Systems 33 | 1844 COMP9315 18s2 DBMS Implementation 34 | \. 35 | 36 | copy Enrolments(sid, cid, mark, grade) from stdin; 37 | 3335555 1622 90 HD 38 | 5123456 1622 45 FL 39 | 5012345 1622 30 FL 40 | 3322111 1732 50 PS 41 | 5012345 1732 50 PS 42 | 5123456 1732 80 DN 43 | 5176543 1733 99 HD 44 | 5012345 1844 49 FL 45 | 5123456 1844 75 DN 46 | 5176543 1844 90 HD 47 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week02/Ex1/scan-cost.txt: -------------------------------------------------------------------------------- 1 | Analysis of cost of scanning a file 2 | and storing results in another file 3 | 4 | #tuples = r = 10,000 5 | #bytes/tuple = R = 200 6 | #bytes/page = B = 4096 7 | #tuples/page = c = floor(B/R) = 20 8 | #pages = ceil(r/c) = 500 9 | 10 | time to read a page = 10msec 11 | time to check one tuple = 1 usec 12 | time to form one result tuple = 1 usec 13 | 14 | Time cost for: select * from R where x > 10; 15 | 16 | #pages read = b = 500 17 | time to read pages = 500 * 10ms = 5s 18 | 19 | cost to check all tuples = 10000 * 1usec = 10ms = 0.01s 20 | 21 | #tuples in result = 5000 22 | (50% of tuples satisfy where clause) 23 | 24 | mktuple cost = 5000tuples * 1usec = 0.005s 25 | 26 | #pages written = ceil(5000/20) = 250 27 | time to write pages = 250 * 10ms = 2.5s 28 | 29 | Total time 30 | = reading + checking + making + writing 31 | = 5s + 0.01s + 0.005 + 2.5 32 | = 7.5s 33 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week02/Ex2/files.txt: -------------------------------------------------------------------------------- 1 | examine the content of the $PGDATA directory 2 | 3 | total 140 4 | drwx------ 19 jas jas 4096 Jun 12 01:16 . 5 | drwxr-xr-x 7 jas jas 4096 Jun 6 12:33 .. 6 | srwxrwxrwx 1 jas jas 0 Jun 12 17:05 .s.PGSQL.5432 7 | -rw------- 1 jas jas 64 Jun 12 17:05 .s.PGSQL.5432.lock 8 | -rw------- 1 jas jas 3 Jun 6 12:33 PG_VERSION 9 | drwx------ 8 jas jas 4096 Jun 11 14:52 base 10 | drwx------ 2 jas jas 4096 Jun 11 14:52 global 11 | -rw------- 1 jas jas 5349 Jun 12 10:43 log 12 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_commit_ts 13 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_dynshmem 14 | -rw------- 1 jas jas 4513 Jun 6 12:33 pg_hba.conf 15 | -rw------- 1 jas jas 1636 Jun 6 12:33 pg_ident.conf 16 | drwx------ 4 jas jas 4096 Jun 12 16:17 pg_logical 17 | drwx------ 4 jas jas 4096 Jun 6 12:33 pg_multixact 18 | drwx------ 2 jas jas 4096 Jun 6 14:52 pg_notify 19 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_replslot 20 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_serial 21 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_snapshots 22 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_stat 23 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_stat_tmp 24 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_subtrans 25 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_tblspc 26 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_twophase 27 | drwx------ 3 jas jas 4096 Jun 6 12:33 pg_wal 28 | drwx------ 2 jas jas 4096 Jun 6 12:33 pg_xact 29 | -rw------- 1 jas jas 88 Jun 6 12:33 postgresql.auto.conf 30 | -rw------- 1 jas jas 23897 Jun 6 12:36 postgresql.conf 31 | -rw------- 1 jas jas 39 Jun 6 14:52 postmaster.opts 32 | -rw------- 1 jas jas 94 Jun 6 14:52 postmaster.pid 33 | 34 | find the directory containing the pizza database 35 | 36 | 16473 37 | 38 | find the file in this directory for the People table 39 | 40 | 16480 41 | 42 | examine the contents of the People file 43 | 44 | strings $PGDATA/base/16473/16480 45 | 46 | what are the other files in the directory? 47 | 48 | other tables (incl pg_xxx tables), free space maps, visibility 49 | 50 | are there forks in any of your databases? 51 | 52 | not mine 53 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week02/Ex3/openFile.txt: -------------------------------------------------------------------------------- 1 | // Rough sketch of PathNameOpenFilePerm 2 | 3 | File PathNameOpenFilePerm(char *fname, int flags, int mode) 4 | { 5 | i = search VfdCache for fname 6 | if (i == NOTFOUND) { 7 | if (VfdCache is full) double the size of VfdCache 8 | i = next available VfdCache entry 9 | } 10 | if (VfdCache[i] is not open) { 11 | if (max open files already) 12 | victim = LRU VfdCache entry 13 | close(VfdCache[victim].fd) 14 | } 15 | VfdCache[i].fd = open(fname,....) 16 | } 17 | return i; 18 | } 19 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week02/Ex4/joinquery.txt: -------------------------------------------------------------------------------- 1 | for each page in Customer { 2 | for each page in Employee { 3 | for each tuple c in Customer page { 4 | for each tuple e in Employee page 5 | { process one (c,e) pair } 6 | } 7 | } 8 | } 9 | 10 | Customer: 10 pages, Employee: 4 pages 11 | 12 | Pages requested 13 | C0 then E0 E1 E2 E3 14 | C1 then E0 E1 E2 E3 15 | C2 then E0 E1 E2 E3 16 | C3 then E0 E1 E2 E3 17 | C4 then E0 E1 E2 E3 18 | ... 19 | C9 then E0 E1 E2 E3 20 | 21 | 22 | ========== 23 | 24 | With 2 buffers (no buffer pool) 25 | 26 | read each page from Customer into one buffer 27 | while Customer page held, read each Employee page 28 | 29 | #reads = 10 (outer) + 10*4 (inner) = 50 reads 30 | 31 | 32 | ========== 33 | 34 | With 20 buffers 35 | 36 | read each Customer page once 37 | read each Employee page once 38 | 39 | # reads = 10 + 4 = 14 reads 40 | 41 | 42 | ========== 43 | 44 | With n = 3 buffers and MRU strategy 45 | 46 | Assume "most recent" = "most recently released" 47 | 48 | Operation Buffer Pool Notes 49 | [0] [1] [2] 50 | 51 | initially _ _ _ 52 | request C0 C0 _ _ 53 | request E0 C0 E0 _ 54 | process C0+E0 55 | release E0 MRU: E0 56 | request E1 C0 E0 E1 57 | process C0+E1 58 | release E1 MRU: E1 -> E0 59 | request E2 C0 E0 E2 60 | process C0+E2 61 | release E2 MRU: E2 -> E0 62 | request E3 C0 E0 E3 63 | process C0+E3 64 | release E3 65 | release C0 C0 is MRU 66 | request C1 C1 E0 E3 67 | request E0 no read! 68 | process C1+E0 69 | release E0 E0 is MRU 70 | request E1 C1 E1 E3 71 | process C1+E1 72 | release E1 ? 73 | request E2 C1 E2 E3 74 | process C1+E2 75 | release E2 E2 is MRU 76 | request E3 no read! 77 | process C1+E3 78 | release E3 E3 is MRU 79 | release C1 MRU: C1 -> E3 -> E0 80 | request C2 C2 E2 E3 MRU: E3 -> E0 81 | request E0 C2 E2 E0 82 | process C2+E0 83 | release E0 MRU: E0 -> E3 84 | etc. etc. etc. 85 | 86 | #reads = ??? more than 14, less than 50 87 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week02/Ex5/Makefile.txt: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-gdwarf-2 3 | 4 | jsim : joinsim.o bufpool.o 5 | $(CC) $(CFLAGS) -o jsim joinsim.o bufpool.o 6 | 7 | joinsim.o : joinsim.c bufpool.h 8 | bufpool.o : bufpool.c bufpool.h 9 | 10 | clean : 11 | rm -f jsim *.o core 12 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week02/Ex5/bufpool.c: -------------------------------------------------------------------------------- 1 | // bufpool.c ... buffer pool implementation 2 | 3 | #include 4 | #include 5 | #include 6 | #include "bufpool.h" 7 | 8 | #define MAXID 4 9 | 10 | // for Cycle strategy, we simply re-use the nused counter 11 | // since we don't actually need to maintain a usedList 12 | #define currSlot nused 13 | 14 | // one buffer 15 | struct buffer { 16 | char id[MAXID]; 17 | int pin; 18 | int dirty; 19 | char *data; 20 | }; 21 | 22 | // collection of buffers + stats 23 | struct bufPool { 24 | int nbufs; // how many buffers 25 | char strategy; // LRU, MRU, Cycle 26 | int nrequests; // stats counters 27 | int nreleases; 28 | int nhits; 29 | int nreads; 30 | int nwrites; 31 | int *freeList; // list of completely unused bufs 32 | int nfree; 33 | int *usedList; // implements replacement strategy 34 | int nused; 35 | struct buffer *bufs; 36 | }; 37 | 38 | static clock = 0; 39 | 40 | 41 | // Helper Functions (private) 42 | 43 | 44 | // pageInBuf(pool,slot) 45 | // - return the name of the page current stored in specified slot 46 | 47 | static 48 | char *pageInBuf(BufPool pool, int slot) 49 | { 50 | char *pname; 51 | pname = pool->bufs[slot].id; 52 | if (pname[0] == '\0') 53 | return "_"; 54 | else 55 | return pname; 56 | } 57 | 58 | // pageInPool(BufPool pool, char rel, int page) 59 | // - check whether page from rel is already in the pool 60 | // - returns the slot containing this page, else returns -1 61 | 62 | static 63 | int pageInPool(BufPool pool, char rel, int page) 64 | { 65 | int i; char id[MAXID]; 66 | sprintf(id,"%c%d",rel,page); 67 | for (i = 0; i < pool->nbufs; i++) { 68 | if (strcmp(id,pool->bufs[i].id) == 0) { 69 | return i; 70 | } 71 | } 72 | return -1; 73 | } 74 | 75 | // removeFirstFree(pool) 76 | // - use the first slot on the free list 77 | // - the slot is removed from the free list 78 | // by moving all later elements down 79 | 80 | static 81 | int removeFirstFree(BufPool pool) 82 | { 83 | int v, i; 84 | assert(pool->nfree > 0); 85 | v = pool->freeList[0]; 86 | for (i = 0; i < pool->nfree-1; i++) 87 | pool->freeList[i] = pool->freeList[i+1]; 88 | pool->nfree--; 89 | return v; 90 | } 91 | 92 | // removeFromUsedList(pool,slot) 93 | // - search for a slot in the usedList and remove it 94 | // - depends on how usedList managed, so is strategy-dependent 95 | 96 | static 97 | void removeFromUsedList(BufPool pool, int slot) 98 | { 99 | int i, j; 100 | switch (pool->strategy) { 101 | case 'L': 102 | case 'M': 103 | // find where this slot appears in the usedList 104 | j = -1; 105 | for (i = 0; i < pool->nused; i++) { 106 | if (pool->usedList[i] == slot) { 107 | j = i; 108 | break; 109 | } 110 | } 111 | // if it's there, remove it 112 | if (j >= 0) { 113 | for (i = j; i < pool->nused-1; i++) 114 | pool->usedList[i] = pool->usedList[i+1]; 115 | pool->nused--; 116 | } 117 | break; 118 | case 'C': 119 | // since no used list, nothing to do 120 | break; 121 | } 122 | } 123 | 124 | // getNextSlot(pool) 125 | // - finds the "best" unused buffer pool slot 126 | // - "best" is determined by the replacement strategy 127 | // - if the replaced page is dirty, write it out 128 | // - initialise the chosen slot to hold the new page 129 | // - if there are no available slots, return -1 130 | 131 | static 132 | int grabNextSlot(BufPool pool) 133 | { 134 | int slot; 135 | switch (pool->strategy) { 136 | case 'L': 137 | // get least recently used slot from used list 138 | if (pool->nused == 0) return -1; 139 | slot = pool->usedList[0]; 140 | int i; 141 | for (i = 0; i < pool->nused-1; i++) 142 | pool->usedList[i] = pool->usedList[i+1]; 143 | pool->nused--; 144 | break; 145 | case 'M': 146 | // get most recently used slot from used list 147 | if (pool->nused == 0) return -1; 148 | slot = pool->usedList[pool->nused-1]; 149 | pool->nused--; 150 | break; 151 | case 'C': 152 | // get next available according to cycle counter 153 | slot = -1; 154 | for (i = 0; i < pool->nbufs; i++) { 155 | int s; 156 | s = (pool->currSlot + i) % pool->nbufs; 157 | if (pool->bufs[s].pin == 0) { 158 | slot = s; 159 | break; 160 | } 161 | } 162 | if (slot >= 0) 163 | pool->currSlot = (slot+1) % pool->nbufs; 164 | break; 165 | } 166 | if (slot >= 0 && pool->bufs[slot].dirty) { 167 | pool->nwrites++; 168 | pool->bufs[slot].dirty = 0; 169 | } 170 | return slot; 171 | } 172 | 173 | 174 | // makeAvailable(pool,slot) 175 | // - add the specified slot to the used list 176 | // - where to add depends on strategy 177 | 178 | static 179 | void makeAvailable(BufPool pool, int slot) 180 | { 181 | switch (pool->strategy) { 182 | case 'L': 183 | case 'M': 184 | // slot become most recently used 185 | pool->usedList[pool->nused] = slot; 186 | pool->nused++; 187 | break; 188 | case 'C': 189 | // slot becomes available 190 | // nothing to do here ... 191 | break; 192 | } 193 | } 194 | 195 | 196 | // Interface Functions 197 | 198 | 199 | // initBufPool(nbufs,strategy) 200 | // - initialise a buffer pool with nbufs 201 | // - buffer pool uses supplied replacement strategy 202 | 203 | BufPool initBufPool(int nbufs, char strategy) 204 | { 205 | BufPool newPool; 206 | struct buffer *bufs; 207 | 208 | newPool = malloc(sizeof(struct bufPool)); 209 | assert(newPool != NULL); 210 | newPool->nbufs = nbufs; 211 | newPool->strategy = strategy; 212 | newPool->nrequests = 0; 213 | newPool->nreleases = 0; 214 | newPool->nhits = 0; 215 | newPool->nreads = 0; 216 | newPool->nwrites = 0; 217 | newPool->nfree = nbufs; 218 | newPool->nused = 0; 219 | newPool->freeList = malloc(nbufs * sizeof(int)); 220 | assert(newPool->freeList != NULL); 221 | newPool->usedList = malloc(nbufs * sizeof(int)); 222 | assert(newPool->usedList != NULL); 223 | newPool->bufs = malloc(nbufs * sizeof(struct buffer)); 224 | assert(newPool->bufs != NULL); 225 | 226 | int i; 227 | for (i = 0; i < nbufs; i++) { 228 | newPool->bufs[i].id[0] = '\0'; 229 | newPool->bufs[i].pin = 0; 230 | newPool->bufs[i].dirty = 0; 231 | newPool->freeList[i] = i; 232 | newPool->usedList[i] = -1; 233 | } 234 | return newPool; 235 | } 236 | 237 | int request_page(BufPool pool, char rel, int page) 238 | { 239 | int slot; 240 | printf("Request %c%d\n", rel, page); 241 | pool->nrequests++; 242 | slot = pageInPool(pool,rel,page); 243 | if (slot >= 0) 244 | pool->nhits++; 245 | else { // page is not already in pool 246 | if (pool->nfree > 0) { 247 | slot = removeFirstFree(pool); 248 | } 249 | else { 250 | slot = grabNextSlot(pool); 251 | } 252 | if (slot < 0) { 253 | fprintf(stderr, "Failed to find slot for %c%d\n",rel,page); 254 | exit(1); 255 | } 256 | pool->nreads++; 257 | sprintf(pool->bufs[slot].id,"%c%d",rel,page); 258 | pool->bufs[slot].pin = 0; 259 | pool->bufs[slot].dirty = 0; 260 | } 261 | // have a slot 262 | pool->bufs[slot].pin++; 263 | removeFromUsedList(pool,slot); 264 | showPoolState(pool); // for debugging 265 | return slot; 266 | } 267 | 268 | void release_page(BufPool pool, char rel, int page) 269 | { 270 | printf("Release %c%d\n", rel, page); 271 | pool->nreleases++; 272 | 273 | int i; 274 | i = pageInPool(pool,rel,page); 275 | assert(i >= 0); 276 | // last user of page is about to release 277 | if (pool->bufs[i].pin == 1) { 278 | makeAvailable(pool, i); 279 | } 280 | pool->bufs[i].pin--; 281 | //showPoolState(pool); // for debugging 282 | } 283 | 284 | // showPoolUsage(pool) 285 | // - prints statistics counters for buffer pool 286 | 287 | void showPoolUsage(BufPool pool) 288 | { 289 | assert(pool != NULL); 290 | printf("#requests: %d\n",pool->nrequests); 291 | printf("#releases: %d\n",pool->nreleases); 292 | printf("#hits : %d\n",pool->nhits); 293 | printf("#reads : %d\n",pool->nreads); 294 | printf("#writes : %d\n",pool->nwrites); 295 | } 296 | 297 | // showPoolState(pool) 298 | // - display printable representation of buffer pool on stdout 299 | 300 | void showPoolState(BufPool pool) 301 | { 302 | #if 1 303 | int i; char *p; 304 | for (i = 0; i < pool->nbufs; i++) { 305 | p = pool->bufs[i].id; 306 | if (p[0] == '\0') p = "-"; 307 | printf("%5s", p); 308 | } 309 | printf("\n"); 310 | #else 311 | int i, j; char *p; struct buffer b; 312 | 313 | printf("%4s %6s %6s %6s\n","Slot","Page","Pin","Dirty"); 314 | for (i = 0; i < pool->nbufs; i++) { 315 | b = pool->bufs[i]; 316 | p = pageInBuf(pool,i); 317 | printf("[%02d] %6s %6d %6d\n", i, p, b.pin, b.dirty); 318 | } 319 | printf("FreeList:"); 320 | for (i = 0; i < pool->nfree; i++) { 321 | j = pool->freeList[i]; 322 | printf(" [%02d]%s", j, pageInBuf(pool,j)); 323 | } 324 | printf("\n"); 325 | printf("UsedList:"); 326 | for (i = 0; i < pool->nused; i++) { 327 | j = pool->usedList[i]; 328 | printf(" [%02d]%s", j, pageInBuf(pool,j)); 329 | } 330 | printf("\n"); 331 | #endif 332 | } 333 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week02/Ex5/bufpool.h: -------------------------------------------------------------------------------- 1 | // bufpool.h ... buffer pool interface 2 | 3 | typedef struct bufPool *BufPool; 4 | 5 | BufPool initBufPool(int, char); 6 | int request_page(BufPool, char, int); 7 | void release_page(BufPool, char, int); 8 | void showPoolUsage(BufPool); 9 | void showPoolState(BufPool); 10 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week02/Ex5/joinsim.c: -------------------------------------------------------------------------------- 1 | // joinsim.c ... simulate nested loop join buffering effects 2 | 3 | #include 4 | #include 5 | #include "bufpool.h" 6 | 7 | void exitUsage(char *); 8 | 9 | // main ... process args and run simulation 10 | 11 | int main(int argc, char **argv) 12 | { 13 | int outer, inner, nbufs; 14 | char strategy = 'L'; 15 | int status; 16 | 17 | // collect argv values 18 | if (argc < 5) { exitUsage(argv[0]); } 19 | sscanf(argv[1], "%d", &outer); 20 | sscanf(argv[2], "%d", &inner); 21 | sscanf(argv[3], "%d", &nbufs); 22 | strategy = argv[4][0]; 23 | 24 | // initalise buffer pool 25 | BufPool pool = initBufPool(nbufs,strategy); 26 | 27 | // simulate the nested loop join 28 | // select * from R join S ... 29 | int i, j; 30 | for (i = 0; i < outer; i++) { 31 | request_page(pool,'R',i); 32 | for (j = 0; j < inner; j++) { 33 | request_page(pool,'S',j); 34 | // process Ri and Sj 35 | release_page(pool,'S',j); 36 | } 37 | release_page(pool,'R',i); 38 | } 39 | 40 | // show buffer pool usage 41 | showPoolUsage(pool); 42 | } 43 | 44 | void exitUsage(char *prog) 45 | { 46 | fprintf(stderr, "Usage: %s OuterPages InnerPages Slots Strategy(M|L|C)\n", prog); 47 | exit(1); 48 | } 49 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex01/get_record.txt: -------------------------------------------------------------------------------- 1 | // using: get_page(), get_record(), ... 2 | 3 | Record get_record(Relation rel, RecordId rid) 4 | { 5 | (pid, tid) = rid 6 | Page *buf = get_page(rel, pid) 7 | Record rec = get_record(buf, tid) 8 | return rec 9 | } 10 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex02/schemas.txt: -------------------------------------------------------------------------------- 1 | Assume: a tuple a byte sequence (of data), preceded 2 | by a header containing e.g field offsets 3 | 4 | -- fixed-size tuples 5 | -- size = 4 + 8 + 4 + 4 + 8 = 28 bytes + header 6 | 7 | create table Course ( 8 | id integer, -- 4 bytes 9 | code char(8), -- 8 bytes, e.g. COMP9315 10 | uoc integer, -- 4 bytes 11 | term char(4), -- 4 bytes e.g. "18s2" "19T1" ... 12 | avgmark float, -- 8 bytes 13 | primary key (id) 14 | ); 15 | 16 | 17 | -- variable-sized tuples 18 | -- tuple = (header, data) 19 | -- data size = 4 + 8 + ??? + 4 + 8 = 24 + ??? bytes + header 20 | 21 | create table Course ( 22 | id integer, -- 4 bytes 23 | code char(8), -- 8 bytes, e.g. COMP9315 24 | title varchar(100), -- ??? bytes 25 | uoc integer, -- 4 bytes 26 | avgmark float, -- 8 bytes 27 | primary key (id) 28 | ); 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex02/tsize.sql: -------------------------------------------------------------------------------- 1 | drop type if exists SchemaTuple cascade; 2 | create type SchemaTuple as ("table" text, "size" text, "attributes" text); 3 | 4 | create or replace function schema1() returns setof SchemaTuple 5 | as $$ 6 | declare 7 | rec record; 8 | rel text := ''; 9 | attr text := ''; 10 | attrs text := ''; 11 | out SchemaTuple; 12 | len integer := 0; 13 | size integer := 0; 14 | isvar boolean := false; 15 | begin 16 | for rec in 17 | select r.relname, a.attname, t.typname, a.attlen, a.atttypmod 18 | from pg_class r 19 | join pg_namespace n on (r.relnamespace = n.oid) 20 | join pg_attribute a on (a.attrelid = r.oid) 21 | join pg_type t on (a.atttypid = t.oid) 22 | where r.relkind='r' 23 | and n.nspname = 'public' 24 | and attnum > 0 25 | order by relname,attnum 26 | loop 27 | if (rec.relname <> rel) then 28 | if (rel <> '') then 29 | out."table" := rel; 30 | out.attributes := attrs; 31 | out.size := size::text; 32 | if (isvar) then 33 | out.size := out.size||'+?'; 34 | end if; 35 | return next out; 36 | end if; 37 | rel := rec.relname; 38 | attrs := ''; 39 | len := 0; 40 | size := 0; 41 | isvar := false; 42 | end if; 43 | if (rec.atttypmod < 0) then 44 | size := size + rec.attlen; 45 | else 46 | end if; 47 | if (attrs <> '') then 48 | attrs := attrs || ', '; 49 | len := len + 2; 50 | end if; 51 | if (rec.typname = 'varchar') then 52 | isvar := true; 53 | rec.typname := 'varchar('||(rec.atttypmod-4)||')'; 54 | elsif (rec.typname = 'bpchar') then 55 | size := size + rec.attypmod; 56 | rec.typname := 'char('||(rec.atttypmod-4)||')'; 57 | elsif (rec.typname = 'int4') then 58 | rec.typname := 'integer'; 59 | elsif (rec.typname = 'float8') then 60 | rec.typname := 'float'; 61 | end if; 62 | attr := rec.attname||':'||rec.typname; 63 | if (len + length(attr) > 50) then 64 | attrs := attrs || E'\n'; 65 | len := 0; 66 | end if; 67 | attrs := attrs || attr; 68 | len := len + length(attr); 69 | end loop; 70 | -- deal with last table 71 | if (rel <> '') then 72 | out."table" := rel; 73 | out.attributes := attrs; 74 | out.size := size::text; 75 | if (isvar) then 76 | out.size := out.size||'+?'; 77 | end if; 78 | return next out; 79 | end if; 80 | end; 81 | $$ language plpgsql; 82 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex03/terminology.txt: -------------------------------------------------------------------------------- 1 | Record = sequence of bytes stored on disk 2 | 3 | Tuple = "interpretable" version of a Record in memory 4 | 5 | Page = copy of page from file on disk 6 | 7 | PageId = index of Page within file = pid 8 | 9 | pageOffset = pid * PAGESIZE 10 | 11 | TupleId = index of record within a page = tid 12 | 13 | RecordId = (PageId, TupleId) = rid 14 | 15 | recOffset = directory[tid] 16 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex03/withDict.c: -------------------------------------------------------------------------------- 1 | // insert into a page with fixed-size records 2 | // and distributed free space and slot bitmap 3 | 4 | // Assume the following definitions 5 | 6 | typedef ... Byte; // one-byte value 7 | typedef ... Count; // two-byte value 8 | 9 | #define PAGESIZE ... 10 | #define DICTSIZE ... 11 | 12 | #define MAXRECS (PAGESIZE-DICTSIZE)/rel.recSize 13 | 14 | typedef struct { 15 | Bit present[MAXRECS]; // bitmap 16 | Record data[1]; // start of tuples 17 | } Page; 18 | 19 | // Initialise Page data 20 | 21 | void initPage(Relation rel, PageId pid, Page *p) 22 | { 23 | // p is a pointer to a PAGESIZE buffer 24 | for (int i = 0; i < MAXRECS; i++) 25 | p->present[i] = 0; 26 | put_page(p, rel, pid); 27 | } 28 | 29 | // Add record into Page; return record ID 30 | 31 | RecordId insert_record(Relation rel, PageId pid, Record rec) 32 | { 33 | // get Page 34 | Page *p = get_page(rel, pid); 35 | // find a free slot 36 | int slot = -1; 37 | for (int i = 0; i < MAXRECS; i++) 38 | if (p->present[i] == 0) { 39 | slot = i; 40 | break; 41 | } 42 | } 43 | if (slot < 0) FAIL no room; 44 | Byte *location = &(p->data) + slot*rel.recSize; 45 | memcpy(location, r, rel.recSize); 46 | put_page(p, rel, pid); 47 | return (pid,slot); 48 | } 49 | 50 | // Delete record from Page; 51 | 52 | void delete_record(Relation rel, TupleId rid) 53 | { 54 | (pid,tid) = rid; 55 | Page *p = get_page(rel, pid); 56 | p->present[i] = 0; 57 | put_page(p, rel, pid); 58 | } 59 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex03/withXmax.c: -------------------------------------------------------------------------------- 1 | // insert into a page with fixed-size records 2 | // and distributed free space and MVCC 3 | 4 | // Assume the following definitions 5 | 6 | typedef ... Byte; // one-byte value 7 | typedef ... Count; // two-byte value 8 | 9 | #define PAGESIZE ... 10 | 11 | #define MAXRECS (PAGSIZE/rel.recSize) 12 | 13 | typedef struct { 14 | Record data[1]; // start of tuples 15 | } Page; 16 | 17 | // Initialise Page data 18 | 19 | void initPage(Relation rel, PageId pid, Page *p) 20 | { 21 | Record *r; 22 | for (int i = 0; i < MAXRECS; i++) { 23 | r = &(p->data) + i*rel.recSize; 24 | r->xmax = 0; 25 | } 26 | put_page(p, rel, pid); 27 | } 28 | 29 | // Add record into Page; return record ID 30 | 31 | RecordId insert_record(Relation rel, PageId pid, Record rec) 32 | { 33 | // get Page 34 | Page *p = get_page(rel, pid); 35 | // find a free slot 36 | int slot = -1; 37 | for (int i = 0; i < MAXRECS; i++) 38 | Record *r = &(p->data) + i*rel.recSize; 39 | if (r->xmax == 0) { 40 | slot = i; 41 | break; 42 | } 43 | } 44 | if (slot < 0) FAIL no room; 45 | Byte *location = &(p->data) + slot*rel.recSize; 46 | memcpy(location, r, rel.recSize); 47 | put_page(p, rel, pid); 48 | return (pid,slot); 49 | } 50 | 51 | // Delete record from Page; 52 | 53 | void delete_record(Relation rel, TupleId rid) 54 | { 55 | (pid,tid) = rid; 56 | Page *p = get_page(rel, pid); 57 | Record *r = &(p->data) + tid*rel.recSize; 58 | r->xmax = currentTxId; 59 | put_page(p, rel, pid); 60 | } 61 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex04/insert1.c: -------------------------------------------------------------------------------- 1 | // Assume the following definitions 2 | 3 | typedef ... Byte; // one-byte value 4 | typedef ... Count; // two-byte value 5 | typedef ... Offset; // two-byte value 6 | 7 | #define PAGESIZE ... 8 | 9 | typedef struct { 10 | Offset freeTop; 11 | Count nrecs; 12 | Offset rec[1]; // start of directory 13 | // data space 14 | } Page; 15 | 16 | // Initialise Page data 17 | 18 | void initPage(Page *p, PageId pid) 19 | { 20 | p->nrecs = 0; 21 | p->freeTop = PAGESIZE-1; 22 | Byte *data; 23 | data = &(p->rec[0]); 24 | int nBytes = PAGESIZE - 2*sizeof(Byte2); 25 | for (int i = 0; i < nBytes; i++) data[i] = 0; 26 | put_page(p, pid); 27 | } 28 | 29 | // Add record into Page; return record index 30 | 31 | int insert(Page *p, Record *r) 32 | { 33 | // TODO 34 | // use top of free space 35 | // copy record data there 36 | // update directory, etc. 37 | } 38 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex04/insert2.c: -------------------------------------------------------------------------------- 1 | // Assume the following definitions 2 | 3 | typedef ... Byte; // one-byte value 4 | typedef ... Count; // two-byte value 5 | typedef ... Offset; // two-byte value 6 | 7 | #define PAGESIZE ... 8 | 9 | typedef struct { 10 | Offset freeTop; 11 | Count nrecs; 12 | Byte rec[1]; // beginning of directory 13 | } Page; 14 | 15 | typedef struct { 16 | Offset size; 17 | Offset next; 18 | } FreeChunk; 19 | 20 | // Initialise Page data 21 | 22 | void initPage(Page *p, PageId pid) 23 | { 24 | p->nrecs = 0; 25 | p->freeList = PAGESIZE-1; 26 | Byte *data; 27 | data = &(p->rec); 28 | int nBytes = PAGESIZE - 2*sizeof(Offset);; 29 | for (int i = 0; i < nBytes; i++) data[i] = 0; 30 | FreeChunk *free = p + PAGESIZE-1 - sizeof(FreeChunk); 31 | free->size = PAGESIZE-2*sizeof(Offset); 32 | free->next = 0; // not valid page offset 33 | put_page(p, pid); 34 | } 35 | 36 | // Add record into Page; return record index 37 | 38 | int insert(Page *p, Record *r) 39 | { 40 | // TODO 41 | // find free space for tuple 42 | // copy record data there 43 | // update directory, etc. 44 | } 45 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex05/spaceutil.txt: -------------------------------------------------------------------------------- 1 | c = average number of records per page 2 | 3 | Map of page structure 4 | 5 | 0 32 32+C X 1023 6 | | | | | | 7 | Header Directory FreeSpace Records ............. 8 | 9 | 10 | Assume that all records are average size ... 11 | 12 | (w:int,x:varchar(20),y:char(10),z:int) 13 | 14 | w = 4 bytes, x = 16 bytes (avg), 15 | y = 10 bytes + 2 bytes padding, z = 4 bytes 16 | 17 | R = average record size = Offsets + Data 18 | R = 4 + (4+16+(10+2)+4) = 40 bytes 19 | 20 | B = 1024, but we lose 32 bytes from header 21 | 22 | Freespace = 1024 - 32 = 992 23 | 24 | When we have N records in page 25 | * lose N bytes of Freespace to directory 26 | * records themselves occupy 40*N bytes 27 | 28 | So ... 40*N + N <= 992 => N = 24 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex06/Relation.txt: -------------------------------------------------------------------------------- 1 | typedef struct 2 | { 3 | table name 4 | attributes 5 | file names 6 | file descriptors 7 | } 8 | RelationData; 9 | 10 | typedef RelationData *Relation; 11 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex06/next_tuple.txt: -------------------------------------------------------------------------------- 1 | // Assuming functions ... 2 | // Page *get_page(rel,pid) 3 | // Record get_record(p,tid) 4 | // Tuple makeTuple(rel,rec) 5 | // int nTuples(p) 6 | // int nPages(rel) 7 | 8 | typedef struct { rel, ... } ScanData; 9 | typedef ScanData *Scan; 10 | 11 | Scan start_scan(Relation rel) 12 | { 13 | Scan new = malloc(ScanData); 14 | new->rel = rel; 15 | new->curPage = get_page(rel,0); 16 | new->curPID = 0; 17 | new->curTID = 0; 18 | return new; 19 | } 20 | 21 | Tuple next_tuple(Scan s) 22 | { 23 | if (s->curTID == nTuples(s->curPage)) { 24 | // finished cur page, get next 25 | if (s->curPID == nPages(s->rel)) 26 | return; 27 | s->curPID++; 28 | s->curPage = get_page(s->rel, s->curPID); 29 | s->curTID =0; 30 | } 31 | Record r = get_record(s->curPage, s->curTID); 32 | s->curTID++; 33 | return makeTuple(s->rel, r); 34 | } 35 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex07/costs.txt: -------------------------------------------------------------------------------- 1 | insert into Heap 2 | 3 | delete from Heap 4 | 5 | insert into Sorted 6 | 7 | delete from Sorted 8 | 9 | insert into Hashed 10 | 11 | delete from Hashed 12 | 13 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex08/field-desc.txt: -------------------------------------------------------------------------------- 1 | How big is a FieldDesc? 2 | 3 | 8KB pages 4 | 5 | Offsets 6 | ======= 7 | 8 | max offset = 8KB-1 9 | 10 | number of bits to represent all offsets = 13 (2^13=8K) 11 | 12 | 13 | Lengths 14 | ======= 15 | 16 | 17 | Types 18 | ===== 19 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex09/hash-cost.txt: -------------------------------------------------------------------------------- 1 | Search process for 2 | 3 | select * from R where k = 51; 4 | 5 | h = hash(51); 6 | p = readPage(h); 7 | for each tuple t in page p { 8 | if (t.k = 51) found match 9 | } 10 | for each overflow page ov of p { 11 | for each tuple t in page ov { 12 | if (t.k = 51) found match 13 | } 14 | } 15 | 16 | Best case = ? 17 | Worst case = ? 18 | Average case = ? 19 | 20 | 21 | 22 | search process for 23 | 24 | select * from R where k > 50; 25 | 26 | Hashing does not help; need to read everything 27 | 28 | All cases = b + b_Ov 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex09/sort-cost.txt: -------------------------------------------------------------------------------- 1 | 2 | tuples per page = c (determined from R,B,H,D) 3 | 4 | R*c <= (B - H - D), where D = c/8 5 | 6 | tuples must fit into "tuple_space" in page 7 | 8 | tuple_space = page_size - header_size - directory_size 9 | page_size = 4096 bytes 10 | header_size = 96 bytes 11 | directory_size = c bits = c/8 bytes 12 | 13 | when c = 64 14 | R*c = 3968 15 | tuple_space = 4096 - 96 - 64/8 = 3992 16 | 17 | (with a bit of wasted space ... 3992-3968 = 24 bytes) 18 | 19 | 20 | number of pages b = ceil(r/c) = ceil(2^20/2^6) = 2^14 = 16384 21 | 22 | 23 | 24 | 25 | total buffers = N = 9 26 | input buffers = n = 8 27 | 28 | first pass yields ceil(b/N) sorted "runs" 29 | 30 | ceil(b/N) = ceil(16384/9) = 1821 31 | 32 | size of runs: 33 | after pass 0 = 9 34 | after pass 1 = 8*9 = 72 35 | after pass 2 = 8*72 = 576 36 | after pass 3 = 8*576 = 4608 37 | after pass 4 = 8*4608 = more than 16384 => all sorted 38 | 39 | initial sorting pass + 4 merging passes = 5 passes 40 | 41 | Cost = pages read/written = 5 * 2 * 2^14 42 | 43 | 44 | 45 | 46 | 47 | total buffers = N = 33 48 | input buffers = n = 32 49 | 50 | first pass yields ceil(b/N) sorted "runs" 51 | 52 | ceil(b/N) = ceil(16384/33) = 497 53 | 54 | size of runs: 55 | after pass 0 = 33 56 | after pass 1 = 32*33 = 1056 57 | after pass 2 = 32*1056 = more than 16384 => all sorted 58 | 59 | initial sorting pass + 2 merging passes = 3 passes 60 | 61 | Cost = pages read/written = 3 * 2 * 2^14 62 | 63 | 64 | 65 | 66 | 67 | total buffers = N = 257 68 | input buffers = n = 256 69 | 70 | first pass yields ceil(b/N) sorted "runs" 71 | 72 | ceil(b/N) = ceil(16384/257) = 64 73 | 74 | size of runs: 75 | after pass 0 = 257 76 | after pass 1 = 256*257 = more than 16384 => all sorted 77 | 78 | initial sorting pass + 1 merging passes = 2 passes 79 | 80 | Cost = pages read/written = 2 * 2 * 2^14 81 | 82 | 83 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex1/get_record.txt: -------------------------------------------------------------------------------- 1 | // using: get_page(), get_record(), ... 2 | 3 | Record get_record(Relation rel, RecordId rid) 4 | { 5 | (pid, tid) = rid 6 | Page *buf = get_page(rel, pid) 7 | Record rec = get_record(buf, tid) 8 | return rec 9 | } 10 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex10/copy-cost.txt: -------------------------------------------------------------------------------- 1 | heap -> heap 2 | 3 | b_in + b_out, where b_out <= b_in 4 | 5 | sorted -> heap 6 | 7 | b_in + b_out, where b_out <= b_in 8 | 9 | heap -> sorted 10 | 11 | b_in + r_in*Cost(insert) (naive) 12 | 13 | Cost(sort(infile)) + b_out (sensible) 14 | 15 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex11/visibility.txt: -------------------------------------------------------------------------------- 1 | Visibility of tuples to PostgreSQL transactions (tx) is 2 | determined by Transaction, Command and Tuple IDs ... 3 | 4 | Each Transaction is allocated a global unique txID 5 | 6 | Transaction = sequence of Commands C_1, C_2, C_3 7 | Command = one SQL statement 8 | 9 | Each Command is allocated a cmdID, unique within current tx 10 | 11 | Each tuple contains: 12 | * xmin = transaction ID of tx that created the tuple 13 | * xmax = transaction ID of tx that deleted the tuple 14 | * cmin = command ID of cmd that created the tuple 15 | * cmax = command ID of cmd that deleted the tuple 16 | * ctid = Tuple ID of newer version of this tuple 17 | 18 | Each command knows: 19 | * Tc = transaction ID of current tx 20 | * Cc = command ID of current cmd 21 | 22 | 23 | 24 | 25 | 26 | Simplified view of "live" tuples ... 27 | 28 | * xmin < Tc && xmax == NULL 29 | * xmin == Tc && cmin < Cc 30 | * xmax == Tc && cmax > Cc 31 | 32 | Simplified view of "dead" tuples ... 33 | 34 | * xmax != NULL && xmax < Tc 35 | * xmax == Tc && cmax < Cc 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | More realistic view of tuple visibility includes Command ... 44 | 45 | Possible states for tuples: 46 | 47 | * visible, newly-created, updated, deleted 48 | 49 | 50 | PostgreSQL recognises that a tuple is deleted ... 51 | 52 | * xmax == Tc and cmax < Cc, or 53 | * xmax < Tc and xmax is committed 54 | 55 | PostgreSQL recognises that a tuple is visible ... 56 | 57 | * not deleted, and 58 | * created by an earlier command in Tc, or 59 | * created by an already-committed transaction 60 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex2/schemas.txt: -------------------------------------------------------------------------------- 1 | Assume: a tuple a byte sequence (of data), preceded 2 | by a header containing e.g field offsets 3 | 4 | -- fixed-size tuples 5 | -- size = 4 + 8 + 4 + 4 + 8 = 28 bytes + header 6 | 7 | create table Course ( 8 | id integer, -- 4 bytes 9 | code char(8), -- 8 bytes, e.g. COMP9315 10 | uoc integer, -- 4 bytes 11 | term char(4), -- 4 bytes e.g. "18s2" "19T1" ... 12 | avgmark float, -- 8 bytes 13 | primary key (id) 14 | ); 15 | 16 | 17 | -- variable-sized tuples 18 | -- tuple = (header, data) 19 | -- data size = 4 + 8 + ??? + 4 + 8 = 24 + ??? bytes + header 20 | 21 | create table Course ( 22 | id integer, -- 4 bytes 23 | code char(8), -- 8 bytes, e.g. COMP9315 24 | title varchar(100), -- ??? bytes 25 | uoc integer, -- 4 bytes 26 | avgmark float, -- 8 bytes 27 | primary key (id) 28 | ); 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex2/tsize.sql: -------------------------------------------------------------------------------- 1 | drop type if exists SchemaTuple cascade; 2 | create type SchemaTuple as ("table" text, "size" text, "attributes" text); 3 | 4 | create or replace function schema1() returns setof SchemaTuple 5 | as $$ 6 | declare 7 | rec record; 8 | rel text := ''; 9 | attr text := ''; 10 | attrs text := ''; 11 | out SchemaTuple; 12 | len integer := 0; 13 | size integer := 0; 14 | isvar boolean := false; 15 | begin 16 | for rec in 17 | select r.relname, a.attname, t.typname, a.attlen, a.atttypmod 18 | from pg_class r 19 | join pg_namespace n on (r.relnamespace = n.oid) 20 | join pg_attribute a on (a.attrelid = r.oid) 21 | join pg_type t on (a.atttypid = t.oid) 22 | where r.relkind='r' 23 | and n.nspname = 'public' 24 | and attnum > 0 25 | order by relname,attnum 26 | loop 27 | if (rec.relname <> rel) then 28 | if (rel <> '') then 29 | out."table" := rel; 30 | out.attributes := attrs; 31 | out.size := size::text; 32 | if (isvar) then 33 | out.size := out.size||'+?'; 34 | end if; 35 | return next out; 36 | end if; 37 | rel := rec.relname; 38 | attrs := ''; 39 | len := 0; 40 | size := 0; 41 | isvar := false; 42 | end if; 43 | if (rec.atttypmod < 0) then 44 | size := size + rec.attlen; 45 | else 46 | end if; 47 | if (attrs <> '') then 48 | attrs := attrs || ', '; 49 | len := len + 2; 50 | end if; 51 | if (rec.typname = 'varchar') then 52 | isvar := true; 53 | rec.typname := 'varchar('||(rec.atttypmod-4)||')'; 54 | elsif (rec.typname = 'bpchar') then 55 | size := size + rec.attypmod; 56 | rec.typname := 'char('||(rec.atttypmod-4)||')'; 57 | elsif (rec.typname = 'int4') then 58 | rec.typname := 'integer'; 59 | elsif (rec.typname = 'float8') then 60 | rec.typname := 'float'; 61 | end if; 62 | attr := rec.attname||':'||rec.typname; 63 | if (len + length(attr) > 50) then 64 | attrs := attrs || E'\n'; 65 | len := 0; 66 | end if; 67 | attrs := attrs || attr; 68 | len := len + length(attr); 69 | end loop; 70 | -- deal with last table 71 | if (rel <> '') then 72 | out."table" := rel; 73 | out.attributes := attrs; 74 | out.size := size::text; 75 | if (isvar) then 76 | out.size := out.size||'+?'; 77 | end if; 78 | return next out; 79 | end if; 80 | end; 81 | $$ language plpgsql; 82 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex3/terminology.txt: -------------------------------------------------------------------------------- 1 | Record = sequence of bytes stored on disk 2 | 3 | Tuple = "interpretable" version of a Record in memory 4 | 5 | Page = copy of page from file on disk 6 | 7 | PageId = index of Page within file = pid 8 | 9 | pageOffset = pid * PAGESIZE 10 | 11 | TupleId = index of record within a page = tid 12 | 13 | RecordId = (PageId, TupleId) = rid 14 | 15 | recOffset = directory[tid] 16 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex3/withDict.c: -------------------------------------------------------------------------------- 1 | // insert into a page with fixed-size records 2 | // and distributed free space and slot bitmap 3 | 4 | // Assume the following definitions 5 | 6 | typedef ... Byte; // one-byte value 7 | typedef ... Count; // two-byte value 8 | 9 | #define PAGESIZE ... 10 | #define DICTSIZE ... 11 | 12 | #define MAXRECS (PAGESIZE-DICTSIZE)/rel.recSize 13 | 14 | typedef struct { 15 | Bit present[MAXRECS]; // bitmap 16 | Record data[1]; // start of tuples 17 | } Page; 18 | 19 | // Initialise Page data 20 | 21 | void initPage(Relation rel, PageId pid, Page *p) 22 | { 23 | // p is a pointer to a PAGESIZE buffer 24 | for (int i = 0; i < MAXRECS; i++) 25 | p->present[i] = 0; 26 | put_page(p, rel, pid); 27 | } 28 | 29 | // Add record into Page; return record ID 30 | 31 | RecordId insert_record(Relation rel, PageId pid, Record rec) 32 | { 33 | // get Page 34 | Page *p = get_page(rel, pid); 35 | // find a free slot 36 | int slot = -1; 37 | for (int i = 0; i < MAXRECS; i++) 38 | if (p->present[i] == 0) { 39 | slot = i; 40 | break; 41 | } 42 | } 43 | if (slot < 0) FAIL no room; 44 | Byte *location = &(p->data) + slot*rel.recSize; 45 | memcpy(location, r, rel.recSize); 46 | put_page(p, rel, pid); 47 | return (pid,slot); 48 | } 49 | 50 | // Delete record from Page; 51 | 52 | void delete_record(Relation rel, TupleId rid) 53 | { 54 | (pid,tid) = rid; 55 | Page *p = get_page(rel, pid); 56 | p->present[i] = 0; 57 | put_page(p, rel, pid); 58 | } 59 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex3/withXmax.c: -------------------------------------------------------------------------------- 1 | // insert into a page with fixed-size records 2 | // and distributed free space and MVCC 3 | 4 | // Assume the following definitions 5 | 6 | typedef ... Byte; // one-byte value 7 | typedef ... Count; // two-byte value 8 | 9 | #define PAGESIZE ... 10 | 11 | #define MAXRECS (PAGSIZE/rel.recSize) 12 | 13 | typedef struct { 14 | Record data[1]; // start of tuples 15 | } Page; 16 | 17 | // Initialise Page data 18 | 19 | void initPage(Relation rel, PageId pid, Page *p) 20 | { 21 | Record *r; 22 | for (int i = 0; i < MAXRECS; i++) { 23 | r = &(p->data) + i*rel.recSize; 24 | r->xmax = 0; 25 | } 26 | put_page(p, rel, pid); 27 | } 28 | 29 | // Add record into Page; return record ID 30 | 31 | RecordId insert_record(Relation rel, PageId pid, Record rec) 32 | { 33 | // get Page 34 | Page *p = get_page(rel, pid); 35 | // find a free slot 36 | int slot = -1; 37 | for (int i = 0; i < MAXRECS; i++) 38 | Record *r = &(p->data) + i*rel.recSize; 39 | if (r->xmax == 0) { 40 | slot = i; 41 | break; 42 | } 43 | } 44 | if (slot < 0) FAIL no room; 45 | Byte *location = &(p->data) + slot*rel.recSize; 46 | memcpy(location, r, rel.recSize); 47 | put_page(p, rel, pid); 48 | return (pid,slot); 49 | } 50 | 51 | // Delete record from Page; 52 | 53 | void delete_record(Relation rel, TupleId rid) 54 | { 55 | (pid,tid) = rid; 56 | Page *p = get_page(rel, pid); 57 | Record *r = &(p->data) + tid*rel.recSize; 58 | r->xmax = currentTxId; 59 | put_page(p, rel, pid); 60 | } 61 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex4/insert1.c: -------------------------------------------------------------------------------- 1 | // Assume the following definitions 2 | 3 | typedef ... Byte; // one-byte value 4 | typedef ... Count; // two-byte value 5 | typedef ... Offset; // two-byte value 6 | 7 | #define PAGESIZE ... 8 | 9 | typedef struct { 10 | Offset freeTop; 11 | Count nrecs; 12 | Offset rec[1]; // start of directory 13 | // data space 14 | } Page; 15 | 16 | // Initialise Page data 17 | 18 | void initPage(Page *p, PageId pid) 19 | { 20 | p->nrecs = 0; 21 | p->freeTop = PAGESIZE-1; 22 | Byte *data; 23 | data = &(p->rec[0]); 24 | int nBytes = PAGESIZE - 2*sizeof(Byte2); 25 | for (int i = 0; i < nBytes; i++) data[i] = 0; 26 | put_page(p, pid); 27 | } 28 | 29 | // Add record into Page; return record index 30 | 31 | int insert(Page *p, Record *r) 32 | { 33 | // TODO 34 | // use top of free space 35 | // copy record data there 36 | // update directory, etc. 37 | } 38 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex4/insert2.c: -------------------------------------------------------------------------------- 1 | // Assume the following definitions 2 | 3 | typedef ... Byte; // one-byte value 4 | typedef ... Count; // two-byte value 5 | typedef ... Offset; // two-byte value 6 | 7 | #define PAGESIZE ... 8 | 9 | typedef struct { 10 | Offset freeTop; 11 | Count nrecs; 12 | Byte rec[1]; // beginning of directory 13 | } Page; 14 | 15 | typedef struct { 16 | Offset size; 17 | Offset next; 18 | } FreeChunk; 19 | 20 | // Initialise Page data 21 | 22 | void initPage(Page *p, PageId pid) 23 | { 24 | p->nrecs = 0; 25 | p->freeList = PAGESIZE-1; 26 | Byte *data; 27 | data = &(p->rec); 28 | int nBytes = PAGESIZE - 2*sizeof(Offset);; 29 | for (int i = 0; i < nBytes; i++) data[i] = 0; 30 | FreeChunk *free = p + PAGESIZE-1 - sizeof(FreeChunk); 31 | free->size = PAGESIZE-2*sizeof(Offset); 32 | free->next = 0; // not valid page offset 33 | put_page(p, pid); 34 | } 35 | 36 | // Add record into Page; return record index 37 | 38 | int insert(Page *p, Record *r) 39 | { 40 | // TODO 41 | // find free space for tuple 42 | // copy record data there 43 | // update directory, etc. 44 | } 45 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/Ex5/spaceutil.txt: -------------------------------------------------------------------------------- 1 | c = average number of records per page 2 | 3 | Map of page structure 4 | 5 | 0 32 32+C X 1023 6 | | | | | | 7 | Header Directory FreeSpace Records ............. 8 | 9 | 10 | Assume that all records are average size ... 11 | 12 | (w:int,x:varchar(20),y:char(10),z:int) 13 | 14 | w = 4 bytes, x = 16 bytes (avg), 15 | y = 10 bytes + 2 bytes padding, z = 4 bytes 16 | 17 | R = average record size = Offsets + Data 18 | R = 4 + (4+16+(10+2)+4) = 40 bytes 19 | 20 | B = 1024, but we lose 32 bytes from header 21 | 22 | Freespace = 1024 - 32 = 992 23 | 24 | When we have N records in page 25 | * lose N bytes of Freespace to directory 26 | * records themselves occupy 40*N bytes 27 | 28 | So ... 40*N + N <= 992 => N = 24 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/pages/page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lecture Exercises/week03/pages/page.png -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/pages/spaceutil.txt: -------------------------------------------------------------------------------- 1 | C = average number of records per page 2 | 3 | Map of page structure 4 | 5 | 0 32 32+C X 1023 6 | | | | | | 7 | Header Directory FreeSpace Records ............. 8 | 9 | 10 | Assume that all records are average size ... 11 | 12 | (a:int,b:varchar(20),c:char(10),d:int) 13 | 14 | a = 4 bytes, b = 16 bytes (avg), 15 | c = 10 bytes + 2 bytes padding, d = 4 bytes 16 | 17 | R = average record size = Offsets + Data 18 | R = 4 + (4+16+(10+2)+4) = 40 bytes 19 | 20 | B = 1024, but we lose 32 bytes from header 21 | 22 | Freespace = 1024 - 32 = 992 23 | 24 | When we have N records in page 25 | * lose N bytes of Freespace to directory 26 | * records themselves occupy 40*N bytes 27 | 28 | So ... 40*N + N <= 992 => N = floor(992/41) = 24 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/schema.sql: -------------------------------------------------------------------------------- 1 | create table People ( 2 | id integer, 3 | ptype varchar(10), 4 | title varchar(5), 5 | family varchar(40), 6 | given varchar(50), 7 | street varchar(40), 8 | suburb varchar(30), 9 | pcode integer, 10 | gender char(1) check (gender in ('m','f')), 11 | birthday date, 12 | country char(3), 13 | primary key (id) 14 | ); 15 | 16 | create table Courses ( 17 | id integer, 18 | code char(8) check (code ~ '[A-Z]{4}[0-9]{4}'), 19 | title varchar(50), 20 | uoc integer check (uoc > 0), 21 | convenor integer references People(id), 22 | primary key (id) 23 | ); 24 | 25 | create table Enrolments ( 26 | course integer references Courses(id), 27 | student integer references People(id), 28 | mark integer check (mark between 0 and 100), 29 | grade char(2) check (grade in ('HD','DN','CR','PS','FL')), 30 | primary key (course,student) 31 | ); 32 | 33 | create table Items ( 34 | id integer, 35 | course integer references Courses(id), 36 | name varchar(20), 37 | maxMark integer check (maxMark > 0), 38 | primary key (id) 39 | ); 40 | 41 | create table Assessments ( 42 | item integer references Items(id), 43 | student integer references People(id), 44 | mark integer check (mark >= 0), 45 | primary key (item,student) 46 | ); 47 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week03/tuples/makeTuple2.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | ushort nfields; // # fields 3 | ushort dataStart; // 4 | FieldDesc fields[]; // field descriptions 5 | // Record data; 6 | } Tuple; 7 | 8 | Tuple mkTuple(RelnDesc schema, Record record) 9 | { 10 | int i, pos = 0; 11 | int size = sizeof(Tuple) + 12 | nfields*sizeof(FieldDesc); 13 | Tuple *t = malloc(size+recSize(record)); 14 | t->nfields = schema.nfields; 15 | for (i=0; i < schema.nfields; i++) { 16 | int len = record[pos++]; 17 | t->fields[i].offset = pos; 18 | t->fields[i].length = len; 19 | // could add checking for over-length fields, etc. 20 | t->fields[i].type = schema.fields[i].type; 21 | pos += length; 22 | } 23 | t->dataStart = size; 24 | return t; 25 | } 26 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex01/copy-cost: -------------------------------------------------------------------------------- 1 | heap -> heap 2 | - scan input page-by-page, write to output 3 | - maybe some reduction in size if input had gaps 4 | 5 | b_in + b_out, where b_out <= b_in 6 | 7 | 8 | sorted -> heap 9 | - same as above 10 | 11 | b_in + b_out, where b_out <= b_in 12 | 13 | 14 | heap -> sorted 15 | - two possibilities: 16 | (1) maintain order on each insert 17 | (2) make a simple copy as above and then Sort 18 | 19 | b_in + r_in*Cost(insert) (1) 20 | 21 | Cost(sort(infile)) + b_out (2) 22 | 23 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex02/sort-cost: -------------------------------------------------------------------------------- 1 | 2 | tuples per page = c (determined from R,B,H,D) 3 | 4 | R*c <= (B - H - D), where D = c/8 5 | 6 | tuples must fit into "tuple_space" in page 7 | 8 | tuple_space = page_size - header_size - directory_size 9 | page_size = 4096 bytes 10 | header_size = 96 bytes 11 | directory_size = c bits = c/8 bytes 12 | 13 | when c = 64 14 | R*c = 3968 15 | tuple_space = 4096 - 96 - 64/8 = 3992 16 | 17 | (with a bit of wasted space ... 3992-3968 = 24 bytes) 18 | 19 | 20 | number of pages b = ceil(r/c) = ceil(2^20/2^6) = 2^14 = 16384 21 | 22 | 23 | 24 | 25 | total buffers = N = 9 26 | input buffers = n = 8 27 | 28 | first pass yields ceil(b/N) sorted "runs" 29 | 30 | ceil(b/N) = ceil(16384/9) = 1821 31 | 32 | size of runs: 33 | after pass 0 = 9 34 | after pass 1 = 8*9 = 72 35 | after pass 2 = 8*72 = 576 36 | after pass 3 = 8*576 = 4608 37 | after pass 4 = 8*4608 = more than 16384 => all sorted 38 | 39 | initial sorting pass + 4 merging passes = 5 passes 40 | 41 | Cost = pages read/written = 5 * 2 * 2^14 42 | 43 | 44 | 45 | 46 | 47 | total buffers = N = 33 48 | input buffers = n = 32 49 | 50 | first pass yields ceil(b/N) sorted "runs" 51 | 52 | ceil(b/N) = ceil(16384/33) = 497 53 | 54 | size of runs: 55 | after pass 0 = 33 56 | after pass 1 = 32*33 = 1056 57 | after pass 2 = 32*1056 = more than 16384 => all sorted 58 | 59 | initial sorting pass + 2 merging passes = 3 passes 60 | 61 | Cost = pages read/written = 3 * 2 * 2^14 62 | 63 | 64 | 65 | 66 | 67 | total buffers = N = 257 68 | input buffers = n = 256 69 | 70 | first pass yields ceil(b/N) sorted "runs" 71 | 72 | ceil(b/N) = ceil(16384/257) = 64 73 | 74 | size of runs: 75 | after pass 0 = 257 76 | after pass 1 = 256*257 = more than 16384 => all sorted 77 | 78 | initial sorting pass + 1 merging passes = 2 passes 79 | 80 | Cost = pages read/written = 2 * 2 * 2^14 81 | 82 | 83 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex03/sort-proj-cost: -------------------------------------------------------------------------------- 1 | R(x,y,z) 2 | Page 0: (1,1,'a') (11,2,'a') (3,3,'c') 3 | Page 1: (13,5,'c') (2,6,'b') (9,4,'a') 4 | Page 2: (6,2,'a') (17,7,'a') (7,3,'b') 5 | Page 3: (14,6,'a') (8,4,'c') (5,2,'b') 6 | Page 4: (10,1,'b') (15,5,'b') (12,6,'b') 7 | Page 5: (4,2,'a') (16,9,'c') (18,8,'c') 8 | 9 | Temp(y) 10 | Page 0: (1) (2) (3) (5) (6) (4) -> (1) (2) (3) (4) (5) (6) 11 | Page 1: (2) (7) (3) (6) (4) (2) -> (2) (2) (3) (4) (6) (7) 12 | Page 2: (1) (5) (6) (2) (9) (8) -> (1) (2) (5) (6) (8) (9) 13 | 14 | Sort .... 15 | 16 | Temp'(y) 17 | Page 0: (1) (1) (2) (2) (2) (2) 18 | Page 1: (3) (3) (4) (4) (5) (5) 19 | Page 2: (6) (6) (6) (7) (8) (9) 20 | 21 | Result(y) 22 | Page 0: (1) (2) (3) (4) (5) (6) 23 | Page 1: (7) (8) (9) 24 | 25 | Cost = read R + write Temp + sort Temp + scan Temp + write Result 26 | = b_R + b_Temp + ~2*b_Temp*log_N(b_Temp) + b_Temp + b_Result 27 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex04/hash-proj-cost: -------------------------------------------------------------------------------- 1 | Inputs (k values): 2 | 3 | 1 2 3 5 6 4 2 7 3 6 4 2 1 5 6 2 9 8 4 | 1 2 3 5 6 4 2 7 3 6 4 2 1 5 6 2 9 8 5 | 6 | 7 | Buffers: 4 total, 1 input, 3 output 8 | 9 | Partition h1(k) = k % 3 10 | 11 | P0 (via Buf[0]) 3 6 3 6 6 9 3 6 3 6 6 9 12 | 13 | P1 (via Buf[1]) 1 4 7 4 1 1 4 7 4 1 14 | 15 | P2 (via Buf[2]) 2 5 2 2 5 2 8 2 5 2 2 5 2 8 16 | 17 | 18 | Duplicate elim h2(k) = (k % 4) % 3 19 | 20 | 21 | P0 3 6 3 6 6 9 3 6 3 6 6 9 22 | 23 | B0 3 24 | 25 | B1 9 26 | 27 | B2 6 28 | 29 | --- 30 | 31 | P1 1 4 7 4 1 1 4 7 4 1 32 | 33 | B0 4 7 34 | 35 | B1 1 36 | 37 | B2 ? 38 | 39 | --- 40 | h2(k) = (k % 4) % 3 41 | 42 | P2 2 5 2 2 5 2 8 2 5 2 2 5 2 8 43 | 44 | B0 8 45 | 46 | B1 5 47 | 48 | B2 2 49 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex05/query-types: -------------------------------------------------------------------------------- 1 | create table Courses ( 2 | id integer primary key, 3 | code char(8), -- e.g. 'COMP9315' 4 | title text, -- e.g. 'Computing 1' 5 | year integer, -- e.g. 2000..2016 6 | convenor integer references Staff(id), 7 | constraint once_per_year unique (code,year) 8 | ); 9 | 10 | 1-d one 11 | select * from Courses where id=1234 12 | #solutions 0 or 1 13 | 14 | n-d one 15 | select * from Courses where code='COMP9315' and year=2015 16 | #solutions 0 17 | 18 | n-d pmr 19 | select * from Courses where code='COMP9315' and convenor=Johns 20 | #solutions ~5 21 | 22 | 1-d pmr 23 | select * from Courses where code='COMP3311' 24 | #solutions 17 25 | select * from Courses where convenor=JohnsID 26 | #solutions 34 27 | select * from Courses where year=2016 28 | #solutions ~4000 29 | 30 | 1-d range 31 | select * from Courses where year >= 2010 and year <= 2016 32 | #solutions ~4000*14 33 | 34 | n-d range 35 | select * from Courses 36 | where convenor > JohnsID and year between 2010 and 2015 37 | #solutions ?? (x*6 where x is hard to determine ... 100's?) 38 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex06/heap-deletion: -------------------------------------------------------------------------------- 1 | Employees table with b = 100, b_q2 = 3, b_q3 = 20 2 | Table not sorted on any attributes (e.g. hashed) 3 | 4 | q1: delete from Employees where id = 12345 5 | 6 | Cost = Cost_one + 1 write 7 | Best = 1*reads + 1*writes 8 | Worst = b*reads + 1*writes 9 | 10 | 11 | q2: delete from Employees where dept = 'Marketing' 12 | 13 | Cost = Cost_pmr + b_q2*writes 14 | All = b*reads + b_q2*writes 15 | 16 | 17 | q3: delete from Employees where 40 <= age and age < 50 18 | 19 | Cost = Cost_range + b_q3*writes 20 | All = b*reads + b_q3*writes 21 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex07/sorted-search: -------------------------------------------------------------------------------- 1 | File: b=16, pages = 0..15 2 | 3 | ---------- 4 | 5 | select * from R where k = 24 6 | 7 | lo=0, hi=4, mid= ? 8 | searchBucket(?) -> (null,min,max) 9 | 10 | ---------- 11 | 12 | select * from R where k = 3 13 | 14 | lo=0, hi=4, mid= ? 15 | searchBucket(?) -> (null,min,max) 16 | 17 | ---------- 18 | 19 | select * from R where k = 14 20 | 21 | lo=0, hi=4, mid= ? 22 | searchBucket(?) -> (null,min,max) 23 | 24 | ---------- 25 | 26 | select max(k) from R 27 | 28 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex08/optimisation: -------------------------------------------------------------------------------- 1 | Optimising binary search in sorted file 2 | 3 | Approach #1 4 | 5 | - store min,max values for each *bucket* in data page 6 | - avoids need to traverse overflow list if key not in bucket 7 | - disadvantage: may need to write data + overflow if insert 8 | new tuple into overflow page 9 | 10 | Approach #2 11 | 12 | - store list of (pid,min,max) values in header page 13 | - would allow us to find relevant bucket with 1 page read 14 | - only then would we need to read data+overflow pages 15 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex09/static-hash: -------------------------------------------------------------------------------- 1 | k hash(k) k hash(k) k hash(k) k hash(k) 2 | a 10001 g 00000 m 11001 s 01110 3 | b 11010 h 00000 n 01000 t 10011 4 | c 01111 i 10010 o 00110 u 00010 5 | d 01111 j 10110 p 11101 v 11111 6 | e 01100 k 00101 q 00010 w 10000 7 | f 00010 l 00101 r 00000 x 00111 8 | z 00010 9 | 10 | b = 4, d = 2, c = 3 11 | converting hash(k) to page ... use bottom two bits 12 | 13 | Page Data Overflow 14 | 15 | [0] e,g,h -> n,r,w 16 | 17 | [1] a,k,l -> m,p 18 | 19 | [2] b,f,i -> j,o,q -> s,u 20 | 21 | [3] c,d,t -> v,x 22 | 23 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -Werror 3 | 4 | all: s h 5 | 6 | s : s.o showBits.o bits.o 7 | gcc -o s s.o showBits.o bits.o 8 | 9 | h : h.o hash.o showBits.o bits.o 10 | gcc -o h h.o hash.o showBits.o bits.o 11 | 12 | clean: 13 | rm -f s h *.o core 14 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/bits.c: -------------------------------------------------------------------------------- 1 | // Extract d bits from uint32 2 | // if d +ve, get low-order bits 3 | // if d -ve, get high-order bits 4 | 5 | #include 6 | #include 7 | #include "bits.h" 8 | 9 | uint32 bits(int d, uint32 val) 10 | { 11 | assert(d >= -32 && d <= 32); 12 | uint32 mask; 13 | char buf[33]; 14 | 15 | if (d > 0) { 16 | mask = (0x1 << d) - 1; 17 | printf("Mask = %s\n",showBits(mask,buf)); 18 | return (val & mask); 19 | } 20 | else if (d < 0) { 21 | d = 0-d; 22 | mask = ((0x1 << d) - 1) << (32-d); 23 | printf("Mask = %s\n",showBits(mask,buf)); 24 | return ((val & mask) >> (32-d)); 25 | } 26 | else 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/bits.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint32; 2 | 3 | uint32 hash_any(unsigned char *, int); 4 | 5 | char *showBits(uint32, char *); 6 | 7 | uint32 bits(int d, uint32 val); 8 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/bits.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lecture Exercises/week04/Ex10/bits.o -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lecture Exercises/week04/Ex10/h -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/h.c: -------------------------------------------------------------------------------- 1 | #include "bits.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define NBITS 32 7 | #define NCHARS (NBITS+1) 8 | 9 | int main(int argc, char **argv) 10 | { 11 | uint32 hashVal, less; 12 | int n; 13 | char a[NCHARS], b[NCHARS]; 14 | 15 | if (argc < 2) { 16 | fprintf(stderr,"Usage: %s keyVal nbits\n",argv[0]); 17 | exit(1); 18 | } 19 | n = (argc < 3) ? 32 : atoi(argv[2]); 20 | if (n == 0) n = 32; 21 | 22 | printf("key = %s\n", argv[1]); 23 | hashVal = hash_any((unsigned char *)argv[1], strlen(argv[1])); 24 | printf("hash = %s\n", showBits(hashVal,a)); 25 | less = bits(n, hashVal); 26 | printf("bits = %s\n", showBits(less,b)); 27 | exit(0); 28 | } 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/h.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lecture Exercises/week04/Ex10/h.o -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/hash.c: -------------------------------------------------------------------------------- 1 | #include "bits.h" 2 | 3 | #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) 4 | 5 | #define mix(a,b,c) \ 6 | { \ 7 | a -= c; a ^= rot(c, 4); c += b; \ 8 | b -= a; b ^= rot(a, 6); a += c; \ 9 | c -= b; c ^= rot(b, 8); b += a; \ 10 | a -= c; a ^= rot(c,16); c += b; \ 11 | b -= a; b ^= rot(a,19); a += c; \ 12 | c -= b; c ^= rot(b, 4); b += a; \ 13 | } 14 | 15 | #define final(a,b,c) \ 16 | { \ 17 | c ^= b; c -= rot(b,14); \ 18 | a ^= c; a -= rot(c,11); \ 19 | b ^= a; b -= rot(a,25); \ 20 | c ^= b; c -= rot(b,16); \ 21 | a ^= c; a -= rot(c, 4); \ 22 | b ^= a; b -= rot(a,14); \ 23 | c ^= b; c -= rot(b,24); \ 24 | } 25 | 26 | uint32 27 | hash_any(unsigned char *k, int keylen) 28 | { 29 | uint32 a, b, c, len; 30 | /* set up the internal state */ 31 | len = keylen; 32 | a = b = 0x9e3779b9; 33 | c = 3923095; 34 | 35 | /* handle most of the key */ 36 | while (len >= 12) 37 | { 38 | #ifdef WORDS_BIGENDIAN 39 | a += (k[3] + ((uint32) k[2] << 8) + ((uint32) k[1] << 16) + ((uint32) k[0] << 24)); 40 | b += (k[7] + ((uint32) k[6] << 8) + ((uint32) k[5] << 16) + ((uint32) k[4] << 24)); 41 | c += (k[11] + ((uint32) k[10] << 8) + ((uint32) k[9] << 16) + ((uint32) k[8] << 24)); 42 | #else /* !WORDS_BIGENDIAN */ 43 | a += (k[0] + ((uint32) k[1] << 8) + ((uint32) k[2] << 16) + ((uint32) k[3] << 24)); 44 | b += (k[4] + ((uint32) k[5] << 8) + ((uint32) k[6] << 16) + ((uint32) k[7] << 24)); 45 | c += (k[8] + ((uint32) k[9] << 8) + ((uint32) k[10] << 16) + ((uint32) k[11] << 24)); 46 | #endif /* WORDS_BIGENDIAN */ 47 | mix(a, b, c); 48 | k += 12; 49 | len -= 12; 50 | } 51 | 52 | /* handle the last 11 bytes */ 53 | #ifdef WORDS_BIGENDIAN 54 | switch (len) /* all the case statements fall through */ 55 | { 56 | case 11: 57 | c += ((uint32) k[10] << 8); 58 | case 10: 59 | c += ((uint32) k[9] << 16); 60 | case 9: 61 | c += ((uint32) k[8] << 24); 62 | /* the lowest byte of c is reserved for the length */ 63 | case 8: 64 | b += k[7]; 65 | case 7: 66 | b += ((uint32) k[6] << 8); 67 | case 6: 68 | b += ((uint32) k[5] << 16); 69 | case 5: 70 | b += ((uint32) k[4] << 24); 71 | case 4: 72 | a += k[3]; 73 | case 3: 74 | a += ((uint32) k[2] << 8); 75 | case 2: 76 | a += ((uint32) k[1] << 16); 77 | case 1: 78 | a += ((uint32) k[0] << 24); 79 | /* case 0: nothing left to add */ 80 | } 81 | #else /* !WORDS_BIGENDIAN */ 82 | switch (len) /* all the case statements fall through */ 83 | { 84 | case 11: 85 | c += ((uint32) k[10] << 24); 86 | case 10: 87 | c += ((uint32) k[9] << 16); 88 | case 9: 89 | c += ((uint32) k[8] << 8); 90 | /* the lowest byte of c is reserved for the length */ 91 | case 8: 92 | b += ((uint32) k[7] << 24); 93 | case 7: 94 | b += ((uint32) k[6] << 16); 95 | case 6: 96 | b += ((uint32) k[5] << 8); 97 | case 5: 98 | b += k[4]; 99 | case 4: 100 | a += ((uint32) k[3] << 24); 101 | case 3: 102 | a += ((uint32) k[2] << 16); 103 | case 2: 104 | a += ((uint32) k[1] << 8); 105 | case 1: 106 | a += k[0]; 107 | /* case 0: nothing left to add */ 108 | } 109 | #endif /* WORDS_BIGENDIAN */ 110 | 111 | final(a, b, c); 112 | return c; 113 | } 114 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/hash.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lecture Exercises/week04/Ex10/hash.o -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/s: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lecture Exercises/week04/Ex10/s -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/s.c: -------------------------------------------------------------------------------- 1 | #include "bits.h" 2 | #include 3 | 4 | int main(int argc, char **argv) 5 | { 6 | int w = 0x00000000; 7 | int x = 0xFFFFFFFF; 8 | int y = 0x55555555; 9 | int z = 0x12345678; 10 | char b[100]; 11 | 12 | printf("w = 0x%08x = %s\n", w, showBits(w,b)); 13 | printf("x = 0x%08x = %s\n", x, showBits(x,b)); 14 | printf("y = 0x%08x = %s\n", y, showBits(y,b)); 15 | printf("z = 0x%08x = %s\n", z, showBits(z,b)); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/s.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lecture Exercises/week04/Ex10/s.o -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/showBits.c: -------------------------------------------------------------------------------- 1 | // Convert 32-bit values to string 2 | // e.g. "01010101 01100110 10000001 01100110" 3 | 4 | #include "bits.h" 5 | 6 | char *showBits(uint32 val, char *buf) 7 | { 8 | int i,j; char ch; 9 | uint32 bit = 0x80000000; 10 | 11 | i = j = 0; 12 | while (bit != 0) { 13 | ch = ((val & bit) != 0) ? '1' : '0'; 14 | buf[i++] = ch; 15 | j++; 16 | if (j%8 == 0) buf[i++] = ' '; 17 | bit = bit >> 1; 18 | } 19 | buf[--i] = '\0'; 20 | return buf; 21 | } 22 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex10/showBits.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lecture Exercises/week04/Ex10/showBits.o -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/Ex11/linear-hash: -------------------------------------------------------------------------------- 1 | k hash(k) k hash(k) k hash(k) k hash(k) 2 | a 10001 g 00000 m 11001 s 01110 3 | b 11010 h 00000 n 01000 t 10011 4 | c 01111 i 10010 o 00110 u 00010 5 | d 01111 j 10110 p 11101 v 11111 6 | e 01100 k 00101 q 00010 w 10000 7 | f 00010 l 00101 r 00000 x 00111 8 | 9 | b = 4, sp = 0, d = 2, c = 3 10 | i = 0 split after each 6 insertions 11 | 12 | Page Data Overflow 13 | 14 | [000]* g,h,n -> r,w 15 | [001] a,m 16 | [010] b,f,i -> q,u 17 | [011] t 18 | [100] e 19 | [101] k,l,p 20 | [110] j,o,s 21 | [111] c,d,v -> x 22 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/bits/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -Werror 3 | 4 | all: s h 5 | 6 | s : s.o showBits.o bits.o 7 | gcc -o s s.o showBits.o bits.o 8 | 9 | h : h.o hash.o showBits.o bits.o 10 | gcc -o h h.o hash.o showBits.o bits.o 11 | 12 | clean: 13 | rm -f s h *.o core 14 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/bits/bits.c: -------------------------------------------------------------------------------- 1 | // Extract d bits from uint32 2 | // if d +ve, get low-order bits 3 | // if d -ve, get high-order bits 4 | 5 | #include 6 | #include 7 | #include "bits.h" 8 | 9 | uint32 bits(int d, uint32 val) 10 | { 11 | assert(d >= -32 && d <= 32); 12 | uint32 mask; 13 | char buf[33]; 14 | 15 | if (d > 0) { 16 | mask = (0x1 << d) - 1; 17 | printf("Mask = %s\n",showBits(mask,buf)); 18 | return (val & mask); 19 | } 20 | else if (d < 0) { 21 | d = 0-d; 22 | mask = ((0x1 << d) - 1) << (32-d); 23 | printf("Mask = %s\n",showBits(mask,buf)); 24 | return ((val & mask) >> (32-d)); 25 | } 26 | else 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/bits/bits.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint32; 2 | 3 | uint32 hash_any(unsigned char *, int); 4 | 5 | char *showBits(uint32, char *); 6 | 7 | uint32 bits(int d, uint32 val); 8 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/bits/h.c: -------------------------------------------------------------------------------- 1 | #include "bits.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define NBITS 32 7 | #define NCHARS (NBITS+1) 8 | 9 | int main(int argc, char **argv) 10 | { 11 | uint32 hashVal, less; 12 | int n; 13 | char a[NCHARS], b[NCHARS]; 14 | 15 | if (argc < 2) { 16 | fprintf(stderr,"Usage: %s keyVal nbits\n",argv[0]); 17 | exit(1); 18 | } 19 | n = (argc < 3) ? 32 : atoi(argv[2]); 20 | if (n == 0) n = 32; 21 | 22 | printf("key = %s\n", argv[1]); 23 | hashVal = hash_any((unsigned char *)argv[1], strlen(argv[1])); 24 | printf("hash = %s\n", showBits(hashVal,a)); 25 | less = bits(n, hashVal); 26 | printf("bits = %s\n", showBits(less,b)); 27 | exit(0); 28 | } 29 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/bits/hash.c: -------------------------------------------------------------------------------- 1 | #include "bits.h" 2 | 3 | #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) 4 | 5 | #define mix(a,b,c) \ 6 | { \ 7 | a -= c; a ^= rot(c, 4); c += b; \ 8 | b -= a; b ^= rot(a, 6); a += c; \ 9 | c -= b; c ^= rot(b, 8); b += a; \ 10 | a -= c; a ^= rot(c,16); c += b; \ 11 | b -= a; b ^= rot(a,19); a += c; \ 12 | c -= b; c ^= rot(b, 4); b += a; \ 13 | } 14 | 15 | #define final(a,b,c) \ 16 | { \ 17 | c ^= b; c -= rot(b,14); \ 18 | a ^= c; a -= rot(c,11); \ 19 | b ^= a; b -= rot(a,25); \ 20 | c ^= b; c -= rot(b,16); \ 21 | a ^= c; a -= rot(c, 4); \ 22 | b ^= a; b -= rot(a,14); \ 23 | c ^= b; c -= rot(b,24); \ 24 | } 25 | 26 | uint32 27 | hash_any(unsigned char *k, int keylen) 28 | { 29 | uint32 a, b, c, len; 30 | /* set up the internal state */ 31 | len = keylen; 32 | a = b = 0x9e3779b9; 33 | c = 3923095; 34 | 35 | /* handle most of the key */ 36 | while (len >= 12) 37 | { 38 | #ifdef WORDS_BIGENDIAN 39 | a += (k[3] + ((uint32) k[2] << 8) + ((uint32) k[1] << 16) + ((uint32) k[0] << 24)); 40 | b += (k[7] + ((uint32) k[6] << 8) + ((uint32) k[5] << 16) + ((uint32) k[4] << 24)); 41 | c += (k[11] + ((uint32) k[10] << 8) + ((uint32) k[9] << 16) + ((uint32) k[8] << 24)); 42 | #else /* !WORDS_BIGENDIAN */ 43 | a += (k[0] + ((uint32) k[1] << 8) + ((uint32) k[2] << 16) + ((uint32) k[3] << 24)); 44 | b += (k[4] + ((uint32) k[5] << 8) + ((uint32) k[6] << 16) + ((uint32) k[7] << 24)); 45 | c += (k[8] + ((uint32) k[9] << 8) + ((uint32) k[10] << 16) + ((uint32) k[11] << 24)); 46 | #endif /* WORDS_BIGENDIAN */ 47 | mix(a, b, c); 48 | k += 12; 49 | len -= 12; 50 | } 51 | 52 | /* handle the last 11 bytes */ 53 | #ifdef WORDS_BIGENDIAN 54 | switch (len) /* all the case statements fall through */ 55 | { 56 | case 11: 57 | c += ((uint32) k[10] << 8); 58 | case 10: 59 | c += ((uint32) k[9] << 16); 60 | case 9: 61 | c += ((uint32) k[8] << 24); 62 | /* the lowest byte of c is reserved for the length */ 63 | case 8: 64 | b += k[7]; 65 | case 7: 66 | b += ((uint32) k[6] << 8); 67 | case 6: 68 | b += ((uint32) k[5] << 16); 69 | case 5: 70 | b += ((uint32) k[4] << 24); 71 | case 4: 72 | a += k[3]; 73 | case 3: 74 | a += ((uint32) k[2] << 8); 75 | case 2: 76 | a += ((uint32) k[1] << 16); 77 | case 1: 78 | a += ((uint32) k[0] << 24); 79 | /* case 0: nothing left to add */ 80 | } 81 | #else /* !WORDS_BIGENDIAN */ 82 | switch (len) /* all the case statements fall through */ 83 | { 84 | case 11: 85 | c += ((uint32) k[10] << 24); 86 | case 10: 87 | c += ((uint32) k[9] << 16); 88 | case 9: 89 | c += ((uint32) k[8] << 8); 90 | /* the lowest byte of c is reserved for the length */ 91 | case 8: 92 | b += ((uint32) k[7] << 24); 93 | case 7: 94 | b += ((uint32) k[6] << 16); 95 | case 6: 96 | b += ((uint32) k[5] << 8); 97 | case 5: 98 | b += k[4]; 99 | case 4: 100 | a += ((uint32) k[3] << 24); 101 | case 3: 102 | a += ((uint32) k[2] << 16); 103 | case 2: 104 | a += ((uint32) k[1] << 8); 105 | case 1: 106 | a += k[0]; 107 | /* case 0: nothing left to add */ 108 | } 109 | #endif /* WORDS_BIGENDIAN */ 110 | 111 | final(a, b, c); 112 | return c; 113 | } 114 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/bits/s.c: -------------------------------------------------------------------------------- 1 | #include "bits.h" 2 | #include 3 | 4 | int main(int argc, char **argv) 5 | { 6 | int w = 0x00000000; 7 | int x = 0xFFFFFFFF; 8 | int y = 0x55555555; 9 | int z = 0x12345678; 10 | char b[100]; 11 | 12 | printf("w = 0x%08x = %s\n", w, showBits(w,b)); 13 | printf("x = 0x%08x = %s\n", x, showBits(x,b)); 14 | printf("y = 0x%08x = %s\n", y, showBits(y,b)); 15 | printf("z = 0x%08x = %s\n", z, showBits(z,b)); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week04/bits/showBits.c: -------------------------------------------------------------------------------- 1 | // Convert 32-bit values to string 2 | // e.g. "01010101 01100110 10000001 01100110" 3 | 4 | #include "bits.h" 5 | 6 | char *showBits(uint32 val, char *buf) 7 | { 8 | int i,j; char ch; 9 | uint32 bit = 0x80000000; 10 | 11 | i = j = 0; 12 | while (bit != 0) { 13 | ch = ((val & bit) != 0) ? '1' : '0'; 14 | buf[i++] = ch; 15 | j++; 16 | if (j%8 == 0) buf[i++] = ' '; 17 | bit = bit >> 1; 18 | } 19 | buf[--i] = '\0'; 20 | return buf; 21 | } 22 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex1/index-size: -------------------------------------------------------------------------------- 1 | B = 8192, R = 128, r = 100000 2 | header in data pages: 256 bytes 3 | key is integer, data file is sorted on key 4 | index entries (keyVal,tupleID): 8 bytes 5 | header in index pages: 32 bytes 6 | 7 | How many pages for dense/sparse index? 8 | 9 | # tuples/page = c = floor((B-256)/128) = 62 10 | # data pages = ceil(100000/62) = 1613 11 | # index entries per page = c_i = floor((B-32)/8) = 1020 12 | 13 | Dense: 14 | # index entries = r = 100000 15 | # index pages = ceil(100000/1020) = 99 16 | 17 | Sparse: 18 | # index entries = b = 1613 19 | # index pages = ceil(1613/1020) = 2 20 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex10/kd-tree-search: -------------------------------------------------------------------------------- 1 | Describe path(s) through the tree in solving 2 | each of the following: 3 | 4 | 5 | Query: (m,1) 6 | 7 | level 1 -> go right 8 | level 2 -> go left 9 | level 3 -> go right 10 | data page ... scan to find (m,1) 11 | 12 | 13 | Query: (a,?) 14 | 15 | level 1 -> go left 16 | level 2 -> go left and right 17 | level 3 (left) -> go left -> data page 18 | level 3 (right) -> go left -> data page 19 | 20 | 21 | Query: (?,1) 22 | 23 | level 1 -> go left and right 24 | level 2 (left) -> go left 25 | level 3 -> go left and right to data pages 26 | level 2 (right) -> go left 27 | level 3 -> go left and right to data pages 28 | 29 | 30 | Query: (?,?) 31 | 32 | scan data pages 33 | 34 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex11/quad-tree-search: -------------------------------------------------------------------------------- 1 | Describe path(s) through the tree in solving 2 | each of the following: 3 | 4 | 5 | Query: (m,1) 6 | 7 | at level 1, (m,1) fits in (a0,m4) 8 | at level 2, (m,1) fits in (g0,m2) 9 | leads to data page 10 | 11 | 12 | Query: (a,?) 13 | 14 | at level 1, (a,?) fits in (a0,m4) and (a5,m9) 15 | (a0,m4) -> (a,?) fits in (a0,f2) and (a3,f4) 16 | (a0,f2) -> (a,?) fits in (a0,c1) and (a2,c2) 17 | (a0,c1) -> data page containing (a,1) 18 | (a2,c2) -> data page but no matching tuples 19 | (a3,f4) -> data page but no matching tuples 20 | 21 | 22 | Query: (?,1) 23 | 24 | ? 25 | 26 | 27 | Query: (?,?) 28 | 29 | ? 30 | 31 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex12/r-tree-search: -------------------------------------------------------------------------------- 1 | Describe path(s) through the tree in solving 2 | each of the following: 3 | 4 | 5 | Q1: select * from Rel where X='a' and Y=4 6 | 7 | ? 8 | 9 | 10 | Q2: select * from Rel where X='i' and Y=6 11 | 12 | ? 13 | 14 | 15 | Q3: select * from Rel where 'c'≤X≤'j' and Y=5 16 | 17 | ? 18 | 19 | 20 | Q4: select * from Rel where X='c' 21 | 22 | ? 23 | 24 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex2/multiple-indexes: -------------------------------------------------------------------------------- 1 | r=100,000, B=4096 2 | 3 | create table Students ( 4 | id integer primary key, 5 | name char(10), -- simplified 6 | gender char(1), -- 'm','f','?' 7 | birthday char(5) -- 'MM-DD' 8 | ); 9 | 10 | select * from Students 11 | where name='John' and birthday = '04-01' 12 | 13 | describe the selectivity of each attribute 14 | estimate the cost of answering using one index 15 | estimate the cost of answering using both indices 16 | 17 | Size of tuples (bytes): 18 | sizeof(id) = 19 | sizeof(name) = 20 | sizeof(gender) = 21 | sizeof(b'day) = 22 | tuple size = 23 | 24 | Size of data file: 25 | R = ? 26 | c = ? 27 | b = ? 28 | Assume: 96 bytes of header/page 29 | 30 | 31 | Size of index entries: 32 | 33 | index entry = sizeof(Key) + tid = x + 4 34 | indexEntry(id) = 35 | indexEntry(name) = 36 | indexEntry(gender) = 37 | indexEntry(b'day) = 38 | 39 | Size of index: 40 | 41 | sum(pages/level) 42 | 43 | c_i(id) = 44 | b_i(id) = 45 | c_i(name) = 46 | b_i(name) = 47 | c_i(gender) = 48 | b_i(gender) = 49 | c_i(b'day) = 50 | b_i(b'day) = 51 | 52 | 53 | Selectivity: 54 | 55 | id = X ... ? 56 | name = X ... ? 57 | gender = X ... ? 58 | birthday = X ... ? 59 | 60 | 61 | Query: 62 | select * from Students 63 | where name='John' and birthday = '04-01' 64 | 65 | Cost using one index ... 66 | 67 | 68 | Query: 69 | select * from Students 70 | where name='John' and birthday = '04-01' 71 | 72 | Cost using indexes on name and birthday ... 73 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex3/bitmap: -------------------------------------------------------------------------------- 1 | Colour index Price index 2 | red 100011... < $4 110001... 3 | blue 001100... >= $4 001110... 4 | green 010000... 5 | 6 | Assume everything 111111... 7 | colour = 'red' 100011... 8 | & 100011... 9 | price < 4.00 110001... 10 | & 100001... 11 | 12 | 13 | Assume everything 111111... 14 | colour = 'green' 010000... 15 | & 010000... 16 | colour = 'blue' 001100... 17 | | 011100... 18 | 19 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex4/ma-hash-value: -------------------------------------------------------------------------------- 1 | cv = <(1,0), (1,1), (2,0), (3,0), (1,2), (2,1), (3,1), (1,3), ...> 2 | 3 | hash1('John Smith') = ...0101010110110100 4 | 5 | hash2('BSc(CompSci)') = ...1011111101101111 6 | 7 | hash3(1990) = ...0001001011000000 8 | 9 | Produce bits of hash value from least-sig to most-sig ... 10 | 11 | bit[0] = 0 12 | 13 | bit[1] = 0 14 | 15 | bit[2] = 1 16 | 17 | bit[3] = 0 18 | 19 | bit[4] = 1 20 | 21 | bit[5] = 1 22 | 23 | composite hash = 110100 24 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex5/ma-hashing: -------------------------------------------------------------------------------- 1 | d=6, b=2^6, CV = <(0,0),(0,1),(1,0),(2,0),(1,1),(0,2), ...> 2 | 3 | hash (a) = ...00101101001101 4 | hash (b) = ...00101101001101 5 | hash (c) = ...00101101001101 6 | 7 | What are the query hashes for each of the following queries: 8 | 9 | (a,b,c) 101101 bucket 45 only 10 | 11 | (a,?,c) 1*1*01 101001, 101101, 111001, 111101 12 | 13 | (?,b,c) *011** 001100, 001101, 001110, 001111, 101100, etc. 14 | 15 | (a,?,?) 1***01 100001, 100101, 101001, 101101, 110001, etc. 16 | 17 | (?,?,?) ****** all of them 0,1,2,3,4...63 18 | 19 | i.e. fill in *** as 000, 001, 010, 011, 100, 101, 110, 111 20 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex6/bit-string: -------------------------------------------------------------------------------- 1 | Representing: 2 | 3 | 01000*10**001*101 4 | 5 | First possibility: 6 | 7 | "01000*10**001*101" (as a string) (18 bytes) 8 | 9 | 10 | Use 2-bits 00 = 0, 01 = 1, 11 = * 11 | 12 | 13 | 14 | Representing: 15 | 16 | 01000*10**001*101 17 | 18 | Second possibility: 19 | 20 | 1000010000010101 real hash bits (2 bytes) 21 | 0000100110001000 stars (2 bytes) 22 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex7/mah-queries: -------------------------------------------------------------------------------- 1 | Consider a table R(x,y,z) using multi-attribute hashing where 2 | 3 | d = 9 d[x] = 5 d[y] = 3 d[z] = 1 4 | 5 | How many buckets are accessed in answering each of these queries? 6 | 7 | select * from R where x = 4 and y = 2 and z = 1 8 | 9 | all bits known => 1 bucket 10 | 11 | select * from R where x = 5 and y = 3 12 | 13 | ? unknown bits => ? buckets 14 | 15 | select * from R where y = 99 16 | 17 | ? unknown bits => ? buckets 18 | 19 | select * from R where z = 23 20 | 21 | ? unknown bits => ? buckets 22 | 23 | select * from R where x > 5 24 | 25 | linear scan; hashing no help with Range queries 26 | 27 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week06/Ex8/mah-design: -------------------------------------------------------------------------------- 1 | Consider relation Person(name,gender,age) ... 2 | 3 | How many bits to use for each attribute? 4 | 5 | 6 | 0.5 ... select * from Person where gender=X and age=Y 7 | 0.3 ... select * from Person where name=X 8 | 0.2 ... select * from Person where gender=X 9 | 10 | total b = 32, d = 5 bits 11 | 12 | name: domain:huge ... used in 0.3 queries => 1 bits 13 | 14 | gender: domain:4 ... max 2 bits ... used in 0.7 queries => 2 bits 15 | 16 | age: domain:128 ... max 7 bits ... used in 0.5 queries => 2 bits 17 | 18 | Avg Cost = 0.5 * 2^1 + 0.3 * 2^4 + 0.2 * 2^3 = 7.4 19 | 20 | 21 | 0.5 ... select * from Person where gender=X and age=Y 22 | 0.3 ... select * from Person where name=X 23 | 0.2 ... select * from Person where gender=X 24 | 25 | total b = 1024, d = 10 bits 26 | 27 | name: domain:huge ... used in 0.3 queries => 2 bits 28 | 29 | gender: domain:4 ... max 2 bits ... used in 0.7 queries => 2 bits 30 | 31 | age: domain:128 ... max 7 bits ... used in 0.5 queries => 6 bits 32 | 33 | Avg Cost = 0.5 * 2^2 + 0.3 * 2^8 + 0.2 * 2^8 = 130 34 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week08/Ex1/join-order: -------------------------------------------------------------------------------- 1 | (Students join Enrol) join (Courses join Staff) 2 | 3 | (Students join (Enrol join (Course join Staff))) 4 | 5 | (Students join ((Enrol join Course) join Staff)) 6 | 7 | (((Students join Enrol) join Course) join Staff) 8 | 9 | BUT NOT 10 | 11 | (Students join Staff) join (Courses join Enrol) 12 | 13 | Tmp1(sid,sname,course,mark) 14 | = Students join[sid=student] Enrol 15 | Tmp2(sid,sname,code,term,lic,mark) 16 | = Tmp1 join[cid=course] Courses 17 | Tmp3(sid,sname,code,term,fname,mark) 18 | = Tmp2 join[lic=fid] Staff 19 | Res(code,sid,sname,mark) 20 | = Sel[term='11s2' & fname='JS'](Tmp3) 21 | 22 | Tmp1(fid,fname) 23 | = Sel[fname='JS'](Staff) 24 | Tmp2(cid,code,lic) 25 | = Sel[term='11s2'](Courses) 26 | Tmp3(cid,code) 27 | = Tmp1 Join[fid=lic] Tmp2 28 | Tmp4(student,code,mark) 29 | = Tmp3 Join[cid=course] Enrolments 30 | Res(code,sid,sname,mark) 31 | = Tmp4 Join[student=sid] Student 32 | 33 | Tmp1 34 | = Students Join Enrol 35 | Tmp2 36 | = Courses Join Staff 37 | Tmp3 38 | = Tmp1 Join Tmp2 39 | Tmp4 40 | = Sel[fname='JS' && term='11s2']Tmp3 41 | Res 42 | = ... 43 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week08/Ex2/sel-size2: -------------------------------------------------------------------------------- 1 | r = 500, V(X,R) = 5, a,b,c,d,e,NULL ~ 40:20:10:10:10:10 2 | 3 | Estimate cost for ... 4 | 5 | 1. select * from R where X is not null 6 | 7 | 90% are not null = 450 tuples 8 | 9 | 10 | 2. select * from R where X >= 'c' 11 | 12 | 30% satisfy condition => 150 tuples 13 | 14 | 15 | 3. select * from R where X between 'b' and 'd' 16 | 17 | 40% satisfy condition => 200 tuples 18 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week08/Ex2/selection-size: -------------------------------------------------------------------------------- 1 | r = 1000, V(A,R) = 10, V(B,R) = 100 2 | 3 | Estimate selectivity of: 4 | 5 | 6 | 1. select * from R where not A=k 7 | 8 | A=k likelihood 1/10 => a<>k likelihood 9/10 9 | 10 | alternatively 11 | 12 | Prob(A=k) = 0.1 13 | Prob(A<>k) = 1 - Prob(A=k) = 0.9 14 | 15 | #tuples in result (A<>k) = 9/10 * 1000 = 900 16 | #tuples in result (A=k) = 1/10 * 1000 = 100 17 | 18 | 19 | 2. select * from R where A=k and B=j 20 | 21 | #tuples(Tmp = sel[A=k](R)) = 1000/10 = 100 22 | #tuples(sel[B=j](Tmp)) = 100/100 = 1 23 | 24 | alternatively 25 | 26 | Prob(A=k) = 0.1 27 | Prob(B=j) = 0.01 28 | Prob(A=k and B=j) = Prob(A=k) * Prob(B=j) = 0.001 29 | 30 | 31 | 3. select * from R where A in (k,l,m,n) 32 | 33 | A in (k,l,m,n) likelhood = 4/10 * 1000 = 400 34 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week08/Ex3/join-size: -------------------------------------------------------------------------------- 1 | Estimate sizes of join results for ... 2 | 3 | 1. select * from R, S where R.s = S.id 4 | 5 | (where S.id is a primary key 6 | and R.s is a foreign key referencing S.id) 7 | 8 | Max size = r_R 9 | when no tuples in R have R.s is null 10 | 11 | Min size = 0 12 | when all tuples in R have R.s is null 13 | 14 | 15 | 2. select * from R, S where R.s <> S.id 16 | 17 | (where S.id is a primary key 18 | and R.s is a foreign key referencing S.id) 19 | 20 | Max size ~= r_R * (r_S-1) 21 | when no tuples in R have R.s is null 22 | 23 | Min size = 0 24 | when all tuples in R have R.s is null 25 | 26 | 27 | 3. select * from R, S where R.x = S.y 28 | 29 | (where R.x and S.y have no connection 30 | except that dom(R.x)=dom(S.y), e.g. integer) 31 | 32 | Min size = 0 33 | when V(x,R) INT V(y,S) = Empty 34 | 35 | Max size = r_R * r_S 36 | when |V(x,R)| == |V(y,S)| == 1 and V(x,R) == v(y,S) 37 | (very unlikely) 38 | 39 | 40 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week08/Ex4/query-plans: -------------------------------------------------------------------------------- 1 | 1. select max(birthday) from People 2 | 3 | sequential scan, with aggregate checking max 4 | 5 | 6 | 2. select max(id) from People 7 | 8 | id is a pk => have Btree index 9 | scan index to find right-most key 10 | 11 | 12 | 3. select family from People order by family 13 | 14 | merge sort, invoked by sequential scan of People 15 | 16 | 17 | 4. select distinct p.id, pname 18 | from People s, CourseEnrolments e 19 | where s.id=e.student and e.grade='FL' 20 | 21 | nested loop join 22 | outer relation is Sel[e.grade='FL'] 23 | inner relation is People 24 | 25 | OR 26 | 27 | index nested loop join 28 | outer relation is Sel[e.grade='FL'] 29 | inner relation is Sel[s.id=e.student] using Btree 30 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week09/Ex1/transfer: -------------------------------------------------------------------------------- 1 | The transaction can be expressed as: 2 | 3 | T: B R(X) R(X) W(X) R(Y) W(Y) C 4 | 5 | To simplify the example, assume read-for-update exists 6 | 7 | T: B R(X) W(X) R(Y) W(Y) C 8 | 9 | Assume T1 = transfer(1,2,100), T2 = transfer(1,2,200) 10 | Initially Accounts(1,x,500), Accounts(2,y,200) 11 | Finally Accounts(1,x,200), Accounts(2,y,500) 12 | 13 | 14 | Serial execution of transfers could be ... 15 | 16 | T1: B R(X) W(X) R(Y) W(Y) C 17 | T2: B R(X) W(X) R(Y) W(Y) C 18 | 19 | (1) 500 400 200 300 20 | (2) 400 200 300 500 21 | 22 | Finally Accounts(1,x,200), Accounts(2,y,500) 23 | 24 | 25 | 26 | 27 | T1 = transfer(1,2,100), T2 = transfer(1,2,200) 28 | 29 | One concurrent execution of transfers ... 30 | 31 | T1: B R(X) W(X) R(Y) W(Y) C 32 | T2: B R(X) W(X) R(Y) W(Y) C 33 | 34 | (1) 500 400 200 300 35 | (2) 400 200 300 500 36 | 37 | Finally Accounts(1,x,200), Accounts(2,y,500) 38 | 39 | 40 | 41 | 42 | T1 = transfer(1,2,100), T2 = transfer(1,2,200) 43 | 44 | Another concurrent execution of transfers ... 45 | 46 | T1: B R(X) W(X) R(Y) W(Y) C 47 | T2: B R(X) W(X) R(Y) W(Y) C 48 | 49 | (1) 500 400 200 300 50 | (2) 500 300 200 400 51 | 52 | Finally Accounts(1,x,300), Accounts(2,y,400) 53 | 54 | 55 | 56 | 57 | T1 = transfer(1,2,100), T2 = transfer(1,2,200) 58 | 59 | Another concurrent execution of transfers ... 60 | 61 | T1: B R(X) W(X) R(Y) W(Y) C 62 | T2: B R(X) W(X) R(Y) W(Y) C 63 | 64 | (1) 500 400 200 300 65 | (2) 500 300 300 500 66 | 67 | Finally Accounts(1,x,300), Accounts(2,y,500) 68 | 69 | 70 | 71 | T1 = transfer(1,2,100), T2 = transfer(1,2,200) 72 | 73 | Another concurrent execution of transfers ... 74 | 75 | T1: B R(X) W(X) R(Y) W(Y) C 76 | T2: B R(X) W(X) R(Y) W(Y) C 77 | 78 | (1) 500 400 200 300 79 | (2) 500 300 200 400 80 | 81 | Finally Accounts(1,x,400), Accounts(2,y,400) 82 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week09/Ex2/number-of-schedules: -------------------------------------------------------------------------------- 1 | Consider n transactions: 2 | 3 | T1, T2, ... Tn 4 | 5 | How many possible serial schedules are there? 6 | 7 | Some possible schedules: 8 | 9 | T1 T2 ... Tn 10 | Tn ... T2 T1 11 | T2 T1 ... Tn 12 | 13 | So, the question is, how many different orderings? 14 | 15 | # possible schedules = n! 16 | 17 | 18 | 19 | Consider 2 transactions: 20 | 21 | Ta: R(X) R(Y) W(X) W(Y) 22 | Tb: R(Y) W(Y) R(X) W(X) 23 | 24 | The objects don't matter in counting schedules. 25 | The order of operations does matter. 26 | 27 | Rename the ops as: 28 | 29 | Ta: a1 a2 a3 a4 30 | Tb: b1 b2 b3 b4 31 | 32 | Some possible schedules: 33 | 34 | a1 a2 a3 a4 b1 b2 b3 b4 35 | b1 b2 b3 b4 a1 a2 a3 a4 36 | a1 b1 a2 b2 a3 b3 a4 b4 37 | b1 a1 b2 a2 b3 a3 b4 a4 38 | etc. etc. 39 | 40 | At each step: 41 | * we have a "current" op 42 | * we have two choices for "next" op 43 | - "next" op in this tx 44 | - "next" op in other tx 45 | 46 | So ... 47 | * initially no "current" op 48 | * "next" op in Ta is a1, "next" op in Tb is b1 49 | * choose either a1 or b1 50 | * if first op is a1, second op is either a2 or b1 51 | * if first op is b1, second op is either a1 or b2 52 | * etc. etc. 53 | 54 | There are 8 ops overall. 55 | The first 7 each have two choices. 56 | The last has only one choice (the remaining op). 57 | 58 | Number of schedules: 2^7 59 | 60 | Left as an exercise ... 61 | 62 | Number of schedules for k tx's, each with n ops 63 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week09/Ex3/recov.serial: -------------------------------------------------------------------------------- 1 | Recoverable: 2 | a schedule is recoverable if each tx commits 3 | only after each tx from which it has read commits 4 | 5 | Serializable: 6 | a schedule is serializable if it is equivalent 7 | to some serial schedule (assume conflict-serializable) 8 | 9 | 10 | Recoverable and serializable: 11 | 12 | T1: W(A) W(B) C 13 | T2: W(A) R(B) C 14 | 15 | 16 | Recoverable and not serializable: 17 | 18 | T1: W(A) W(B) C 19 | T2: W(A) R(B) C 20 | 21 | 22 | Not recoverable and serializable: 23 | 24 | T1: W(A) W(B) C 25 | T2: W(A) R(B) C 26 | 27 | or 28 | 29 | T1: W(A) W(B) C 30 | T2: W(A) R(B) C 31 | 32 | 33 | ACR: 34 | 35 | T1: W(A) W(B) C 36 | T2: W(A) R(B) C 37 | 38 | or 39 | 40 | T1: W(A) W(B) C 41 | T2: W(A) R(B) C 42 | 43 | Both are recoverable and serializable. 44 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week09/Ex3/recoverable: -------------------------------------------------------------------------------- 1 | Consider the two transactions: 2 | 3 | T1: W(A) W(B) C 4 | T2: W(A) R(B) C 5 | 6 | Recoverable: 7 | * all tx's Ti that wrote values used by Tj 8 | * must have committed before Tj commits 9 | 10 | 11 | A schedule which is recoverable and serializable 12 | 13 | T1: W(A) W(B) C 14 | T2: W(A) R(B) C 15 | 16 | 17 | A schedule which is recoverable but not serializable 18 | 19 | T1: W(A) W(B) C 20 | T2: W(A) R(B) C 21 | 22 | 23 | A schedule which is serializable but not recoverable 24 | 25 | T1: W(A) W(B) C 26 | T2: W(A) R(B) C 27 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week09/Ex4/serializable: -------------------------------------------------------------------------------- 1 | (A) Consider the schedule: 2 | 3 | T1: W(B) W(A) 4 | T2: R(B) W(A) 5 | T3: R(A) W(A) 6 | 7 | 8 | Conflict Equivalence 9 | ==================== 10 | 11 | Check precedence graph ... 12 | 13 | conflict on B between T1 and T2: T2 --> T1 14 | conflict on A between T1 and T3: T1 --> T3 15 | conflict on A between T2 and T3: T3 --> T2 16 | conflict on A between T2 and T3: T2 --> T3 17 | 18 | This graph has a cycle T1 --> T3 --> T2 --> T1 19 | so the schedule is not conflict serializable 20 | 21 | Also, a simpler cycle T3 --> T2 --> T3 22 | 23 | 24 | T1: W(B) W(A) 25 | T2: R(B) W(A) 26 | T3: R(A) W(A) 27 | 28 | 29 | View Equivalence 30 | ================ 31 | 32 | For each shared object: 33 | - determine first reader 34 | - determine last writer 35 | - determine which version is read by each Ti 36 | 37 | S1 ... 38 | T1: W(B) W(A) 39 | T2: R(B) W(A) 40 | T3: R(A) W(A) 41 | 42 | is view-equivalent to 43 | 44 | S2 ... 45 | T1: W(B) W(A) 46 | T2: R(B) W(A) 47 | T3: R(A) W(A) 48 | 49 | which is obviously a serial schedule 50 | 51 | "Proof" of view equivalence: 52 | 53 | S1 ... 54 | B first reader T2, last writer T1 55 | A first reader T3, last writer T3, T3 reads T1's A 56 | 57 | S2 ... 58 | B first reader T2, last writer T1 59 | A first reader T3, last writer T3, T3 reads T1's A 60 | 61 | 62 | 63 | 64 | 65 | (B) Consider the schedule: 66 | 67 | T1: W(B) W(A) 68 | T2: R(B) W(A) 69 | T3: R(A) W(A) 70 | 71 | Conflict Equavalence 72 | ==================== 73 | 74 | Check precedence graph ... 75 | 76 | * there is a conflict between T1 and T2 on B with T2 --> T1 77 | * there is a conflict between T1 and T2 on A with T1 --> T2 78 | 79 | This graph has a cycle T1 --> T2 --> T1 80 | so the schedule is not conflict serializable 81 | 82 | 83 | 84 | View Equivalence 85 | ================ 86 | 87 | For each shared object: 88 | - determine first reader (which tx reads initial value) 89 | - determine last writer (which tx writes the last value) 90 | - determine which version is read by each Ti 91 | 92 | S1 ... 93 | 94 | T1: W(B) W(A) 95 | T2: R(B) W(A) 96 | T3: R(A) W(A) 97 | 98 | For B, first reader is T2, last writer is T1 99 | For A, first reader is T3, last writer is T3 100 | T3 reads the value of A written by T1 101 | 102 | 103 | There are six possible serial schedules 104 | 105 | T1T2T3, T1T3T2, T2T1T3, T2T3T1, T3T1T2, T3T2T1 106 | 107 | The only schedules that have the property 108 | T3 reads the value of A written by T2 109 | are those where T2 comes before T3 110 | i.e. T1T2T3, T2T3T1 111 | 112 | Of these, the only schedules that have the property 113 | last writer of A is T3 114 | are T1T2T3 115 | 116 | This schedule also has the property 117 | first reader of A is T3 118 | 119 | T1T2T3 is not view equivalent because 120 | T2 reads the version of B produced by T1 121 | whereas in schedule S1 122 | T2 reads the initial value of B 123 | 124 | Thus, there is no serial schedule that has all of 125 | the same read/write properties for shared variables 126 | as S1 does 127 | => S1 is not view-equivalent to any serial schedule 128 | => S1 is not view serializable 129 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week09/Ex5/deadlock: -------------------------------------------------------------------------------- 1 | T1: R(A) W(C) W(D) 2 | T2: R(B) W(C) 3 | T3: R(D) W(B) 4 | T4: R(E) W(A) 5 | 6 | All locks are granted until w3(B). Now, T3 has to wait for T2, 7 | which has a shared lock on B, and the waits-for graph is 8 | 9 | T3 ----> T2 10 | 11 | At the next step, T2 must wait for T1, which has a lock on C. 12 | The waits-for graph is: 13 | 14 | T3 ----> T2 ----> T1 15 | 16 | Next, w4(A) causes T4 to wait for T1. There is still no cycle, 17 | and the waits-for graph is: 18 | 19 | T3 ----> T2 ----> T1 <---- T4 20 | 21 | Finally, T1 tries to write D. It cannot get the exclusive lock on D 22 | that it needs, because T3 holds a shared lock on D. If we allowed T1 23 | to wait, the graph would be: 24 | 25 | T3 ----> T2 ----> T1 <---- T4 26 | ^ | 27 | |_________________| 28 | 29 | Thus, T1 must abort and relinquish its locks. At that time, 30 | T2 and T4 can each get the locks they need. 31 | When T2 finishes, T3 can proceed. 32 | -------------------------------------------------------------------------------- /19T2/Lecture Exercises/week09/Ex6/seat-alloc: -------------------------------------------------------------------------------- 1 | Need to ensure that no "conflicting" access to the 2 | SeatAlloc table happens. 3 | 4 | The possible conflict: 5 | * two tx's read simultaneously and both find the seat empty 6 | * both then proceed to give the same seat to two different pax's 7 | 8 | We need to ensure that only one tx at a time can access SeatAlloc. 9 | 10 | One way: 11 | 12 | LOCK TABLE SeatAlloc 13 | - gives exclusive access to the SeatAlloc table 14 | - solves problem, but locks out updates on all other flights 15 | 16 | Would be nice to be able to only lock attempts to allocate 17 | seats for this flight or even better just lock concurrent 18 | attempts on this seat. 19 | 20 | A better way: 21 | 22 | SELECT ... FOR UPDATE 23 | - gives exclusive access to the seat allocation in question 24 | 25 | 26 | First approach ... 27 | 28 | create or replace function 29 | allocSeat(paxID int, fltID int, seat text) returns boolean 30 | as $$ 31 | declare 32 | pid int; 33 | begin 34 | SELECT paxID into pid from SeatingAlloc 35 | where flightID = fltID and seatNum = seat; 36 | if (pid is null) then 37 | update SeatingAlloc set pax = paxID 38 | where flightID = fltID and seatNum = seat; 39 | end if; 40 | return (pid is null); 41 | end; 42 | $$ language plpgsql; 43 | 44 | BEGIN; 45 | LOCK TABLE SeatAlloc; 46 | select allocSeat(...) 47 | COMMIT; 48 | 49 | 50 | Second approach ... 51 | 52 | create or replace function 53 | allocSeat(paxID int, fltID int, seat text) returns boolean 54 | as $$ 55 | declare 56 | avail boolean; 57 | begin 58 | SELECT count(*)=1 into avail from SeatsAvail 59 | where flightID = fltID and seatNum = seat 60 | FOR UPDATE; 61 | if (avail) then 62 | update SeatingAlloc set pax = paxID 63 | where flightID = fltID and seatNum = seat; 64 | -- COMMIT; 65 | end if; 66 | return avail; 67 | end; 68 | $$ language plpgsql; 69 | 70 | -------------------------------------------------------------------------------- /19T2/Lectures/all-slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lectures/all-slides.pdf -------------------------------------------------------------------------------- /19T2/Lectures/week01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lectures/week01.pdf -------------------------------------------------------------------------------- /19T2/Lectures/week02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lectures/week02.pdf -------------------------------------------------------------------------------- /19T2/Lectures/week03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lectures/week03.pdf -------------------------------------------------------------------------------- /19T2/Lectures/week04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lectures/week04.pdf -------------------------------------------------------------------------------- /19T2/Lectures/week06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lectures/week06.pdf -------------------------------------------------------------------------------- /19T2/Lectures/week08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lectures/week08.pdf -------------------------------------------------------------------------------- /19T2/Lectures/week09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lectures/week09.pdf -------------------------------------------------------------------------------- /19T2/Lectures/week10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Lectures/week10.pdf -------------------------------------------------------------------------------- /19T2/Prac Exercises/p01/COMP9315 19T2 - Prac Exercise 01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Prac Exercises/p01/COMP9315 19T2 - Prac Exercise 01.pdf -------------------------------------------------------------------------------- /19T2/Prac Exercises/p01/beer.dump: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | SET statement_timeout = 0; 6 | SET client_encoding = 'SQL_ASCII'; 7 | SET standard_conforming_strings = off; 8 | SET check_function_bodies = false; 9 | SET client_min_messages = warning; 10 | SET escape_string_warning = off; 11 | 12 | SET search_path = public, pg_catalog; 13 | 14 | -- 15 | -- Name: barname; Type: DOMAIN; Schema: public; Owner: - 16 | -- 17 | 18 | CREATE DOMAIN barname AS character varying(30); 19 | 20 | 21 | -- 22 | -- Name: beername; Type: DOMAIN; Schema: public; Owner: - 23 | -- 24 | 25 | CREATE DOMAIN beername AS character varying(30); 26 | 27 | 28 | -- 29 | -- Name: drinkername; Type: DOMAIN; Schema: public; Owner: - 30 | -- 31 | 32 | CREATE DOMAIN drinkername AS character varying(20); 33 | 34 | 35 | SET default_tablespace = ''; 36 | 37 | SET default_with_oids = false; 38 | 39 | -- 40 | -- Name: bars; Type: TABLE; Schema: public; Owner: -; Tablespace: 41 | -- 42 | 43 | CREATE TABLE bars ( 44 | name barname NOT NULL, 45 | addr character varying(20), 46 | license integer 47 | ); 48 | 49 | 50 | -- 51 | -- Name: beers; Type: TABLE; Schema: public; Owner: -; Tablespace: 52 | -- 53 | 54 | CREATE TABLE beers ( 55 | name barname NOT NULL, 56 | manf character varying(20) 57 | ); 58 | 59 | 60 | -- 61 | -- Name: drinkers; Type: TABLE; Schema: public; Owner: -; Tablespace: 62 | -- 63 | 64 | CREATE TABLE drinkers ( 65 | name drinkername NOT NULL, 66 | addr character varying(30), 67 | phone character(10) 68 | ); 69 | 70 | 71 | -- 72 | -- Name: frequents; Type: TABLE; Schema: public; Owner: -; Tablespace: 73 | -- 74 | 75 | CREATE TABLE frequents ( 76 | drinker drinkername NOT NULL, 77 | bar barname NOT NULL 78 | ); 79 | 80 | 81 | -- 82 | -- Name: likes; Type: TABLE; Schema: public; Owner: -; Tablespace: 83 | -- 84 | 85 | CREATE TABLE likes ( 86 | drinker drinkername NOT NULL, 87 | beer beername NOT NULL 88 | ); 89 | 90 | 91 | -- 92 | -- Name: sells; Type: TABLE; Schema: public; Owner: -; Tablespace: 93 | -- 94 | 95 | CREATE TABLE sells ( 96 | bar barname NOT NULL, 97 | beer beername NOT NULL, 98 | price double precision 99 | ); 100 | 101 | 102 | -- 103 | -- Data for Name: bars; Type: TABLE DATA; Schema: public; Owner: - 104 | -- 105 | 106 | COPY bars (name, addr, license) FROM stdin; 107 | Australia Hotel The Rocks 123456 108 | Coogee Bay Hotel Coogee 966500 109 | Lord Nelson The Rocks 123888 110 | Marble Bar Sydney 122123 111 | Regent Hotel Kingsford 987654 112 | Royal Hotel Randwick 938500 113 | \. 114 | 115 | 116 | -- 117 | -- Data for Name: beers; Type: TABLE DATA; Schema: public; Owner: - 118 | -- 119 | 120 | COPY beers (name, manf) FROM stdin; 121 | 80/- Caledonian 122 | Amber Ale ,James Squire 123 | Bigfoot Barley Wine Sierra Nevada 124 | Burragorang Bock George IV Inn 125 | Chestnut Lager Bridge Road Brewers 126 | Crown Lager Carlton 127 | Fosters Lager Carlton 128 | India Pale Ale James Squire 129 | Invalid Stout Carlton 130 | Melbourne Bitter Carlton 131 | New Toohey's 132 | Old Toohey's 133 | Old Admiral Lord Nelson 134 | Pale Ale Sierra Nevada 135 | Pilsener James Squire 136 | Pilsner Murray's 137 | Porter James Squire 138 | Premium Lager Cascade 139 | Red Toohey's 140 | Sheaf Stout Toohey's 141 | Sparkling Ale Cooper's 142 | Stout Cooper's 143 | Three Sheets Lord Nelson 144 | Victoria Bitter Carlton 145 | \. 146 | 147 | 148 | -- 149 | -- Data for Name: drinkers; Type: TABLE DATA; Schema: public; Owner: - 150 | -- 151 | 152 | COPY drinkers (name, addr, phone) FROM stdin; 153 | Adam Randwick 9385-4444 154 | Gernot Newtown 9415-3378 155 | John Clovelly 9665-1234 156 | Justin Mosman 9845-4321 157 | \. 158 | 159 | 160 | -- 161 | -- Data for Name: frequents; Type: TABLE DATA; Schema: public; Owner: - 162 | -- 163 | 164 | COPY frequents (drinker, bar) FROM stdin; 165 | Adam Coogee Bay Hotel 166 | Gernot Lord Nelson 167 | John Coogee Bay Hotel 168 | John Lord Nelson 169 | John Australia Hotel 170 | Justin Regent Hotel 171 | Justin Marble Bar 172 | \. 173 | 174 | 175 | -- 176 | -- Data for Name: likes; Type: TABLE DATA; Schema: public; Owner: - 177 | -- 178 | 179 | COPY likes (drinker, beer) FROM stdin; 180 | Adam Crown Lager 181 | Adam Fosters Lager 182 | Adam New 183 | Gernot Premium Lager 184 | Gernot Sparkling Ale 185 | John 80/- 186 | John Bigfoot Barley Wine 187 | John Pale Ale 188 | John Three Sheets 189 | Justin Sparkling Ale 190 | Justin Victoria Bitter 191 | \. 192 | 193 | 194 | -- 195 | -- Data for Name: sells; Type: TABLE DATA; Schema: public; Owner: - 196 | -- 197 | 198 | COPY sells (bar, beer, price) FROM stdin; 199 | Australia Hotel Burragorang Bock 3.5 200 | Coogee Bay Hotel New 2.25 201 | Coogee Bay Hotel Old 2.5 202 | Coogee Bay Hotel Sparkling Ale 2.7999999999999998 203 | Coogee Bay Hotel Victoria Bitter 2.2999999999999998 204 | Lord Nelson Three Sheets 3.75 205 | Lord Nelson Old Admiral 3.75 206 | Marble Bar New 2.7999999999999998 207 | Marble Bar Old 2.7999999999999998 208 | Marble Bar Victoria Bitter 2.7999999999999998 209 | Regent Hotel New 2.2000000000000002 210 | Regent Hotel Victoria Bitter 2.2000000000000002 211 | Royal Hotel New 2.2999999999999998 212 | Royal Hotel Old 2.2999999999999998 213 | Royal Hotel Victoria Bitter 2.2999999999999998 214 | \. 215 | 216 | 217 | -- 218 | -- Name: bars_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 219 | -- 220 | 221 | ALTER TABLE ONLY bars 222 | ADD CONSTRAINT bars_pkey PRIMARY KEY (name); 223 | 224 | 225 | -- 226 | -- Name: beers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 227 | -- 228 | 229 | ALTER TABLE ONLY beers 230 | ADD CONSTRAINT beers_pkey PRIMARY KEY (name); 231 | 232 | 233 | -- 234 | -- Name: drinkers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 235 | -- 236 | 237 | ALTER TABLE ONLY drinkers 238 | ADD CONSTRAINT drinkers_pkey PRIMARY KEY (name); 239 | 240 | 241 | -- 242 | -- Name: frequents_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 243 | -- 244 | 245 | ALTER TABLE ONLY frequents 246 | ADD CONSTRAINT frequents_pkey PRIMARY KEY (drinker, bar); 247 | 248 | 249 | -- 250 | -- Name: likes_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 251 | -- 252 | 253 | ALTER TABLE ONLY likes 254 | ADD CONSTRAINT likes_pkey PRIMARY KEY (drinker, beer); 255 | 256 | 257 | -- 258 | -- Name: sells_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 259 | -- 260 | 261 | ALTER TABLE ONLY sells 262 | ADD CONSTRAINT sells_pkey PRIMARY KEY (bar, beer); 263 | 264 | 265 | -- 266 | -- Name: frequents_bar_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - 267 | -- 268 | 269 | ALTER TABLE ONLY frequents 270 | ADD CONSTRAINT frequents_bar_fkey FOREIGN KEY (bar) REFERENCES bars(name); 271 | 272 | 273 | -- 274 | -- Name: frequents_drinker_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - 275 | -- 276 | 277 | ALTER TABLE ONLY frequents 278 | ADD CONSTRAINT frequents_drinker_fkey FOREIGN KEY (drinker) REFERENCES drinkers(name); 279 | 280 | 281 | -- 282 | -- Name: likes_beer_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - 283 | -- 284 | 285 | ALTER TABLE ONLY likes 286 | ADD CONSTRAINT likes_beer_fkey FOREIGN KEY (beer) REFERENCES beers(name); 287 | 288 | 289 | -- 290 | -- Name: likes_drinker_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - 291 | -- 292 | 293 | ALTER TABLE ONLY likes 294 | ADD CONSTRAINT likes_drinker_fkey FOREIGN KEY (drinker) REFERENCES drinkers(name); 295 | 296 | 297 | -- 298 | -- Name: sells_bar_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - 299 | -- 300 | 301 | ALTER TABLE ONLY sells 302 | ADD CONSTRAINT sells_bar_fkey FOREIGN KEY (bar) REFERENCES bars(name); 303 | 304 | 305 | -- 306 | -- Name: sells_beer_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - 307 | -- 308 | 309 | ALTER TABLE ONLY sells 310 | ADD CONSTRAINT sells_beer_fkey FOREIGN KEY (beer) REFERENCES beers(name); 311 | 312 | 313 | -- 314 | -- PostgreSQL database dump complete 315 | -- 316 | 317 | -------------------------------------------------------------------------------- /19T2/Prac Exercises/p02/COMP9315 19T2 - Prac Exercise 02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Prac Exercises/p02/COMP9315 19T2 - Prac Exercise 02.pdf -------------------------------------------------------------------------------- /19T2/Prac Exercises/p02/schema.sql: -------------------------------------------------------------------------------- 1 | -- "pg_class" holds core information about tables 2 | -- "pg_attribute" contains information about attributes 3 | -- "pg_namespace" contains information about schemata 4 | 5 | create or replace function schema() returns setof text 6 | as $$ 7 | declare 8 | rec record; 9 | rel text := ''; 10 | att text := ''; 11 | out text := ''; 12 | len integer := 0; 13 | begin 14 | for rec in 15 | select t.relname, a.attname -- Name of the table, The column name 16 | from pg_class t, pg_attribute a, pg_namespace n 17 | where t.relkind='r' -- r=ordinary table 18 | and t.relnamespace = n.oid -- The OID of the namespace that contains this relation, pg_namespace.oid 19 | and n.nspname = 'public' -- Name of the namespace 20 | and a.attrelid = t.oid -- The table this column belongs to, pg_class.oid 21 | and a.attnum > 0 -- The number of the column 22 | order by t.relname, a.attnum 23 | loop 24 | if (rec.relname <> rel) then -- If table name is different from the former one 25 | if (rel <> '') then -- If relation name is non-null 26 | out := rel || '(' || att || ')'; 27 | return next out; 28 | end if; 29 | rel := rec.relname; -- relation name = table name 30 | att := ''; 31 | len := 0; 32 | end if; 33 | if (att <> '') then -- If attribute-list is non-null 34 | att := att || ', '; -- Append attribute to attribute-list 35 | len := len + 2; -- string length + 2 36 | end if; 37 | if (len + length(rec.attname) > 70) then -- newline 38 | att := att || E'\n '; 39 | len := 0; 40 | end if; 41 | att := att || rec.attname; 42 | len := len + length(rec.attname); 43 | end loop; 44 | -- deal with last table 45 | if (rel <> '') then 46 | out := rel || '(' || att || ')'; 47 | return next out; 48 | end if; 49 | end; 50 | $$ language plpgsql; 51 | -------------------------------------------------------------------------------- /19T2/Prac Exercises/p02/schema1.sql: -------------------------------------------------------------------------------- 1 | -- atttypmod records type-specific data supplied at table creation time (for example, the maximum length of a varchar column) 2 | 3 | drop type if exists SchemaTuple cascade; 4 | create type SchemaTuple as ("table" text, "attributes" text); 5 | 6 | create or replace function schema1() returns setof SchemaTuple 7 | as $$ 8 | declare 9 | rec record; 10 | rel text := ''; 11 | attr text := ''; 12 | attrs text := ''; 13 | out SchemaTuple; 14 | len integer := 0; 15 | begin 16 | for rec in 17 | select r.relname, a.attname, t.typname, a.atttypmod 18 | from pg_class r 19 | join pg_namespace n on (r.relnamespace = n.oid) 20 | join pg_attribute a on (a.attrelid = r.oid) 21 | join pg_type t on (a.atttypid = t.oid) 22 | where r.relkind='r' 23 | and n.nspname = 'public' 24 | and attnum > 0 25 | order by relname,attnum 26 | loop 27 | if (rec.relname <> rel) then 28 | if (rel <> '') then 29 | out."table" := rel; -- set out.table 30 | out.attributes := attrs; -- set out.attributes 31 | return next out; 32 | end if; 33 | rel := rec.relname; 34 | attrs := ''; 35 | len := 0; 36 | end if; 37 | if (attrs <> '') then 38 | attrs := attrs || ', '; 39 | len := len + 2; 40 | end if; 41 | -- Add data type description 42 | if (rec.typname = 'varchar') then 43 | rec.typname := 'varchar('||(rec.atttypmod-4)||')'; 44 | elsif (rec.typname = 'bpchar') then 45 | rec.typname := 'char('||(rec.atttypmod-4)||')'; 46 | elsif (rec.typname = 'int4') then 47 | rec.typname := 'integer'; 48 | elsif (rec.typname = 'float8') then 49 | rec.typname := 'float'; 50 | end if; 51 | attr := rec.attname||':'||rec.typname; -- attr includes attr name + data type 52 | if (len + length(attr) > 50) then 53 | attrs := attrs || E'\n'; 54 | len := 0; 55 | end if; 56 | attrs := attrs || attr; 57 | len := len + length(attr); 58 | end loop; 59 | -- deal with last table 60 | if (rel <> '') then 61 | out."table" := rel; 62 | out.attributes := attrs; 63 | return next out; 64 | end if; 65 | end; 66 | $$ language plpgsql; 67 | -------------------------------------------------------------------------------- /19T2/Prac Exercises/p03/COMP9315 19T2 - Prac Exercise 03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Prac Exercises/p03/COMP9315 19T2 - Prac Exercise 03.pdf -------------------------------------------------------------------------------- /19T2/Prac Exercises/p03/load.out: -------------------------------------------------------------------------------- 1 | SET 2 | SET 3 | SET 4 | SET 5 | SET 6 | SET 7 | SET 8 | CREATE TYPE 9 | CREATE FUNCTION 10 | SET 11 | SET 12 | CREATE TABLE 13 | CREATE TABLE 14 | CREATE TABLE 15 | CREATE TABLE 16 | CREATE TABLE 17 | COPY 14098 18 | COPY 980 19 | COPY 3506 20 | COPY 3931 21 | COPY 1980 22 | ALTER TABLE 23 | ALTER TABLE 24 | ALTER TABLE 25 | ALTER TABLE 26 | ALTER TABLE 27 | ALTER TABLE 28 | ALTER TABLE 29 | ALTER TABLE 30 | ALTER TABLE 31 | ALTER TABLE 32 | ALTER TABLE 33 | -------------------------------------------------------------------------------- /19T2/Prac Exercises/p03/pop.sql: -------------------------------------------------------------------------------- 1 | create language plpgsql; 2 | 3 | create type TableInfo as ("table" text, ntuples int); 4 | 5 | -- show how many tuples are in each table 6 | 7 | create or replace function 8 | pop() returns setof TableInfo 9 | as $$ 10 | declare 11 | r record; 12 | nr integer; 13 | res TableInfo; 14 | begin 15 | for r in select tablename 16 | from pg_tables 17 | where schemaname = 'public' 18 | order by tablename 19 | loop 20 | execute 'select count(*) from ' 21 | ||quote_ident(r.tablename) into nr; 22 | res."table" := r.tablename::text; 23 | res.ntuples := nr::int; 24 | return next res; 25 | end loop; 26 | return; 27 | end; 28 | $$ 29 | language plpgsql; 30 | 31 | -------------------------------------------------------------------------------- /19T2/Prac Exercises/p03/schema.sql: -------------------------------------------------------------------------------- 1 | create table People ( 2 | id integer, 3 | ptype varchar(10), 4 | title varchar(5), 5 | family varchar(40), 6 | given varchar(50), 7 | street varchar(40), 8 | suburb varchar(30), 9 | pcode integer, 10 | gender char(1) check (gender in ('m','f')), 11 | birthday date, 12 | country char(3), 13 | primary key (id) 14 | ); 15 | 16 | create table Courses ( 17 | id integer, 18 | code char(8) check (code ~ '[A-Z]{4}[0-9]{4}'), 19 | title varchar(50), 20 | uoc integer check (uoc > 0), 21 | convenor integer references People(id), 22 | primary key (id) 23 | ); 24 | 25 | create table Enrolments ( 26 | course integer references Courses(id), 27 | student integer references People(id), 28 | mark integer check (mark between 0 and 100), 29 | grade char(2) check (grade in ('HD','DN','CR','PS','FL')), 30 | primary key (course,student) 31 | ); 32 | 33 | create table Items ( 34 | id integer, 35 | course integer references Courses(id), 36 | name varchar(20), 37 | maxMark integer check (maxMark > 0), 38 | primary key (id) 39 | ); 40 | 41 | create table Assessments ( 42 | item integer references Items(id), 43 | student integer references People(id), 44 | mark integer check (mark >= 0), 45 | primary key (item,student) 46 | ); 47 | -------------------------------------------------------------------------------- /19T2/Prac Exercises/p04/COMP9315 19T2 - Prac Exercise 04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Prac Exercises/p04/COMP9315 19T2 - Prac Exercise 04.pdf -------------------------------------------------------------------------------- /19T2/Prac Exercises/p04/LogData: -------------------------------------------------------------------------------- 1 | John Monday 09:00 17:00 2 | John Tuesday 09:00 16:30 3 | John Wednesday 08:30 17:00 4 | John Thursday 09:15 16:45 5 | John Friday 08:30 18:00 6 | Jane Monday 08:30 17:15 7 | Jane Tuesday 08:45 17:30 8 | Jane Wednesday 09:00 18:00 9 | Jane Thursday 08:45 17:30 10 | Jane Friday 08:30 16:00 11 | -------------------------------------------------------------------------------- /19T2/Prac Exercises/p05/COMP9315 19T2 - Prac Exercise 05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Prac Exercises/p05/COMP9315 19T2 - Prac Exercise 05.pdf -------------------------------------------------------------------------------- /19T2/README.md: -------------------------------------------------------------------------------- 1 | # DBMS Implementation COMP9315 19T2 2 | 3 | ## Course Summary 4 | This course aims to introduce students to the detailed internal structure of database management systems (DBMSs) such as Oracle or SQL Server. DBMSs contain a variety of interesting data structures and algorithms that are also potentially useful outside the DBMS context; knowing about them is a useful way of extending your general programming background. While the focus is on relational DBMSs, given that they have the best-developed technological foundation, we will also consider more recent developments in the management of large data repositories. 5 | 6 | Relational DBMSs need to deal with a variety of issues: storage structures and management, implementation of relational operations, query optimisation, transactions, concurrency, recovery, security. The course will address most of these, along with a brief look at emerging database systems trends. The level of detail on individual topics will vary; some will be covered in significant detail, others will be covered relatively briefly. 7 | 8 | An important aspect of this course is to give you a chance to undertake an in-depth exploration of the internals of a real DBMS: PostgreSQL. Lectures will discuss the general principles of how DBMSs are implemented, and will also illustrate them with examples from PostgreSQL where possible. 9 | 10 | -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 18s2 - Exercises 01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 18s2 - Exercises 01.pdf -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 18s2 - Exercises 02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 18s2 - Exercises 02.pdf -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 18s2 - Exercises 03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 18s2 - Exercises 03.pdf -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 18s2 - Exercises 04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 18s2 - Exercises 04.pdf -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 18s2 - Exercises 05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 18s2 - Exercises 05.pdf -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 18s2 - Exercises 06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 18s2 - Exercises 06.pdf -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 18s2 - Exercises 07.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 18s2 - Exercises 07.pdf -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 19T2 - Exercises 08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 19T2 - Exercises 08.pdf -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 19T2 - Exercises 09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 19T2 - Exercises 09.pdf -------------------------------------------------------------------------------- /19T2/Theory Exercises/COMP9315 19T2 - Exercises 10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weil0819/COMP9315/2da6f617cf4b67e048959d0b160f70220cb2c850/19T2/Theory Exercises/COMP9315 19T2 - Exercises 10.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # COMP9315 Database Systems Implementation (6 Units of Credit) 2 | 3 | Detailed examination of techniques used in the implementation of relational, object-oriented and distributed database systems. Topics are drawn from: query optimisation, transaction management, advanced file access methods, database performance tuning. 4 | 5 | ## Conditions for Enrolment 6 | Prerequisite: COMP9024 and COMP9311. 7 | 8 | --------------------------------------------------------------------------------