mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-03 21:08:25 +00:00 
			
		
		
		
	* Upgrade xorm to v1.0.0 * small nit * Fix tests * Update xorm * Update xorm * fix go.sum * fix test * Fix bug when dump * Fix bug * update xorm to latest * Fix migration test * update xorm to latest * Fix import order * Use xorm tag
		
			
				
	
	
		
			166 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
// Copyright 2018 The Xorm Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package builder
 | 
						|
 | 
						|
import (
 | 
						|
	sql2 "database/sql"
 | 
						|
	"fmt"
 | 
						|
	"reflect"
 | 
						|
	"strings"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
func condToSQL(cond Cond) (string, []interface{}, error) {
 | 
						|
	if cond == nil || !cond.IsValid() {
 | 
						|
		return "", nil, nil
 | 
						|
	}
 | 
						|
 | 
						|
	w := NewWriter()
 | 
						|
	if err := cond.WriteTo(w); err != nil {
 | 
						|
		return "", nil, err
 | 
						|
	}
 | 
						|
	return w.String(), w.args, nil
 | 
						|
}
 | 
						|
 | 
						|
func condToBoundSQL(cond Cond) (string, error) {
 | 
						|
	if cond == nil || !cond.IsValid() {
 | 
						|
		return "", nil
 | 
						|
	}
 | 
						|
 | 
						|
	w := NewWriter()
 | 
						|
	if err := cond.WriteTo(w); err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
	return ConvertToBoundSQL(w.String(), w.args)
 | 
						|
}
 | 
						|
 | 
						|
// ToSQL convert a builder or conditions to SQL and args
 | 
						|
func ToSQL(cond interface{}) (string, []interface{}, error) {
 | 
						|
	switch cond.(type) {
 | 
						|
	case Cond:
 | 
						|
		return condToSQL(cond.(Cond))
 | 
						|
	case *Builder:
 | 
						|
		return cond.(*Builder).ToSQL()
 | 
						|
	}
 | 
						|
	return "", nil, ErrNotSupportType
 | 
						|
}
 | 
						|
 | 
						|
// ToBoundSQL convert a builder or conditions to parameters bound SQL
 | 
						|
func ToBoundSQL(cond interface{}) (string, error) {
 | 
						|
	switch cond.(type) {
 | 
						|
	case Cond:
 | 
						|
		return condToBoundSQL(cond.(Cond))
 | 
						|
	case *Builder:
 | 
						|
		return cond.(*Builder).ToBoundSQL()
 | 
						|
	}
 | 
						|
	return "", ErrNotSupportType
 | 
						|
}
 | 
						|
 | 
						|
func noSQLQuoteNeeded(a interface{}) bool {
 | 
						|
	switch a.(type) {
 | 
						|
	case int, int8, int16, int32, int64:
 | 
						|
		return true
 | 
						|
	case uint, uint8, uint16, uint32, uint64:
 | 
						|
		return true
 | 
						|
	case float32, float64:
 | 
						|
		return true
 | 
						|
	case bool:
 | 
						|
		return true
 | 
						|
	case string:
 | 
						|
		return false
 | 
						|
	case time.Time, *time.Time:
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	t := reflect.TypeOf(a)
 | 
						|
 | 
						|
	switch t.Kind() {
 | 
						|
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
						|
		return true
 | 
						|
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
						|
		return true
 | 
						|
	case reflect.Float32, reflect.Float64:
 | 
						|
		return true
 | 
						|
	case reflect.Bool:
 | 
						|
		return true
 | 
						|
	case reflect.String:
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// ConvertToBoundSQL will convert SQL and args to a bound SQL
 | 
						|
func ConvertToBoundSQL(sql string, args []interface{}) (string, error) {
 | 
						|
	buf := strings.Builder{}
 | 
						|
	var i, j, start int
 | 
						|
	for ; i < len(sql); i++ {
 | 
						|
		if sql[i] == '?' {
 | 
						|
			_, err := buf.WriteString(sql[start:i])
 | 
						|
			if err != nil {
 | 
						|
				return "", err
 | 
						|
			}
 | 
						|
			start = i + 1
 | 
						|
 | 
						|
			if len(args) == j {
 | 
						|
				return "", ErrNeedMoreArguments
 | 
						|
			}
 | 
						|
 | 
						|
			arg := args[j]
 | 
						|
			if namedArg, ok := arg.(sql2.NamedArg); ok {
 | 
						|
				arg = namedArg.Value
 | 
						|
			}
 | 
						|
 | 
						|
			if noSQLQuoteNeeded(arg) {
 | 
						|
				_, err = fmt.Fprint(&buf, arg)
 | 
						|
			} else {
 | 
						|
				// replace ' -> '' (standard replacement) to avoid critical SQL injection,
 | 
						|
				// NOTICE: may allow some injection like % (or _) in LIKE query
 | 
						|
				_, err = fmt.Fprintf(&buf, "'%v'", strings.Replace(fmt.Sprintf("%v", arg), "'",
 | 
						|
					"''", -1))
 | 
						|
			}
 | 
						|
			if err != nil {
 | 
						|
				return "", err
 | 
						|
			}
 | 
						|
			j = j + 1
 | 
						|
		}
 | 
						|
	}
 | 
						|
	_, err := buf.WriteString(sql[start:])
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
	return buf.String(), nil
 | 
						|
}
 | 
						|
 | 
						|
// ConvertPlaceholder replaces the place holder ? to $1, $2 ... or :1, :2 ... according prefix
 | 
						|
func ConvertPlaceholder(sql, prefix string) (string, error) {
 | 
						|
	buf := strings.Builder{}
 | 
						|
	var i, j, start int
 | 
						|
	var ready = true
 | 
						|
	for ; i < len(sql); i++ {
 | 
						|
		if sql[i] == '\'' && i > 0 && sql[i-1] != '\\' {
 | 
						|
			ready = !ready
 | 
						|
		}
 | 
						|
		if ready && sql[i] == '?' {
 | 
						|
			if _, err := buf.WriteString(sql[start:i]); err != nil {
 | 
						|
				return "", err
 | 
						|
			}
 | 
						|
 | 
						|
			start = i + 1
 | 
						|
			j = j + 1
 | 
						|
 | 
						|
			if _, err := buf.WriteString(fmt.Sprintf("%v%d", prefix, j)); err != nil {
 | 
						|
				return "", err
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if _, err := buf.WriteString(sql[start:]); err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
 | 
						|
	return buf.String(), nil
 | 
						|
}
 |