Wstępne budowanie zapytania SQL (zapobieganie wstrzykiwaniu SQL)
Jeśli generujesz ciąg SQL z symbolem zastępczym dla każdej wartości, łatwiej jest od razu wygenerować końcowy kod SQL.
Zauważ, że ponieważ wartości to string
s, jest miejsce na atak wstrzykiwania SQL, więc najpierw sprawdzamy, czy cały string
wartości są rzeczywiście liczbami, a my kontynuujemy tylko wtedy, gdy tak:
tags := []string{"1", "2", "3"}
buf := bytes.NewBufferString("SELECT COUNT(id) FROM tags WHERE id IN(")
for i, v := range tags {
if i > 0 {
buf.WriteString(",")
}
if _, err := strconv.Atoi(v); err != nil {
panic("Not number!")
}
buf.WriteString(v)
}
buf.WriteString(")")
Wykonanie:
num := 0
if err := Db.QueryRow(buf.String()).Scan(&num); err != nil {
log.Println(err)
}
Korzystanie z ANY
Możesz także użyć ANY
Postgresql , którego składnia jest następująca:
expression operator ANY (array expression)
Dzięki temu nasze zapytanie może wyglądać tak:
SELECT COUNT(id) FROM tags WHERE id = ANY('{1,2,3}'::int[])
W takim przypadku możesz zadeklarować formę tekstową tablicy jako parametr:
SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])
Który można po prostu zbudować w następujący sposób:
tags := []string{"1", "2", "3"}
param := "{" + strings.Join(tags, ",") + "}"
Zauważ, że w tym przypadku nie jest wymagane żadne sprawdzenie, ponieważ wyrażenie tablicowe nie pozwoli na wstrzyknięcie SQL (ale raczej spowoduje błąd wykonania zapytania).
Więc pełny kod:
tags := []string{"1", "2", "3"}
q := "SELECT COUNT(id) FROM tags WHERE id = ANY($1::int[])"
param := "{" + strings.Join(tags, ",") + "}"
num := 0
if err := Db.QueryRow(q, param).Scan(&num); err != nil {
log.Println(err)
}