diff --git a/basic/postgresql.go b/basic/postgresql.go index 226688b..c804347 100644 --- a/basic/postgresql.go +++ b/basic/postgresql.go @@ -31,8 +31,10 @@ CREATE TABLE IF NOT EXISTS event ( tagvalues text[] GENERATED ALWAYS AS (tags_to_tagvalues(tags)) STORED ); -CREATE UNIQUE INDEX IF NOT EXISTS ididx ON event (id); -CREATE UNIQUE INDEX IF NOT EXISTS pubkeytimeidx ON event (pubkey, created_at); +CREATE UNIQUE INDEX IF NOT EXISTS ididx ON event USING btree (id text_pattern_ops); +CREATE INDEX IF NOT EXISTS pubkeyprefix ON event USING btree (pubkey text_pattern_ops); +CREATE INDEX IF NOT EXISTS timeidx ON event (created_at); +CREATE INDEX IF NOT EXISTS kindidx ON event (kind); CREATE INDEX IF NOT EXISTS arbitrarytagvalues ON event USING gin (tagvalues); `) relayer.Log.Print(err) diff --git a/basic/query.go b/basic/query.go index bd3fda7..cb3f364 100644 --- a/basic/query.go +++ b/basic/query.go @@ -7,6 +7,7 @@ import ( "fmt" "strconv" "strings" + "time" "github.com/fiatjaf/go-nostr" "github.com/rs/zerolog/log" @@ -27,21 +28,21 @@ func (b *BasicRelay) QueryEvents(filter *nostr.Filter) (events []nostr.Event, er return } - inids := make([]string, 0, len(filter.IDs)) + likeids := make([]string, 0, len(filter.IDs)) for _, id := range filter.IDs { // to prevent sql attack here we will check if // these ids are valid 32byte hex parsed, err := hex.DecodeString(id) - if err != nil || len(parsed) != 32 { + if err != nil || len(parsed) <= 32 { continue } - inids = append(inids, fmt.Sprintf("'%x'", parsed)) + likeids = append(likeids, fmt.Sprintf("id LIKE '%x%%'", parsed)) } - if len(inids) == 0 { + if len(likeids) == 0 { // ids being [] mean you won't get anything return } - conditions = append(conditions, `id IN (`+strings.Join(inids, ",")+`)`) + conditions = append(conditions, "("+strings.Join(likeids, " OR ")+")") } if filter.Authors != nil { @@ -50,7 +51,7 @@ func (b *BasicRelay) QueryEvents(filter *nostr.Filter) (events []nostr.Event, er return } - inkeys := make([]string, 0, len(filter.Authors)) + likekeys := make([]string, 0, len(filter.Authors)) for _, key := range filter.Authors { // to prevent sql attack here we will check if // these keys are valid 32byte hex @@ -58,13 +59,13 @@ func (b *BasicRelay) QueryEvents(filter *nostr.Filter) (events []nostr.Event, er if err != nil || len(parsed) != 32 { continue } - inkeys = append(inkeys, fmt.Sprintf("'%x'", parsed)) + likekeys = append(likekeys, fmt.Sprintf("pubkey LIKE '%x%%'", parsed)) } - if len(inkeys) == 0 { + if len(likekeys) == 0 { // authors being [] mean you won't get anything return } - conditions = append(conditions, `pubkey IN (`+strings.Join(inkeys, ",")+`)`) + conditions = append(conditions, "("+strings.Join(likekeys, " OR ")+")") } if filter.Kinds != nil { @@ -143,11 +144,13 @@ func (b *BasicRelay) QueryEvents(filter *nostr.Filter) (events []nostr.Event, er for rows.Next() { var evt nostr.Event - err := rows.Scan(&evt.ID, &evt.PubKey, &evt.CreatedAt, + var timestamp int64 + err := rows.Scan(&evt.ID, &evt.PubKey, ×tamp, &evt.Kind, &evt.Tags, &evt.Content, &evt.Sig) if err != nil { return nil, fmt.Errorf("failed to scan row: %w", err) } + evt.CreatedAt = time.Unix(timestamp, 0) events = append(events, evt) } diff --git a/basic/save.go b/basic/save.go index e251930..042c85d 100644 --- a/basic/save.go +++ b/basic/save.go @@ -41,7 +41,7 @@ func (b *BasicRelay) SaveEvent(evt *nostr.Event) error { _, err := b.DB.Exec(` INSERT INTO event (id, pubkey, created_at, kind, tags, content, sig) VALUES ($1, $2, $3, $4, $5, $6, $7) - `, evt.ID, evt.PubKey, evt.CreatedAt, evt.Kind, tagsj, evt.Content, evt.Sig) + `, evt.ID, evt.PubKey, evt.CreatedAt.Unix(), evt.Kind, tagsj, evt.Content, evt.Sig) if err != nil { if strings.Index(err.Error(), "UNIQUE") != -1 { // already exists