Skip to content
This repository has been archived by the owner on Oct 17, 2020. It is now read-only.

Added GetByAliases function in db and repository #539

Merged
merged 21 commits into from Mar 12, 2020
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 0 additions & 24 deletions backend/.env.dist

This file was deleted.

6 changes: 3 additions & 3 deletions backend/app/adapter/db/.env
@@ -1,7 +1,7 @@
DB_HOST=localhost
DB_PORT=5432
DB_PORT=5433
DB_USER=postgres
DB_PASSWORD=password
DB_NAME=short-test
DB_PASSWORD=123456
DB_NAME=tom

MIGRATION_ROOT=./migration
dawntomm marked this conversation as resolved.
Show resolved Hide resolved
62 changes: 62 additions & 0 deletions backend/app/adapter/db/url.go
Expand Up @@ -3,6 +3,7 @@ package db
import (
"database/sql"
"fmt"
"strings"

"github.com/short-d/short/app/adapter/db/table"
"github.com/short-d/short/app/entity"
Expand Down Expand Up @@ -96,6 +97,67 @@ WHERE "%s"=$1;`,
return url, nil
}

// GetByAliases finds URLs for a list of aliases
func (u URLSql) GetByAliases(aliases []string) ([]entity.URL, error) {
// create a string for aliases parameters
// it looks like: $1, $2, $3, ......
params := make([]string, 0, len(aliases))
for i := range aliases {
params = append(params, fmt.Sprintf("$%d", i+1))
}
parameterStr := strings.Join(params, ", ")
magicoder10 marked this conversation as resolved.
Show resolved Hide resolved

// create a list of interface{} to hold aliases for db.Query()
aliasesInterface := []interface{}{}
for _, alias := range aliases {
aliasesInterface = append(aliasesInterface, alias)
}
dawntomm marked this conversation as resolved.
Show resolved Hide resolved

var urls []entity.URL

statement := fmt.Sprintf(`
SELECT "%s","%s","%s","%s","%s"
FROM "%s"
WHERE "%s" IN (%s);`,
dawntomm marked this conversation as resolved.
Show resolved Hide resolved
table.URL.ColumnAlias,
table.URL.ColumnOriginalURL,
table.URL.ColumnExpireAt,
table.URL.ColumnCreatedAt,
table.URL.ColumnUpdatedAt,
table.URL.TableName,
table.URL.ColumnAlias,
parameterStr,
)

rows, err := u.db.Query(statement, aliasesInterface...)
if err != nil {
return urls, nil
}

defer rows.Close()
for rows.Next() {
url := entity.URL{}
err := rows.Scan(
&url.Alias,
&url.OriginalURL,
&url.ExpireAt,
&url.CreatedAt,
&url.UpdatedAt,
)
if err != nil {
return urls, err
}

url.CreatedAt = utc(url.CreatedAt)
url.UpdatedAt = utc(url.UpdatedAt)
url.ExpireAt = utc(url.ExpireAt)

urls = append(urls, url)
}

return urls, nil
}

// NewURLSql creates URLSql
func NewURLSql(db *sql.DB) *URLSql {
return &URLSql{
Expand Down
111 changes: 111 additions & 0 deletions backend/app/adapter/db/url_integration_test.go
Expand Up @@ -242,6 +242,117 @@ func TestURLSql_Create(t *testing.T) {
}
}

func TestURLSql_GetByAliases(t *testing.T) {
twoYearsAgo := mustParseTime(t, "2017-05-01T08:02:16-07:00")
now := mustParseTime(t, "2019-05-01T08:02:16-07:00")

testCases := []struct {
name string
tableRows []urlTableRow
aliases []string
hasErr bool
expectedURLs []entity.URL
}{
{
name: "alias not found",
tableRows: []urlTableRow{},
aliases: []string{"220uFicCJj"},
hasErr: false,
},
{
name: "found url",
tableRows: []urlTableRow{
{
alias: "220uFicCJj",
longLink: "http://www.google.com",
createdAt: &twoYearsAgo,
expireAt: &now,
updatedAt: &now,
},
{
alias: "yDOBcj5HIPbUAsw",
longLink: "http://www.facebook.com",
createdAt: &twoYearsAgo,
expireAt: &now,
updatedAt: &now,
},
},
aliases: []string{"220uFicCJj", "yDOBcj5HIPbUAsw"},
hasErr: false,
expectedURLs: []entity.URL{
entity.URL{
Alias: "220uFicCJj",
OriginalURL: "http://www.google.com",
CreatedAt: &twoYearsAgo,
ExpireAt: &now,
UpdatedAt: &now,
},
entity.URL{
Alias: "yDOBcj5HIPbUAsw",
OriginalURL: "http://www.facebook.com",
CreatedAt: &twoYearsAgo,
ExpireAt: &now,
UpdatedAt: &now,
},
},
},
{
name: "nil time",
tableRows: []urlTableRow{
{
alias: "220uFicCJj",
longLink: "http://www.google.com",
createdAt: nil,
expireAt: nil,
updatedAt: nil,
},
{
alias: "yDOBcj5HIPbUAsw",
longLink: "http://www.facebook.com",
createdAt: &twoYearsAgo,
expireAt: &now,
updatedAt: &now,
},
},
aliases: []string{"220uFicCJj"},
hasErr: false,
expectedURLs: []entity.URL{
entity.URL{
Alias: "220uFicCJj",
OriginalURL: "http://www.google.com",
CreatedAt: nil,
ExpireAt: nil,
UpdatedAt: nil,
},
},
},
magicoder10 marked this conversation as resolved.
Show resolved Hide resolved
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
mdtest.AccessTestDB(
dbConnector,
dbMigrationTool,
dbMigrationRoot,
dbConfig,
func(sqlDB *sql.DB) {
insertURLTableRows(t, sqlDB, testCase.tableRows)

urlRepo := db.NewURLSql(sqlDB)
urls, err := urlRepo.GetByAliases(testCase.aliases)

if testCase.hasErr {
mdtest.NotEqual(t, nil, err)
return
}
mdtest.Equal(t, nil, err)
mdtest.Equal(t, testCase.expectedURLs, urls)
},
)
})
}
}

func insertURLTableRows(t *testing.T, sqlDB *sql.DB, tableRows []urlTableRow) {
for _, tableRow := range tableRows {
_, err := sqlDB.Exec(
Expand Down
1 change: 1 addition & 0 deletions backend/app/usecase/repository/url.go
Expand Up @@ -7,4 +7,5 @@ type URL interface {
IsAliasExist(alias string) (bool, error)
GetByAlias(alias string) (entity.URL, error)
Create(url entity.URL) error
GetByAliases(aliases []string) ([]entity.URL, error)
}
15 changes: 15 additions & 0 deletions backend/app/usecase/repository/url_fake.go
Expand Up @@ -45,6 +45,21 @@ func (u URLFake) GetByAlias(alias string) (entity.URL, error) {
return url, nil
}

// GetByAliases finds all URL for a list of aliases
func (u URLFake) GetByAliases(aliases []string) ([]entity.URL, error) {
var urls []entity.URL

for _, alias := range aliases {
url, err := u.GetByAlias(alias)

if err != nil {
return urls, err
}
urls = append(urls, url)
}
return urls, nil
}

// NewURLFake creates in memory URL repository
func NewURLFake(urls map[string]entity.URL) URLFake {
return URLFake{
Expand Down