2017-09-14 42 views
0

我想使動態SQL GoLang和我似乎無法找到正確的方式來做到這一點。GoLang動態SQL查詢App Engine中

基本上,我只想做:

query := "SELECT id, email, something FROM User" 

var paramValues []string 
filterString := "" 

if userParams.Name != "" { 
    paramString += " WHERE id = ?" 
    paramValues = append(paramValues, userParams.Name) 
} 

if userParams.UserID != "" { 
    if len(paramString) > 0 { 
     paramString += " AND" 
    } else { 
     paramString += " WHERE" 
    } 

    paramString += " email = ?" 
    paramValues = append(paramValues, userParams.UserID) 
} 
stmtOut, err := db.Prepare(query + paramString) 

err = stmtOut.QueryRow(paramValues).Scan(&id, &email, &something) 

相關的building a dynamic query in mysql and golang

我一直無法找到一種可靠的方法可以做到這一點不允許SQL注入。我的上述解決方案的問題是,QueryRow()用不了[]字符串作爲參數。

我想從SQL注入保護,所以fmt.Sprintf並沒有真正解決問題。

這樣我可以允許使用任一ID或電子郵件用戶搜索,我也將使用此邏輯用於與多個可搜索字段不同的對象。

我使用去-SQL驅動程序/ MySQL的

回答

1

這裏的東西,我可以在我的本地機器(go1.8的Linux/AMD64和電流GO MySQL驅動1.3)上運行。

夫婦的方式被證明。

package main 

import (
    "database/sql" 
    "log" 

    _ "github.com/go-sql-driver/mysql" 

    "fmt" 
) 

// var db *sql.DB 
// var err error 

/* 
Database Name/Schema : Test123 
Table Name: test 
Table Columns and types: 
number INT (PRIMARY KEY) 
cube INT 
*/ 

func main() { 
    //Username root, password root 
    db, err := sql.Open("mysql", "root:[email protected](127.0.0.1:3306)/Test123?charset=utf8") 

    if err != nil { 
     fmt.Println(err) // needs proper handling as per app requirement 
     return 
    } 
    defer db.Close() 

    err = db.Ping() 
    if err != nil { 
     fmt.Println(err) // needs proper handling as per app requirement 
     return 
    } 

    //Prepared statement for inserting data 
    stmtIns, err := db.Prepare("INSERT INTO test VALUES(?, ?)") // ? = placeholders 
    if err != nil { 
     panic(err.Error()) // needs proper handling as per app requirement 
    } 
    defer stmtIns.Close() 

    //Insert cubes of 1- 10 numbers 

    for i := 1; i < 10; i++ { 
     _, err = stmtIns.Exec(i, (i * i * i)) // Insert tuples (i, i^3) 
     if err != nil { 
      panic(err.Error()) // proper error handling instead of panic in your app 
     } 
    } 

    num := 3 

    // Select statement 

    dataEntity := "cube" 
    condition := "WHERE number=? AND cube > ?" 
    finalStatement := "SELECT " + dataEntity + " FROM test " + condition 
    cubeLowerLimit := 10 

    var myCube int 
    err = db.QueryRow(finalStatement, num, cubeLowerLimit).Scan(&myCube) 
    switch { 
    case err == sql.ErrNoRows: 
     log.Printf("No row with this number %d", num) 
    case err != nil: 
     log.Fatal(err) 
    default: 
     fmt.Printf("Cube for %d is %d\n", num, myCube) 
    } 

    var cubenum int 

    // //Prepared statement for reading data 
    stmtRead, err := db.Prepare(finalStatement) 
    if err != nil { 
     panic(err.Error()) // needs proper err handling 
    } 
    defer stmtRead.Close() 

    // Query for cube of 5 
    num = 5 
    err = stmtRead.QueryRow(num, cubeLowerLimit).Scan(&cubenum) 
    switch { 
    case err == sql.ErrNoRows: 
     log.Printf("No row with this number %d", num) 
    case err != nil: 
     log.Fatal(err) 
    default: 
     fmt.Printf("Cube number for %d is %d\n", num, cubenum) 
    } 

} 

如果你運行它隨後的時間,你需要刪除的行中的數據庫,以便插入不會產生恐慌(或可選擇地改變插入的行代碼,以便它不慌)。我還沒有在Google App Engine上嘗試過。希望這可以幫助。