From 696ca9f45d34a535c42346efa68cee6fcb4f1a4d Mon Sep 17 00:00:00 2001 From: ichami630 Date: Thu, 3 Apr 2025 16:13:05 +0100 Subject: [PATCH 01/10] added some comments and the .env files --- .env.example | 2 +- api/api.go | 2 +- db/repo/db.go | 7 +++-- db/repo/querier.go | 4 ++- go.mod | 2 -- go.sum | 73 ++++++++++++++++++++++++++++++++++++---------- 6 files changed, 67 insertions(+), 23 deletions(-) diff --git a/.env.example b/.env.example index 55b129f..a69e7a9 100644 --- a/.env.example +++ b/.env.example @@ -9,4 +9,4 @@ DB_PORT=5432 DB_Name=messages DB_TLS_DISABLED=true -MIGRATIONS_PATH="./db/migrations" +MIGRATIONS_PATH="../../db/migrations" diff --git a/api/api.go b/api/api.go index ada2548..70ff45c 100644 --- a/api/api.go +++ b/api/api.go @@ -23,7 +23,7 @@ func (h *MessageHandler) WireHttpHandler() http.Handler { r.Use(gin.CustomRecovery(func(c *gin.Context, _ any) { c.String(http.StatusInternalServerError, "Internal Server Error: panic") c.AbortWithStatus(http.StatusInternalServerError) - })) + })) //prevents the server from crashing if an error occurs in any route r.POST("/message", h.handleCreateMessage) r.GET("/message/:id", h.handleGetMessage) diff --git a/db/repo/db.go b/db/repo/db.go index 19f8234..4a8205a 100644 --- a/db/repo/db.go +++ b/db/repo/db.go @@ -18,15 +18,16 @@ type DBTX interface { } func New(db DBTX) *Queries { - return &Queries{db: db} + return &Queries{db: db} //creates a new query struct and returns its memory address } type Queries struct { db DBTX -} +} //has a field db that stores something that implements DBTX func (q *Queries) WithTx(tx pgx.Tx) *Queries { return &Queries{ db: tx, } -} +}//creates a new Queries instance, but replaces db with a transaction(tx) +//instead of the regular database connection diff --git a/db/repo/querier.go b/db/repo/querier.go index 5b0504e..a58aae0 100644 --- a/db/repo/querier.go +++ b/db/repo/querier.go @@ -14,4 +14,6 @@ type Querier interface { GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) } -var _ Querier = (*Queries)(nil) +var _ Querier = (*Queries)(nil) //ensures that queries implements the querier interface +//This assigns nil of type *Queries to a variable of type Querier. +//If Queries does not implement all methods of Querier, the code will fail to compile. diff --git a/go.mod b/go.mod index 044585d..84f82e3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/golang-migrate/migrate/v4 v4.18.2 github.com/jackc/pgx/v5 v5.7.4 github.com/joho/godotenv v1.5.1 - github.com/rs/zerolog v1.34.0 ) require ( @@ -31,7 +30,6 @@ require ( github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/go.sum b/go.sum index cfed3a0..bced695 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,7 @@ +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ardanlabs/conf/v3 v3.4.0 h1:Qy7/doJjhsv7Lvzqd9tbvH8fAZ9jzqKtwnwcmZ+sxGs= github.com/ardanlabs/conf/v3 v3.4.0/go.mod h1:OIi6NK95fj8jKFPdZ/UmcPlY37JBg99hdP9o5XmNK9c= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= @@ -8,15 +12,33 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dhui/dktest v0.4.4 h1:+I4s6JRE1yGuqflzwqG+aIaMdgXIorCf5P98JnaAWa8= +github.com/dhui/dktest v0.4.4/go.mod h1:4+22R4lgsdAXrDyaH4Nqx2JEz2hLp49MqQmm9HLCQhM= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= +github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -25,9 +47,12 @@ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBEx github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-migrate/migrate/v4 v4.18.2 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8= github.com/golang-migrate/migrate/v4 v4.18.2/go.mod h1:2CM6tJvn2kqPXwnXO/d3rAQYiyoIm180VsO8PRX6Rpk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= @@ -50,28 +75,39 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= -github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= -github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -82,11 +118,20 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -94,25 +139,23 @@ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From a4cb957887ddf87a988f942b293f0c7d13f33391 Mon Sep 17 00:00:00 2001 From: ichami630 Date: Thu, 3 Apr 2025 22:35:35 +0100 Subject: [PATCH 02/10] added the delete route --- api/api.go | 16 ++++++++++++++++ db/query/message.sql | 5 ++++- db/repo/message.sql.go | 8 ++++++++ db/repo/querier.go | 1 + 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/api/api.go b/api/api.go index 70ff45c..484069d 100644 --- a/api/api.go +++ b/api/api.go @@ -28,6 +28,7 @@ func (h *MessageHandler) WireHttpHandler() http.Handler { r.POST("/message", h.handleCreateMessage) r.GET("/message/:id", h.handleGetMessage) r.GET("/thread/:id/messages", h.handleGetThreadMessages) + r.DELETE("/message/:id", h.handleDeleteMessage) return r } @@ -84,3 +85,18 @@ func (h *MessageHandler) handleGetThreadMessages(c *gin.Context) { "messages": messages, }) } + +func (h *MessageHandler) handleDeleteMessage(c *gin.Context) { + id := c.Param("id") + if id == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) + return + } + + if err := h.querier.DeleteMessage(c, id); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete message"}) + } + + c.JSON(http.StatusOK, gin.H{"message": "message deleted successfully"}) + +} diff --git a/db/query/message.sql b/db/query/message.sql index 1d34c69..3d7a09e 100644 --- a/db/query/message.sql +++ b/db/query/message.sql @@ -10,4 +10,7 @@ WHERE id = $1; -- name: GetMessagesByThread :many SELECT * FROM message WHERE thread = $1 -ORDER BY created_at DESC; \ No newline at end of file +ORDER BY created_at DESC; + +-- name: DeleteMessage : one +DELETE FROM message WHERE id = $1; \ No newline at end of file diff --git a/db/repo/message.sql.go b/db/repo/message.sql.go index ce74c13..dc1ad4f 100644 --- a/db/repo/message.sql.go +++ b/db/repo/message.sql.go @@ -52,11 +52,19 @@ func (q *Queries) GetMessageByID(ctx context.Context, id string) (Message, error return i, err } + const getMessagesByThread = `-- name: GetMessagesByThread :many SELECT id, thread, sender, content, created_at FROM message WHERE thread = $1 ORDER BY created_at DESC ` +const deleteMessage = `-- name: DeleteMessage : one +DELETE FROM message WHERE id = $1` + +func (q *Queries) DeleteMessage(ctx context.Context, id string) error{ + _,err := q.db.Exec(ctx,deleteMessage,id) + return err +} func (q *Queries) GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) { rows, err := q.db.Query(ctx, getMessagesByThread, thread) diff --git a/db/repo/querier.go b/db/repo/querier.go index a58aae0..99454db 100644 --- a/db/repo/querier.go +++ b/db/repo/querier.go @@ -12,6 +12,7 @@ type Querier interface { CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error) GetMessageByID(ctx context.Context, id string) (Message, error) GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) + DeleteMessage(ctx context.Context,id string) error } var _ Querier = (*Queries)(nil) //ensures that queries implements the querier interface From 7115ee62bbb9eac1c852cc9c1843606438b67235 Mon Sep 17 00:00:00 2001 From: ichami630 Date: Fri, 4 Apr 2025 10:49:50 +0100 Subject: [PATCH 03/10] added a patch request to update message content --- api/api.go | 16 ++++++++++++++++ db/query/message.sql | 10 ++++++++-- db/repo/db.go | 7 +++---- db/repo/message.sql.go | 34 ++++++++++++++++++++++++++-------- db/repo/querier.go | 7 +++---- 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/api/api.go b/api/api.go index 484069d..4e36d77 100644 --- a/api/api.go +++ b/api/api.go @@ -29,6 +29,7 @@ func (h *MessageHandler) WireHttpHandler() http.Handler { r.GET("/message/:id", h.handleGetMessage) r.GET("/thread/:id/messages", h.handleGetThreadMessages) r.DELETE("/message/:id", h.handleDeleteMessage) + r.PATCH("/message", h.handleUpdateMessage) return r } @@ -100,3 +101,18 @@ func (h *MessageHandler) handleDeleteMessage(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "message deleted successfully"}) } + +func (h *MessageHandler) handleUpdateMessage(c *gin.Context) { + var req repo.UpdateMessageParams + if err := c.ShouldBindBodyWithJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if err := h.querier.UpdateMessage(c, req); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"success": "Message updated successfully"}) +} diff --git a/db/query/message.sql b/db/query/message.sql index 3d7a09e..68f9b85 100644 --- a/db/query/message.sql +++ b/db/query/message.sql @@ -12,5 +12,11 @@ SELECT * FROM message WHERE thread = $1 ORDER BY created_at DESC; --- name: DeleteMessage : one -DELETE FROM message WHERE id = $1; \ No newline at end of file +-- name: DeleteMessage :exec +DELETE FROM message WHERE id = $1; + +-- name: UpdateMessage :exec +UPDATE message +SET content = $2 +WHERE id = $1 +RETURNING *; \ No newline at end of file diff --git a/db/repo/db.go b/db/repo/db.go index 4a8205a..19f8234 100644 --- a/db/repo/db.go +++ b/db/repo/db.go @@ -18,16 +18,15 @@ type DBTX interface { } func New(db DBTX) *Queries { - return &Queries{db: db} //creates a new query struct and returns its memory address + return &Queries{db: db} } type Queries struct { db DBTX -} //has a field db that stores something that implements DBTX +} func (q *Queries) WithTx(tx pgx.Tx) *Queries { return &Queries{ db: tx, } -}//creates a new Queries instance, but replaces db with a transaction(tx) -//instead of the regular database connection +} diff --git a/db/repo/message.sql.go b/db/repo/message.sql.go index dc1ad4f..e08bd7b 100644 --- a/db/repo/message.sql.go +++ b/db/repo/message.sql.go @@ -34,6 +34,15 @@ func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessageParams) (M return i, err } +const deleteMessage = `-- name: DeleteMessage :exec +DELETE FROM message WHERE id = $1 +` + +func (q *Queries) DeleteMessage(ctx context.Context, id string) error { + _, err := q.db.Exec(ctx, deleteMessage, id) + return err +} + const getMessageByID = `-- name: GetMessageByID :one SELECT id, thread, sender, content, created_at FROM message WHERE id = $1 @@ -52,19 +61,11 @@ func (q *Queries) GetMessageByID(ctx context.Context, id string) (Message, error return i, err } - const getMessagesByThread = `-- name: GetMessagesByThread :many SELECT id, thread, sender, content, created_at FROM message WHERE thread = $1 ORDER BY created_at DESC ` -const deleteMessage = `-- name: DeleteMessage : one -DELETE FROM message WHERE id = $1` - -func (q *Queries) DeleteMessage(ctx context.Context, id string) error{ - _,err := q.db.Exec(ctx,deleteMessage,id) - return err -} func (q *Queries) GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) { rows, err := q.db.Query(ctx, getMessagesByThread, thread) @@ -91,3 +92,20 @@ func (q *Queries) GetMessagesByThread(ctx context.Context, thread string) ([]Mes } return items, nil } + +const updateMessage = `-- name: UpdateMessage :exec +UPDATE message +SET content = $2 +WHERE id = $1 +RETURNING id, thread, sender, content, created_at +` + +type UpdateMessageParams struct { + ID string `json:"id"` + Content string `json:"content"` +} + +func (q *Queries) UpdateMessage(ctx context.Context, arg UpdateMessageParams) error { + _, err := q.db.Exec(ctx, updateMessage, arg.ID, arg.Content) + return err +} diff --git a/db/repo/querier.go b/db/repo/querier.go index 99454db..9486692 100644 --- a/db/repo/querier.go +++ b/db/repo/querier.go @@ -10,11 +10,10 @@ import ( type Querier interface { CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error) + DeleteMessage(ctx context.Context, id string) error GetMessageByID(ctx context.Context, id string) (Message, error) GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) - DeleteMessage(ctx context.Context,id string) error + UpdateMessage(ctx context.Context, arg UpdateMessageParams) error } -var _ Querier = (*Queries)(nil) //ensures that queries implements the querier interface -//This assigns nil of type *Queries to a variable of type Querier. -//If Queries does not implement all methods of Querier, the code will fail to compile. +var _ Querier = (*Queries)(nil) From 387f8bb497422bf400e2dee5d7e822e1937a6773 Mon Sep 17 00:00:00 2001 From: ichami630 Date: Fri, 4 Apr 2025 15:54:12 +0100 Subject: [PATCH 04/10] added a delete --- db/query/message.sql | 5 ++++- db/repo/message.sql.go | 9 +++++++++ db/repo/querier.go | 1 + go.sum | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/db/query/message.sql b/db/query/message.sql index 68f9b85..bbe7889 100644 --- a/db/query/message.sql +++ b/db/query/message.sql @@ -19,4 +19,7 @@ DELETE FROM message WHERE id = $1; UPDATE message SET content = $2 WHERE id = $1 -RETURNING *; \ No newline at end of file +RETURNING *; + +-- name: DeleteAll :exec +DELETE FROM message; \ No newline at end of file diff --git a/db/repo/message.sql.go b/db/repo/message.sql.go index e08bd7b..49bb559 100644 --- a/db/repo/message.sql.go +++ b/db/repo/message.sql.go @@ -34,6 +34,15 @@ func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessageParams) (M return i, err } +const deleteAll = `-- name: DeleteAll :exec +DELETE FROM message +` + +func (q *Queries) DeleteAll(ctx context.Context) error { + _, err := q.db.Exec(ctx, deleteAll) + return err +} + const deleteMessage = `-- name: DeleteMessage :exec DELETE FROM message WHERE id = $1 ` diff --git a/db/repo/querier.go b/db/repo/querier.go index 9486692..ece582a 100644 --- a/db/repo/querier.go +++ b/db/repo/querier.go @@ -10,6 +10,7 @@ import ( type Querier interface { CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error) + DeleteAll(ctx context.Context) error DeleteMessage(ctx context.Context, id string) error GetMessageByID(ctx context.Context, id string) (Message, error) GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) diff --git a/go.sum b/go.sum index bced695..bfa8f3c 100644 --- a/go.sum +++ b/go.sum @@ -4,12 +4,20 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ardanlabs/conf/v3 v3.4.0 h1:Qy7/doJjhsv7Lvzqd9tbvH8fAZ9jzqKtwnwcmZ+sxGs= github.com/ardanlabs/conf/v3 v3.4.0/go.mod h1:OIi6NK95fj8jKFPdZ/UmcPlY37JBg99hdP9o5XmNK9c= +github.com/ardanlabs/conf/v3 v3.6.0 h1:lyp86FblrH34n+XLCHz6di5vImdGb3uypWPy5HYNNzI= +github.com/ardanlabs/conf/v3 v3.6.0/go.mod h1:IIucqD+601gt3jfhMXVukxoT16LnoGVd2DzRC2GhHiA= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= +github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= +github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= +github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -29,8 +37,12 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E= +github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= @@ -45,8 +57,12 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= +github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-migrate/migrate/v4 v4.18.2 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8= @@ -74,6 +90,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -102,6 +120,8 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -120,6 +140,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -134,25 +156,41 @@ go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt3 go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= +golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From c6831bfa4235b804dde15543e8783ca7a3e584b1 Mon Sep 17 00:00:00 2001 From: ichami630 Date: Sat, 5 Apr 2025 10:30:39 +0100 Subject: [PATCH 05/10] added the thread table with fk_constraint in message table --- db/migrations/000002_init_thread_and_fk.up.sql | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 db/migrations/000002_init_thread_and_fk.up.sql diff --git a/db/migrations/000002_init_thread_and_fk.up.sql b/db/migrations/000002_init_thread_and_fk.up.sql new file mode 100644 index 0000000..a734fdf --- /dev/null +++ b/db/migrations/000002_init_thread_and_fk.up.sql @@ -0,0 +1,15 @@ +-- create thread table +CREATE TABLE IF NOT EXISTS thread ( + id SERIAL PRIMARY KEY, + title VARCHAR(64) NOT NULL, + created_at TIMESTAMPTZ DEFAULT now() +); + +-- modify table message +ALTER TABLE message DROP COLUMN thread; + +ALTER TABLE message ADD COLUMN thread_id INT NOT NULL; + +-- add foreign key contrain +ALTER TABLE message ADD CONSTRAINT fk_thread_id +FOREIGN KEY (thread_id) REFERENCES thread(id) ON DELETE CASCADE; \ No newline at end of file From 5420eaa98fc50ec74a1b446366de736215cf1bb9 Mon Sep 17 00:00:00 2001 From: ichami630 Date: Sat, 5 Apr 2025 12:28:47 +0100 Subject: [PATCH 06/10] configured the thread endpoint --- api/api.go | 89 +++++++++++------- db/migrations/000003_init_drop_sender.up.sql | 2 + db/query/message.sql | 52 +++++++++-- db/repo/message.sql.go | 94 ++++++++++++++------ db/repo/models.go | 9 +- db/repo/querier.go | 31 ++++++- 6 files changed, 203 insertions(+), 74 deletions(-) create mode 100644 db/migrations/000003_init_drop_sender.up.sql diff --git a/api/api.go b/api/api.go index 4e36d77..31244c7 100644 --- a/api/api.go +++ b/api/api.go @@ -25,40 +25,45 @@ func (h *MessageHandler) WireHttpHandler() http.Handler { c.AbortWithStatus(http.StatusInternalServerError) })) //prevents the server from crashing if an error occurs in any route + r.POST("/thread", h.handleCreateThread) r.POST("/message", h.handleCreateMessage) r.GET("/message/:id", h.handleGetMessage) - r.GET("/thread/:id/messages", h.handleGetThreadMessages) - r.DELETE("/message/:id", h.handleDeleteMessage) + // r.GET("/thread/:id/messages", h.handleGetThreadMessages) + // r.DELETE("/message/:id", h.handleDeleteMessage) r.PATCH("/message", h.handleUpdateMessage) return r } -func (h *MessageHandler) handleCreateMessage(c *gin.Context) { - var req repo.CreateMessageParams - err := c.ShouldBindBodyWithJSON(&req) - if err != nil { +type CreateThreadParams struct { + Title string `json:"title"` +} + +func (h *MessageHandler) handleCreateThread(c *gin.Context) { + var req CreateThreadParams + if err := c.ShouldBindBodyWithJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } - message, err := h.querier.CreateMessage(c, req) + thread, err := h.querier.CreateThread(c, req.Title) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } - c.JSON(http.StatusOK, message) + c.JSON(http.StatusOK, thread) } -func (h *MessageHandler) handleGetMessage(c *gin.Context) { - id := c.Param("id") - if id == "" { - c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) +func (h *MessageHandler) handleCreateMessage(c *gin.Context) { + var req repo.CreateMessageParams + err := c.ShouldBindBodyWithJSON(&req) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } - message, err := h.querier.GetMessageByID(c, id) + message, err := h.querier.CreateMessage(c, req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return @@ -67,40 +72,56 @@ func (h *MessageHandler) handleGetMessage(c *gin.Context) { c.JSON(http.StatusOK, message) } -func (h *MessageHandler) handleGetThreadMessages(c *gin.Context) { +func (h *MessageHandler) handleGetMessage(c *gin.Context) { id := c.Param("id") if id == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) return } - messages, err := h.querier.GetMessagesByThread(c, id) + message, err := h.querier.GetMessageByID(c, id) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } - c.JSON(http.StatusOK, gin.H{ - "thread": id, - "topic": "example", - "messages": messages, - }) + c.JSON(http.StatusOK, message) } -func (h *MessageHandler) handleDeleteMessage(c *gin.Context) { - id := c.Param("id") - if id == "" { - c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) - return - } - - if err := h.querier.DeleteMessage(c, id); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete message"}) - } - - c.JSON(http.StatusOK, gin.H{"message": "message deleted successfully"}) - -} +// func (h *MessageHandler) handleGetThreadMessages(c *gin.Context) { +// id := c.Param("thread_id") +// if id == "" { +// c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) +// return +// } + +// messages, err := h.querier.GetMessagesByThread(c, id) +// if err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) +// return +// } + +// c.JSON(http.StatusOK, gin.H{ +// "thread": id, +// "topic": "example", +// "messages": messages, +// }) +// } + +// func (h *MessageHandler) handleDeleteMessage(c *gin.Context) { +// id := c.Param("id") +// if id == "" { +// c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) +// return +// } + +// if err := h.querier.DeleteMessage(c, id); err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete message"}) +// } + +// c.JSON(http.StatusOK, gin.H{"message": "message deleted successfully"}) + +// } func (h *MessageHandler) handleUpdateMessage(c *gin.Context) { var req repo.UpdateMessageParams diff --git a/db/migrations/000003_init_drop_sender.up.sql b/db/migrations/000003_init_drop_sender.up.sql new file mode 100644 index 0000000..30dc221 --- /dev/null +++ b/db/migrations/000003_init_drop_sender.up.sql @@ -0,0 +1,2 @@ +-- drop the sender column since the thread.title is the sender in question +ALTER TABLE message DROP COLUMN sender; \ No newline at end of file diff --git a/db/query/message.sql b/db/query/message.sql index bbe7889..87636dd 100644 --- a/db/query/message.sql +++ b/db/query/message.sql @@ -1,6 +1,42 @@ +-- -- name: CreateMessage :one +-- INSERT INTO message (thread, sender, content) +-- VALUES ($1, $2, $3) +-- RETURNING *; + +-- -- name: GetMessageByID :one +-- SELECT * FROM message +-- WHERE id = $1; + +-- -- name: GetMessagesByThread :many +-- SELECT * FROM message +-- WHERE thread = $1 +-- ORDER BY created_at DESC; + +-- -- name: DeleteMessage :exec +-- DELETE FROM message WHERE id = $1; + +-- -- name: UpdateMessage :exec +-- UPDATE message +-- SET content = $2 +-- WHERE id = $1 +-- RETURNING *; + +-- -- name: CreateThread :one +-- INSERT INTO thread (title) +-- VALUES ($1) +-- RETURNING *; + +-- -- name: DeleteAll :exec +-- DELETE FROM message; + +-- name: CreateThread :one +INSERT INTO thread (title) +VALUES ($1) +RETURNING *; + -- name: CreateMessage :one -INSERT INTO message (thread, sender, content) -VALUES ($1, $2, $3) +INSERT INTO message (content,thread_id) +VALUES ($1, $2) RETURNING *; -- name: GetMessageByID :one @@ -9,17 +45,17 @@ WHERE id = $1; -- name: GetMessagesByThread :many SELECT * FROM message -WHERE thread = $1 +WHERE thread_id = $1 ORDER BY created_at DESC; --- name: DeleteMessage :exec +-- name: DeleteMessageById :exec DELETE FROM message WHERE id = $1; +-- name: DeleteMessageByThreadId :exec +DELETE FROM message WHERE thread_id = $1; + -- name: UpdateMessage :exec UPDATE message SET content = $2 WHERE id = $1 -RETURNING *; - --- name: DeleteAll :exec -DELETE FROM message; \ No newline at end of file +RETURNING *; \ No newline at end of file diff --git a/db/repo/message.sql.go b/db/repo/message.sql.go index 49bb559..2417f3c 100644 --- a/db/repo/message.sql.go +++ b/db/repo/message.sql.go @@ -10,50 +10,92 @@ import ( ) const createMessage = `-- name: CreateMessage :one -INSERT INTO message (thread, sender, content) -VALUES ($1, $2, $3) -RETURNING id, thread, sender, content, created_at +INSERT INTO message (content,thread_id) +VALUES ($1, $2) +RETURNING id, content, created_at, thread_id ` type CreateMessageParams struct { - Thread string `json:"thread"` - Sender string `json:"sender"` - Content string `json:"content"` + Content string `json:"content"` + ThreadID int32 `json:"thread_id"` } func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error) { - row := q.db.QueryRow(ctx, createMessage, arg.Thread, arg.Sender, arg.Content) + row := q.db.QueryRow(ctx, createMessage, arg.Content, arg.ThreadID) var i Message err := row.Scan( &i.ID, - &i.Thread, - &i.Sender, &i.Content, &i.CreatedAt, + &i.ThreadID, ) return i, err } -const deleteAll = `-- name: DeleteAll :exec -DELETE FROM message +const createThread = `-- name: CreateThread :one + + + + + + + +INSERT INTO thread (title) +VALUES ($1) +RETURNING id, title, created_at ` -func (q *Queries) DeleteAll(ctx context.Context) error { - _, err := q.db.Exec(ctx, deleteAll) - return err +// -- name: CreateMessage :one +// INSERT INTO message (thread, sender, content) +// VALUES ($1, $2, $3) +// RETURNING *; +// -- name: GetMessageByID :one +// SELECT * FROM message +// WHERE id = $1; +// -- name: GetMessagesByThread :many +// SELECT * FROM message +// WHERE thread = $1 +// ORDER BY created_at DESC; +// -- name: DeleteMessage :exec +// DELETE FROM message WHERE id = $1; +// -- name: UpdateMessage :exec +// UPDATE message +// SET content = $2 +// WHERE id = $1 +// RETURNING *; +// -- name: CreateThread :one +// INSERT INTO thread (title) +// VALUES ($1) +// RETURNING *; +// -- name: DeleteAll :exec +// DELETE FROM message; +func (q *Queries) CreateThread(ctx context.Context, title string) (Thread, error) { + row := q.db.QueryRow(ctx, createThread, title) + var i Thread + err := row.Scan(&i.ID, &i.Title, &i.CreatedAt) + return i, err } -const deleteMessage = `-- name: DeleteMessage :exec +const deleteMessageById = `-- name: DeleteMessageById :exec DELETE FROM message WHERE id = $1 ` -func (q *Queries) DeleteMessage(ctx context.Context, id string) error { - _, err := q.db.Exec(ctx, deleteMessage, id) +func (q *Queries) DeleteMessageById(ctx context.Context, id string) error { + _, err := q.db.Exec(ctx, deleteMessageById, id) + return err +} + +const deleteMessageByThreadId = `-- name: DeleteMessageByThreadId :exec +DELETE FROM message WHERE thread_id = $1 +` + +func (q *Queries) DeleteMessageByThreadId(ctx context.Context, threadID int32) error { + _, err := q.db.Exec(ctx, deleteMessageByThreadId, threadID) return err } const getMessageByID = `-- name: GetMessageByID :one -SELECT id, thread, sender, content, created_at FROM message +SELECT id, content, created_at, thread_id FROM message WHERE id = $1 ` @@ -62,22 +104,21 @@ func (q *Queries) GetMessageByID(ctx context.Context, id string) (Message, error var i Message err := row.Scan( &i.ID, - &i.Thread, - &i.Sender, &i.Content, &i.CreatedAt, + &i.ThreadID, ) return i, err } const getMessagesByThread = `-- name: GetMessagesByThread :many -SELECT id, thread, sender, content, created_at FROM message -WHERE thread = $1 +SELECT id, content, created_at, thread_id FROM message +WHERE thread_id = $1 ORDER BY created_at DESC ` -func (q *Queries) GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) { - rows, err := q.db.Query(ctx, getMessagesByThread, thread) +func (q *Queries) GetMessagesByThread(ctx context.Context, threadID int32) ([]Message, error) { + rows, err := q.db.Query(ctx, getMessagesByThread, threadID) if err != nil { return nil, err } @@ -87,10 +128,9 @@ func (q *Queries) GetMessagesByThread(ctx context.Context, thread string) ([]Mes var i Message if err := rows.Scan( &i.ID, - &i.Thread, - &i.Sender, &i.Content, &i.CreatedAt, + &i.ThreadID, ); err != nil { return nil, err } @@ -106,7 +146,7 @@ const updateMessage = `-- name: UpdateMessage :exec UPDATE message SET content = $2 WHERE id = $1 -RETURNING id, thread, sender, content, created_at +RETURNING id, content, created_at, thread_id ` type UpdateMessageParams struct { diff --git a/db/repo/models.go b/db/repo/models.go index 92c72c8..50b4887 100644 --- a/db/repo/models.go +++ b/db/repo/models.go @@ -10,8 +10,13 @@ import ( type Message struct { ID string `json:"id"` - Thread string `json:"thread"` - Sender string `json:"sender"` Content string `json:"content"` CreatedAt pgtype.Timestamp `json:"created_at"` + ThreadID int32 `json:"thread_id"` +} + +type Thread struct { + ID int32 `json:"id"` + Title string `json:"title"` + CreatedAt pgtype.Timestamptz `json:"created_at"` } diff --git a/db/repo/querier.go b/db/repo/querier.go index ece582a..c7c6f6e 100644 --- a/db/repo/querier.go +++ b/db/repo/querier.go @@ -10,10 +10,35 @@ import ( type Querier interface { CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error) - DeleteAll(ctx context.Context) error - DeleteMessage(ctx context.Context, id string) error + // -- name: CreateMessage :one + // INSERT INTO message (thread, sender, content) + // VALUES ($1, $2, $3) + // RETURNING *; + // -- name: GetMessageByID :one + // SELECT * FROM message + // WHERE id = $1; + // -- name: GetMessagesByThread :many + // SELECT * FROM message + // WHERE thread = $1 + // ORDER BY created_at DESC; + // -- name: DeleteMessage :exec + // DELETE FROM message WHERE id = $1; + // -- name: UpdateMessage :exec + // UPDATE message + // SET content = $2 + // WHERE id = $1 + // RETURNING *; + // -- name: CreateThread :one + // INSERT INTO thread (title) + // VALUES ($1) + // RETURNING *; + // -- name: DeleteAll :exec + // DELETE FROM message; + CreateThread(ctx context.Context,title string) (Thread,error) + DeleteMessageById(ctx context.Context, id string) error + DeleteMessageByThreadId(ctx context.Context, threadID int32) error GetMessageByID(ctx context.Context, id string) (Message, error) - GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) + GetMessagesByThread(ctx context.Context, threadID int32) ([]Message, error) UpdateMessage(ctx context.Context, arg UpdateMessageParams) error } From a56ec4ef997079b709b726926b52fd5d073df1e2 Mon Sep 17 00:00:00 2001 From: ichami630 Date: Tue, 8 Apr 2025 15:41:32 +0100 Subject: [PATCH 07/10] create message, create thread before creating message --- api/api.go | 44 ++++++++++++++++++++++++++++++++-------- db/query/message.sql | 5 ++++- db/repo/message.sql.go | 11 ++++++++++ db/repo/querier.go | 3 ++- helper/helperFunction.go | 8 ++++++++ 5 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 helper/helperFunction.go diff --git a/api/api.go b/api/api.go index 31244c7..828e168 100644 --- a/api/api.go +++ b/api/api.go @@ -1,6 +1,8 @@ package api import ( + "database/sql" + "errors" "net/http" "github.com/Iknite-Space/sqlc-example-api/db/repo" @@ -29,7 +31,7 @@ func (h *MessageHandler) WireHttpHandler() http.Handler { r.POST("/message", h.handleCreateMessage) r.GET("/message/:id", h.handleGetMessage) // r.GET("/thread/:id/messages", h.handleGetThreadMessages) - // r.DELETE("/message/:id", h.handleDeleteMessage) + // r.DELETE("/message/:id", h.handleDeleteMessageById) r.PATCH("/message", h.handleUpdateMessage) return r @@ -57,18 +59,28 @@ func (h *MessageHandler) handleCreateThread(c *gin.Context) { func (h *MessageHandler) handleCreateMessage(c *gin.Context) { var req repo.CreateMessageParams - err := c.ShouldBindBodyWithJSON(&req) - if err != nil { + if err := c.ShouldBindBodyWithJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } + //first check whether the thread exist + _, err := h.querier.GetThreadById(c, req.ThreadID) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + c.JSON(http.StatusBadRequest, gin.H{"error": "Thread not found"}) + return + } + c.JSON(http.StatusInternalServerError, gin.H{"error": "Server error"}) + return + } + + //now we proceed to create the message message, err := h.querier.CreateMessage(c, req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } - c.JSON(http.StatusOK, message) } @@ -108,19 +120,33 @@ func (h *MessageHandler) handleGetMessage(c *gin.Context) { // }) // } -// func (h *MessageHandler) handleDeleteMessage(c *gin.Context) { +// func (h *MessageHandler) handleDeleteMessageById(c *gin.Context) { // id := c.Param("id") // if id == "" { -// c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) +// c.JSON(http.StatusBadRequest, gin.H{"error": "Id cannot be null"}) +// } + +// //start a transaction +// tx, err := h.querier.(*repo.Queries).DB().Begin(c) +// if err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to start transaction"}) // return // } +// defer tx.Rollback(c) // will rollback if not committed -// if err := h.querier.DeleteMessage(c, id); err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete message"}) +// txQuerier := h.querier.(*repo.Queries).WithTx(tx) + +// if err := txQuerier.DeleteMessageById(c, id); err != nil { +// c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to delete message"}) // } -// c.JSON(http.StatusOK, gin.H{"message": "message deleted successfully"}) +// // Commit transaction if everything is good +// if err := tx.Commit(c); err != nil { +// c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to commit transaction"}) +// return +// } +// c.JSON(http.StatusOK, gin.H{"success": "Deleted successfully"}) // } func (h *MessageHandler) handleUpdateMessage(c *gin.Context) { diff --git a/db/query/message.sql b/db/query/message.sql index 87636dd..af6cd6d 100644 --- a/db/query/message.sql +++ b/db/query/message.sql @@ -58,4 +58,7 @@ DELETE FROM message WHERE thread_id = $1; UPDATE message SET content = $2 WHERE id = $1 -RETURNING *; \ No newline at end of file +RETURNING *; + +-- name: GetThreadById :one +SELECT * FROM thread WHERE id = $1; \ No newline at end of file diff --git a/db/repo/message.sql.go b/db/repo/message.sql.go index 2417f3c..c0cccf6 100644 --- a/db/repo/message.sql.go +++ b/db/repo/message.sql.go @@ -142,6 +142,17 @@ func (q *Queries) GetMessagesByThread(ctx context.Context, threadID int32) ([]Me return items, nil } +const getThreadById = `-- name: GetThreadById :one +SELECT id, title, created_at FROM thread WHERE id = $1 +` + +func (q *Queries) GetThreadById(ctx context.Context, id int32) (Thread, error) { + row := q.db.QueryRow(ctx, getThreadById, id) + var i Thread + err := row.Scan(&i.ID, &i.Title, &i.CreatedAt) + return i, err +} + const updateMessage = `-- name: UpdateMessage :exec UPDATE message SET content = $2 diff --git a/db/repo/querier.go b/db/repo/querier.go index c7c6f6e..6dabb44 100644 --- a/db/repo/querier.go +++ b/db/repo/querier.go @@ -34,11 +34,12 @@ type Querier interface { // RETURNING *; // -- name: DeleteAll :exec // DELETE FROM message; - CreateThread(ctx context.Context,title string) (Thread,error) + CreateThread(ctx context.Context, title string) (Thread, error) DeleteMessageById(ctx context.Context, id string) error DeleteMessageByThreadId(ctx context.Context, threadID int32) error GetMessageByID(ctx context.Context, id string) (Message, error) GetMessagesByThread(ctx context.Context, threadID int32) ([]Message, error) + GetThreadById(ctx context.Context, id int32) (Thread, error) UpdateMessage(ctx context.Context, arg UpdateMessageParams) error } diff --git a/helper/helperFunction.go b/helper/helperFunction.go new file mode 100644 index 0000000..b7a0cd4 --- /dev/null +++ b/helper/helperFunction.go @@ -0,0 +1,8 @@ +package helper + +import "strconv" + +func GetParamAsInt32(key string) (int32, error) { + intVal, err := strconv.Atoi(key) + return int32(intVal), err +} From 330314eb10f079b85afd9fea526e9d542193e5a1 Mon Sep 17 00:00:00 2001 From: ichami630 Date: Tue, 8 Apr 2025 16:20:42 +0100 Subject: [PATCH 08/10] get messages found in thread --- api/api.go | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/api/api.go b/api/api.go index 828e168..32f22ad 100644 --- a/api/api.go +++ b/api/api.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/Iknite-Space/sqlc-example-api/db/repo" + "github.com/Iknite-Space/sqlc-example-api/helper" "github.com/gin-gonic/gin" ) @@ -30,7 +31,7 @@ func (h *MessageHandler) WireHttpHandler() http.Handler { r.POST("/thread", h.handleCreateThread) r.POST("/message", h.handleCreateMessage) r.GET("/message/:id", h.handleGetMessage) - // r.GET("/thread/:id/messages", h.handleGetThreadMessages) + r.GET("/thread/messages/:threadId", h.handleGetThreadMessages) // r.DELETE("/message/:id", h.handleDeleteMessageById) r.PATCH("/message", h.handleUpdateMessage) @@ -100,25 +101,27 @@ func (h *MessageHandler) handleGetMessage(c *gin.Context) { c.JSON(http.StatusOK, message) } -// func (h *MessageHandler) handleGetThreadMessages(c *gin.Context) { -// id := c.Param("thread_id") -// if id == "" { -// c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) -// return -// } +func (h *MessageHandler) handleGetThreadMessages(c *gin.Context) { + id := c.Param("threadId") + intVal, err := helper.GetParamAsInt32(id) -// messages, err := h.querier.GetMessagesByThread(c, id) -// if err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) -// return -// } + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } -// c.JSON(http.StatusOK, gin.H{ -// "thread": id, -// "topic": "example", -// "messages": messages, -// }) -// } + messages, err := h.querier.GetMessagesByThread(c, intVal) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + if len(messages) == 0 { + c.JSON(http.StatusNotFound, gin.H{"error": "No messages found for this thread"}) + } + + c.JSON(http.StatusOK, messages) +} // func (h *MessageHandler) handleDeleteMessageById(c *gin.Context) { // id := c.Param("id") From 36244d92a12b263b18472f99db19da0493bc5f86 Mon Sep 17 00:00:00 2001 From: ichami630 Date: Wed, 9 Apr 2025 10:55:04 +0100 Subject: [PATCH 09/10] delete message by messageid --- api/api.go | 48 ++++++++++++++++-------------------------- db/query/message.sql | 5 +++-- db/repo/message.sql.go | 10 +++++---- db/repo/querier.go | 2 +- 4 files changed, 28 insertions(+), 37 deletions(-) diff --git a/api/api.go b/api/api.go index 32f22ad..0ffb26d 100644 --- a/api/api.go +++ b/api/api.go @@ -32,7 +32,7 @@ func (h *MessageHandler) WireHttpHandler() http.Handler { r.POST("/message", h.handleCreateMessage) r.GET("/message/:id", h.handleGetMessage) r.GET("/thread/messages/:threadId", h.handleGetThreadMessages) - // r.DELETE("/message/:id", h.handleDeleteMessageById) + r.DELETE("/message/:id", h.handleDeleteMessageById) r.PATCH("/message", h.handleUpdateMessage) return r @@ -123,35 +123,6 @@ func (h *MessageHandler) handleGetThreadMessages(c *gin.Context) { c.JSON(http.StatusOK, messages) } -// func (h *MessageHandler) handleDeleteMessageById(c *gin.Context) { -// id := c.Param("id") -// if id == "" { -// c.JSON(http.StatusBadRequest, gin.H{"error": "Id cannot be null"}) -// } - -// //start a transaction -// tx, err := h.querier.(*repo.Queries).DB().Begin(c) -// if err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to start transaction"}) -// return -// } -// defer tx.Rollback(c) // will rollback if not committed - -// txQuerier := h.querier.(*repo.Queries).WithTx(tx) - -// if err := txQuerier.DeleteMessageById(c, id); err != nil { -// c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to delete message"}) -// } - -// // Commit transaction if everything is good -// if err := tx.Commit(c); err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to commit transaction"}) -// return -// } - -// c.JSON(http.StatusOK, gin.H{"success": "Deleted successfully"}) -// } - func (h *MessageHandler) handleUpdateMessage(c *gin.Context) { var req repo.UpdateMessageParams if err := c.ShouldBindBodyWithJSON(&req); err != nil { @@ -166,3 +137,20 @@ func (h *MessageHandler) handleUpdateMessage(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": "Message updated successfully"}) } + +func (h *MessageHandler) handleDeleteMessageById(c *gin.Context) { + id := c.Param("id") + + _, err := h.querier.DeleteMessageById(c, id) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + c.JSON(http.StatusNotFound, gin.H{"error": "Message not found"}) + return + } + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Message deleted successfully"}) + +} diff --git a/db/query/message.sql b/db/query/message.sql index af6cd6d..aa8afd6 100644 --- a/db/query/message.sql +++ b/db/query/message.sql @@ -48,8 +48,9 @@ SELECT * FROM message WHERE thread_id = $1 ORDER BY created_at DESC; --- name: DeleteMessageById :exec -DELETE FROM message WHERE id = $1; +-- name: DeleteMessageById :one +DELETE FROM message WHERE id = $1 +RETURNING id; -- name: DeleteMessageByThreadId :exec DELETE FROM message WHERE thread_id = $1; diff --git a/db/repo/message.sql.go b/db/repo/message.sql.go index c0cccf6..790aee6 100644 --- a/db/repo/message.sql.go +++ b/db/repo/message.sql.go @@ -76,13 +76,15 @@ func (q *Queries) CreateThread(ctx context.Context, title string) (Thread, error return i, err } -const deleteMessageById = `-- name: DeleteMessageById :exec +const deleteMessageById = `-- name: DeleteMessageById :one DELETE FROM message WHERE id = $1 +RETURNING id ` -func (q *Queries) DeleteMessageById(ctx context.Context, id string) error { - _, err := q.db.Exec(ctx, deleteMessageById, id) - return err +func (q *Queries) DeleteMessageById(ctx context.Context, id string) (string, error) { + row := q.db.QueryRow(ctx, deleteMessageById, id) + err := row.Scan(&id) + return id, err } const deleteMessageByThreadId = `-- name: DeleteMessageByThreadId :exec diff --git a/db/repo/querier.go b/db/repo/querier.go index 6dabb44..35495ee 100644 --- a/db/repo/querier.go +++ b/db/repo/querier.go @@ -35,7 +35,7 @@ type Querier interface { // -- name: DeleteAll :exec // DELETE FROM message; CreateThread(ctx context.Context, title string) (Thread, error) - DeleteMessageById(ctx context.Context, id string) error + DeleteMessageById(ctx context.Context, id string) (string, error) DeleteMessageByThreadId(ctx context.Context, threadID int32) error GetMessageByID(ctx context.Context, id string) (Message, error) GetMessagesByThread(ctx context.Context, threadID int32) ([]Message, error) From 88de87d9af518688a5f1a649919eed4c1173074a Mon Sep 17 00:00:00 2001 From: ichami630 Date: Wed, 9 Apr 2025 11:07:38 +0100 Subject: [PATCH 10/10] delete all messages in a thread --- api/api.go | 24 ++++++++++++++++++++++++ db/query/message.sql | 5 +++-- db/repo/message.sql.go | 11 +++++++---- db/repo/querier.go | 2 +- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/api/api.go b/api/api.go index 0ffb26d..24929a1 100644 --- a/api/api.go +++ b/api/api.go @@ -33,6 +33,7 @@ func (h *MessageHandler) WireHttpHandler() http.Handler { r.GET("/message/:id", h.handleGetMessage) r.GET("/thread/messages/:threadId", h.handleGetThreadMessages) r.DELETE("/message/:id", h.handleDeleteMessageById) + r.DELETE("/thread/:threadId/messages", h.handleDeleteMessageByThreadId) r.PATCH("/message", h.handleUpdateMessage) return r @@ -154,3 +155,26 @@ func (h *MessageHandler) handleDeleteMessageById(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "Message deleted successfully"}) } + +func (h *MessageHandler) handleDeleteMessageByThreadId(c *gin.Context) { + id := c.Param("threadId") + + intId, err := helper.GetParamAsInt32(id) + if err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + + _, err = h.querier.DeleteMessageByThreadId(c, intId) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + c.JSON(http.StatusNotFound, gin.H{"error": "Message not found"}) + return + } + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Message deleted successfully"}) + +} diff --git a/db/query/message.sql b/db/query/message.sql index aa8afd6..01a2871 100644 --- a/db/query/message.sql +++ b/db/query/message.sql @@ -52,8 +52,9 @@ ORDER BY created_at DESC; DELETE FROM message WHERE id = $1 RETURNING id; --- name: DeleteMessageByThreadId :exec -DELETE FROM message WHERE thread_id = $1; +-- name: DeleteMessageByThreadId :one +DELETE FROM message WHERE thread_id = $1 +RETURNING thread_id; -- name: UpdateMessage :exec UPDATE message diff --git a/db/repo/message.sql.go b/db/repo/message.sql.go index 790aee6..d7e7acb 100644 --- a/db/repo/message.sql.go +++ b/db/repo/message.sql.go @@ -87,13 +87,16 @@ func (q *Queries) DeleteMessageById(ctx context.Context, id string) (string, err return id, err } -const deleteMessageByThreadId = `-- name: DeleteMessageByThreadId :exec +const deleteMessageByThreadId = `-- name: DeleteMessageByThreadId :one DELETE FROM message WHERE thread_id = $1 +RETURNING thread_id ` -func (q *Queries) DeleteMessageByThreadId(ctx context.Context, threadID int32) error { - _, err := q.db.Exec(ctx, deleteMessageByThreadId, threadID) - return err +func (q *Queries) DeleteMessageByThreadId(ctx context.Context, threadID int32) (int32, error) { + row := q.db.QueryRow(ctx, deleteMessageByThreadId, threadID) + var thread_id int32 + err := row.Scan(&thread_id) + return thread_id, err } const getMessageByID = `-- name: GetMessageByID :one diff --git a/db/repo/querier.go b/db/repo/querier.go index 35495ee..0d61b45 100644 --- a/db/repo/querier.go +++ b/db/repo/querier.go @@ -36,7 +36,7 @@ type Querier interface { // DELETE FROM message; CreateThread(ctx context.Context, title string) (Thread, error) DeleteMessageById(ctx context.Context, id string) (string, error) - DeleteMessageByThreadId(ctx context.Context, threadID int32) error + DeleteMessageByThreadId(ctx context.Context, threadID int32) (int32, error) GetMessageByID(ctx context.Context, id string) (Message, error) GetMessagesByThread(ctx context.Context, threadID int32) ([]Message, error) GetThreadById(ctx context.Context, id int32) (Thread, error)