From e8003f15d777adf76e40d160785d68d47aa2b9e1 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Mon, 4 Jan 2021 00:16:58 -0500 Subject: [PATCH] Basic sqlite Implementation --- .gitignore | 1 + cmd/cmd.go | 16 ++++++ db/imagini.db | Bin 0 -> 32768 bytes db/schemas/imagini.db.bak | Bin 0 -> 32768 bytes db/schemas/sqlite-create.sql | 53 ++++++++++++++++++ db/schemas/sqlite-testdata.sql | 23 ++++++++ db/sqlite.go | 95 +++++++++++++++++++++++++++++++++ db/sqlite.sql | 53 ------------------ go.mod | 1 + go.sum | 2 + main.go | 1 + web/App.vue | 3 -- 12 files changed, 192 insertions(+), 56 deletions(-) create mode 100644 db/imagini.db create mode 100644 db/schemas/imagini.db.bak create mode 100644 db/schemas/sqlite-create.sql create mode 100644 db/schemas/sqlite-testdata.sql create mode 100644 db/sqlite.go delete mode 100644 db/sqlite.sql delete mode 100644 web/App.vue diff --git a/.gitignore b/.gitignore index e0f5045..1575361 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ notes web/node_modules/ +web/dist/ diff --git a/cmd/cmd.go b/cmd/cmd.go index 7e15b34..6c20330 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -2,9 +2,12 @@ package cmd import ( "reichard.io/imagini/routes" + "reichard.io/imagini/db" + "github.com/urfave/cli/v2" "net/http" "log" + "fmt" ) var CmdServe = cli.Command{ @@ -14,6 +17,13 @@ var CmdServe = cli.Command{ Action: serveWeb, } +var CmdDBTest = cli.Command{ + Name: "db", + Aliases: []string{"d"}, + Usage: "test db.", + Action: testDatabase, +} + func serveWeb(ctx *cli.Context) error { routes.RegisterRoutes() @@ -22,3 +32,9 @@ func serveWeb(ctx *cli.Context) error { } return nil } + +func testDatabase(ctx *cli.Context) error { + resp := db.ItemsFromAlbum(1, 3) + fmt.Printf("%v", resp) + return nil +} diff --git a/db/imagini.db b/db/imagini.db new file mode 100644 index 0000000000000000000000000000000000000000..5b8aafa4924360b2830d29a400191713a08bdff7 GIT binary patch literal 32768 zcmeI*Pfy!s90%~{u|tj175BoToOmiO34@S-{FSOgsj1QdWx;H%A`TCUml!#5WE<4p z3f&9XWp85dVW&xb1=F;9FS~S?Nt?9O9@~LnNU9trSoB@X_DLc`HqMx$tOh9C%(V4 z^4Tx9|GK>>-eQ9Q1Rwwb2tWV=5cppUoLY*Knx3Yw(>_16&26(`@pb#~xb0m!9p9+x z>xRyZ^@m$Jt6hp5uuM{|wS!ufM+dC3W9X0dD%*K#u$}#_tyvM|L2HA9Ol+G^t9s?} z4*ODn&N97*vaG6a>Q#MbL*HXzZx!Ecdl%v4wTit?Vilt_GUuUW_VoTOC6!Lov;8pF zC?35k@eHHFD7jw!esa6j%JzEoc`)MHa3r;3&vb`pSnKe%dB6<)nLxRKxt2oINGyYW z(XN;21;qGkV@hgjioPD}&y~TO(M$y=x8hlZazXhBv*h#U@C-i89EDxP@(ae6iHeii zdO}G}PSVqCm|PGF_OWi+QS>zb4 z>Wi_mD~tnXFUZ?$bIXoK9R6)N_FGZPSMDyg=5gEaU)bVa%WUj^vv*M{Zl`6cq_SCh z_C+}8J<~lg-96LytxnU6zmwu=#Dh^jUR3e&O*C3c4b!W;R@b+j&b6sfYbV@3zPetL z+2Gk+JoICO00bZa0SG_<0uX=z1Rwwb2teQ?76_jIW$hKwe${>y2W$|400bZa0SG_< z0uX=z1Rwwb2>b^E8CfBdbK>hN4=vk16#JU_g15W2nX5bPEvL@yLa|g1_8Cbbsd;hb z6Y(V=?&vrIADVS1Rwwb2tWV= z5P$##AOHaf+&qCJStazrgZaYvv|P*=%5(YBTye!HL-`XGA+nYDV7!d>@009U<00Izz00bZa0SG_< z0wW2ivP{xlo7YWGkz_L2aGIV%#YvsJUiAF`j%fdAe`@bWY7ZAd00Izz00bZa0SG_< z0uX=z1R!ve1roAMRe4O3DV3xIl~pQ7&;M_T_Ph3*_U0xJ9%F+51Rwwb2tWV=5P$## zAOHafeCh&s3yYLTQ2+n{ literal 0 HcmV?d00001 diff --git a/db/schemas/imagini.db.bak b/db/schemas/imagini.db.bak new file mode 100644 index 0000000000000000000000000000000000000000..5b8aafa4924360b2830d29a400191713a08bdff7 GIT binary patch literal 32768 zcmeI*Pfy!s90%~{u|tj175BoToOmiO34@S-{FSOgsj1QdWx;H%A`TCUml!#5WE<4p z3f&9XWp85dVW&xb1=F;9FS~S?Nt?9O9@~LnNU9trSoB@X_DLc`HqMx$tOh9C%(V4 z^4Tx9|GK>>-eQ9Q1Rwwb2tWV=5cppUoLY*Knx3Yw(>_16&26(`@pb#~xb0m!9p9+x z>xRyZ^@m$Jt6hp5uuM{|wS!ufM+dC3W9X0dD%*K#u$}#_tyvM|L2HA9Ol+G^t9s?} z4*ODn&N97*vaG6a>Q#MbL*HXzZx!Ecdl%v4wTit?Vilt_GUuUW_VoTOC6!Lov;8pF zC?35k@eHHFD7jw!esa6j%JzEoc`)MHa3r;3&vb`pSnKe%dB6<)nLxRKxt2oINGyYW z(XN;21;qGkV@hgjioPD}&y~TO(M$y=x8hlZazXhBv*h#U@C-i89EDxP@(ae6iHeii zdO}G}PSVqCm|PGF_OWi+QS>zb4 z>Wi_mD~tnXFUZ?$bIXoK9R6)N_FGZPSMDyg=5gEaU)bVa%WUj^vv*M{Zl`6cq_SCh z_C+}8J<~lg-96LytxnU6zmwu=#Dh^jUR3e&O*C3c4b!W;R@b+j&b6sfYbV@3zPetL z+2Gk+JoICO00bZa0SG_<0uX=z1Rwwb2teQ?76_jIW$hKwe${>y2W$|400bZa0SG_< z0uX=z1Rwwb2>b^E8CfBdbK>hN4=vk16#JU_g15W2nX5bPEvL@yLa|g1_8Cbbsd;hb z6Y(V=?&vrIADVS1Rwwb2tWV= z5P$##AOHaf+&qCJStazrgZaYvv|P*=%5(YBTye!HL-`XGA+nYDV7!d>@009U<00Izz00bZa0SG_< z0wW2ivP{xlo7YWGkz_L2aGIV%#YvsJUiAF`j%fdAe`@bWY7ZAd00Izz00bZa0SG_< z0uX=z1R!ve1roAMRe4O3DV3xIl~pQ7&;M_T_Ph3*_U0xJ9%F+51Rwwb2tWV=5P$## zAOHafeCh&s3yYLTQ2+n{ literal 0 HcmV?d00001 diff --git a/db/schemas/sqlite-create.sql b/db/schemas/sqlite-create.sql new file mode 100644 index 0000000..c958876 --- /dev/null +++ b/db/schemas/sqlite-create.sql @@ -0,0 +1,53 @@ +CREATE TABLE IF NOT EXISTS [ServerSettings] ( + [settingID] INTEGER PRIMARY KEY, + [name] TEXT NOT NULL, + [description] TEXT NOT NULL, + [value] TEXT NOT NULL +); + +CREATE TABLE IF NOT EXISTS [Users] ( + [userID] INTEGER PRIMARY KEY, + [name] TEXT NOT NULL, + [email] TEXT, + [authType] TEXT NOT NULL, + [salt] TEXT, + [hashedPWSalt] TEXT +); + +CREATE TABLE IF NOT EXISTS [MediaItems] ( + [mediaID] INTEGER PRIMARY KEY, + [userID] INTEGER NOT NULL, + [EXIFDate] TEXT NOT NULL, + [uploadDate] TEXT NOT NULL, + [latitude] TEXT, + [longitude] TEXT, + [mediaType] INTEGER, /* 0 = Photo, 1 = Video */ + [relPath] TEXT NOT NULL, + FOREIGN KEY (userID) REFERENCES Users(userID) +); + +CREATE TABLE IF NOT EXISTS [Tags] ( + [tagID] INTEGER PRIMARY KEY, + [name] TEXT NOT NULL +); + +CREATE TABLE IF NOT EXISTS [MediaTags] ( + [mediaID] INTEGER NOT NULL, + [tagID] INTEGER NOT NULL, + FOREIGN KEY (mediaID) REFERENCES MediaItems(mediaID) + FOREIGN KEY (tagID) REFERENCES Tags(tagID) +); + +CREATE TABLE IF NOT EXISTS [Albums] ( + [albumID] INTEGER PRIMARY KEY, + [userID] INTEGER NOT NULL, + [name] TEXT NOT NULL, + FOREIGN KEY (userID) REFERENCES Users(userID) +); + +CREATE TABLE IF NOT EXISTS [MediaAlbums] ( + [mediaID] INTEGER NOT NULL, + [albumID] INTEGER NOT NULL, + FOREIGN KEY (mediaID) REFERENCES MediaItems(mediaID) + FOREIGN KEY (albumID) REFERENCES Albums(albumID) +); diff --git a/db/schemas/sqlite-testdata.sql b/db/schemas/sqlite-testdata.sql new file mode 100644 index 0000000..beb9574 --- /dev/null +++ b/db/schemas/sqlite-testdata.sql @@ -0,0 +1,23 @@ +INSERT INTO Users (name, email, authType, salt, hashedPWSalt) VALUES ("Evan", "evan@reichard.io", "Local", "1234", "1234"); +INSERT INTO Users (name, email, authType, salt, hashedPWSalt) VALUES ("James", "james@example.com", "Local", "1234", "1234"); +INSERT INTO Users (name, email, authType, salt, hashedPWSalt) VALUES ("Bill", "bill@example.com", "Local", "1234", "1234"); + +INSERT INTO MediaItems (userID, EXIFDate, uploadDate, latitude, longitude, mediaType, relPath) VALUES (1, "2012-03-29T10:05:45-06:00", "2012-03-29T10:05:45-06:00", "38.94141753254032", "-77.45238664604386", 0, "/image1.jpg"); +INSERT INTO MediaItems (userID, EXIFDate, uploadDate, latitude, longitude, mediaType, relPath) VALUES (2, "2013-03-29T10:05:45-06:00", "2013-03-29T10:05:45-06:00", "38.94141753254032", "-77.45238664604386", 0, "/image2.jpg"); +INSERT INTO MediaItems (userID, EXIFDate, uploadDate, latitude, longitude, mediaType, relPath) VALUES (3, "2014-03-29T10:05:45-06:00", "2014-03-29T10:05:45-06:00", "38.94141753254032", "-77.45238664604386", 0, "/image3.jpg"); + +INSERT INTO Tags (name) VALUES ("cars"); +INSERT INTO Tags (name) VALUES ("dogs"); +INSERT INTO Tags (name) VALUES ("places"); + +INSERT INTO Albums (userID, name) VALUES (1, "My Favorite Things"); +INSERT INTO Albums (userID, name) VALUES (2, "Trip 2020"); +INSERT INTO Albums (userID, name) VALUES (3, "Corona 2020"); + +INSERT INTO MediaTags (mediaID, tagID) VALUES (1, 3); +INSERT INTO MediaTags (mediaID, tagID) VALUES (2, 2); +INSERT INTO MediaTags (mediaID, tagID) VALUES (3, 1); + +INSERT INTO MediaAlbums (mediaID, albumID) VALUES (1, 3); +INSERT INTO MediaAlbums (mediaID, albumID) VALUES (2, 2); +INSERT INTO MediaAlbums (mediaID, albumID) VALUES (3, 1); diff --git a/db/sqlite.go b/db/sqlite.go new file mode 100644 index 0000000..0eb70ff --- /dev/null +++ b/db/sqlite.go @@ -0,0 +1,95 @@ +package db + +import ( + "database/sql" + "log" + + _ "github.com/mattn/go-sqlite3" +) + +type MediaItem struct { + mediaID int + userID int + EXIFDate string + uploadDate string + latitude string + longitude string + mediaType int + relPath string +} + +func init() { + // Initialize DB +} + +func ItemsFromAlbum(userID int, albumID int) []MediaItem { + database, _ := sql.Open("sqlite3", "./db/imagini.db") + rows, _ := database.Query(` + SELECT + MediaItems.* + FROM + MediaAlbums + INNER JOIN MediaItems ON MediaAlbums.mediaID = MediaItems.mediaID + WHERE MediaAlbums.albumID = ? AND MediaItems.userID = ?`, albumID, userID) + + var matchingMediaItems []MediaItem + var mi MediaItem + for rows.Next() { + err := rows.Scan(&mi.mediaID, &mi.userID, &mi.EXIFDate, &mi.uploadDate, &mi.latitude, &mi.longitude, &mi.mediaType, &mi.relPath) + if err != nil { + log.Fatal(err) + } + matchingMediaItems = append(matchingMediaItems, mi) + } + rows.Close() + return matchingMediaItems +} + +func ItemsFromTags(userID int, tagID int) []MediaItem { + database, _ := sql.Open("sqlite3", "./db/imagini.db") + rows, _ := database.Query(` + SELECT + MediaItems.* + FROM + MediaTags + INNER JOIN MediaItems ON MediaTags.mediaID = MediaItems.mediaID + WHERE MediaTags.tagID = ? AND MediaItems.userID = ?`, tagID, userID) + + var matchingMediaItems []MediaItem + var mi MediaItem + for rows.Next() { + err := rows.Scan(&mi.mediaID, &mi.userID, &mi.EXIFDate, &mi.uploadDate, &mi.latitude, &mi.longitude, &mi.mediaType, &mi.relPath) + if err != nil { + log.Fatal(err) + } + matchingMediaItems = append(matchingMediaItems, mi) + } + rows.Close() + return matchingMediaItems +} + +func IndexMediaItems(newItems []MediaItem) { + database, _ := sql.Open("sqlite3", "./db/imagini.db") + statement, _ := database.Prepare(` + INSERT INTO MediaItems ( + userID, + EXIFDate + uploadDate, + latitude, + longitude, + mediaType, + relPath + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`) + for _, s := range newItems { + statement.Exec( + &s.userID, + &s.EXIFDate, + &s.uploadDate, + &s.latitude, + &s.longitude, + &s.mediaType, + &s.relPath, + ) + } + database.Close() +} diff --git a/db/sqlite.sql b/db/sqlite.sql deleted file mode 100644 index d1a8564..0000000 --- a/db/sqlite.sql +++ /dev/null @@ -1,53 +0,0 @@ -CREATE TABLE IF NOT EXISTS [ServerSettings] ( - [SettingID] INTEGER PRIMARY KEY, - [Name] TEXT NOT NULL, - [Description] TEXT NOT NULL, - [Value] TEXT NOT NULL -); - -CREATE TABLE IF NOT EXISTS [Users] ( - [UserID] INTEGER PRIMARY KEY, - [Name] TEXT NOT NULL, - [Email] TEXT, - [AuthType] TEXT NOT NULL, - [Salt] TEXT, - [HashedPWSalt] TEXT -); - -CREATE TABLE IF NOT EXISTS [Items] ( - [ItemID] INTEGER PRIMARY KEY, - [UserID] INTEGER NOT NULL, - [EXIFDate] TEXT NOT NULL, - [UploadDate] TEXT NOT NULL, - [Latitude] TEXT, - [Longitude] TEXT, - [Type] INTEGER, /* 0 = Photo, 1 = Video */ - [RelPath] TEXT NOT NULL, - FOREIGN KEY (UserID) REFERENCES Users(UserID) -); - -CREATE TABLE IF NOT EXISTS [Tags] ( - [TagID] INTEGER PRIMARY KEY, - [TagName] TEXT NOT NULL -); - -CREATE TABLE IF NOT EXISTS [ItemTags] ( - [ItemID] INTEGER NOT NULL, - [TagID] INTEGER NOT NULL, - FOREIGN KEY (ItemID) REFERENCES Items(ItemID) - FOREIGN KEY (TagID) REFERENCES Tags(TagID) -); - -CREATE TABLE IF NOT EXISTS [Albums] ( - [AlbumID] INTEGER PRIMARY KEY, - [UserID] INTEGER NOT NULL, - [Name] TEXT NOT NULL, - FOREIGN KEY (UserID) REFERENCES Users(UserID) -); - -CREATE TABLE IF NOT EXISTS [ItemAlbums] ( - [ItemID] INTEGER NOT NULL, - [AlbumID] INTEGER NOT NULL, - FOREIGN KEY (ItemID) REFERENCES Items(ItemID) - FOREIGN KEY (AlbumID) REFERENCES Albums(AlbumID) -); diff --git a/go.mod b/go.mod index 2e17d90..8fdabfd 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module reichard.io/imagini go 1.15 require ( + github.com/mattn/go-sqlite3 v1.14.6 github.com/tus/tusd v1.4.0 github.com/urfave/cli/v2 v2.3.0 ) diff --git a/go.sum b/go.sum index a7c6ead..592ef1f 100644 --- a/go.sum +++ b/go.sum @@ -63,6 +63,8 @@ github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eT github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= diff --git a/main.go b/main.go index c9ad6da..de61315 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ func main() { Usage: "A self hosted photo library.", Commands: []*cli.Command{ &cmd.CmdServe, + &cmd.CmdDBTest, }, } diff --git a/web/App.vue b/web/App.vue deleted file mode 100644 index a3741b5..0000000 --- a/web/App.vue +++ /dev/null @@ -1,3 +0,0 @@ -