mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 02:32:25 -05:00 
			
		
		
		
	This allows for building GoToSocial with [SQLite transpiled to WASM](https://github.com/ncruces/go-sqlite3) and accessed through [Wazero](https://wazero.io/).
		
			
				
	
	
		
			112 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package sqlite3
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"math"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 	"unsafe"
 | |
| 
 | |
| 	"github.com/ncruces/go-sqlite3/internal/util"
 | |
| )
 | |
| 
 | |
| // Quote escapes and quotes a value
 | |
| // making it safe to embed in SQL text.
 | |
| func Quote(value any) string {
 | |
| 	switch v := value.(type) {
 | |
| 	case nil:
 | |
| 		return "NULL"
 | |
| 	case bool:
 | |
| 		if v {
 | |
| 			return "1"
 | |
| 		} else {
 | |
| 			return "0"
 | |
| 		}
 | |
| 
 | |
| 	case int:
 | |
| 		return strconv.Itoa(v)
 | |
| 	case int64:
 | |
| 		return strconv.FormatInt(v, 10)
 | |
| 	case float64:
 | |
| 		switch {
 | |
| 		case math.IsNaN(v):
 | |
| 			return "NULL"
 | |
| 		case math.IsInf(v, 1):
 | |
| 			return "9.0e999"
 | |
| 		case math.IsInf(v, -1):
 | |
| 			return "-9.0e999"
 | |
| 		}
 | |
| 		return strconv.FormatFloat(v, 'g', -1, 64)
 | |
| 	case time.Time:
 | |
| 		return "'" + v.Format(time.RFC3339Nano) + "'"
 | |
| 
 | |
| 	case string:
 | |
| 		if strings.IndexByte(v, 0) >= 0 {
 | |
| 			break
 | |
| 		}
 | |
| 
 | |
| 		buf := make([]byte, 2+len(v)+strings.Count(v, "'"))
 | |
| 		buf[0] = '\''
 | |
| 		i := 1
 | |
| 		for _, b := range []byte(v) {
 | |
| 			if b == '\'' {
 | |
| 				buf[i] = b
 | |
| 				i += 1
 | |
| 			}
 | |
| 			buf[i] = b
 | |
| 			i += 1
 | |
| 		}
 | |
| 		buf[i] = '\''
 | |
| 		return unsafe.String(&buf[0], len(buf))
 | |
| 
 | |
| 	case []byte:
 | |
| 		buf := make([]byte, 3+2*len(v))
 | |
| 		buf[0] = 'x'
 | |
| 		buf[1] = '\''
 | |
| 		i := 2
 | |
| 		for _, b := range v {
 | |
| 			const hex = "0123456789ABCDEF"
 | |
| 			buf[i+0] = hex[b/16]
 | |
| 			buf[i+1] = hex[b%16]
 | |
| 			i += 2
 | |
| 		}
 | |
| 		buf[i] = '\''
 | |
| 		return unsafe.String(&buf[0], len(buf))
 | |
| 
 | |
| 	case ZeroBlob:
 | |
| 		if v > ZeroBlob(1e9-3)/2 {
 | |
| 			break
 | |
| 		}
 | |
| 
 | |
| 		buf := bytes.Repeat([]byte("0"), int(3+2*int64(v)))
 | |
| 		buf[0] = 'x'
 | |
| 		buf[1] = '\''
 | |
| 		buf[len(buf)-1] = '\''
 | |
| 		return unsafe.String(&buf[0], len(buf))
 | |
| 	}
 | |
| 
 | |
| 	panic(util.ValueErr)
 | |
| }
 | |
| 
 | |
| // QuoteIdentifier escapes and quotes an identifier
 | |
| // making it safe to embed in SQL text.
 | |
| func QuoteIdentifier(id string) string {
 | |
| 	if strings.IndexByte(id, 0) >= 0 {
 | |
| 		panic(util.ValueErr)
 | |
| 	}
 | |
| 
 | |
| 	buf := make([]byte, 2+len(id)+strings.Count(id, `"`))
 | |
| 	buf[0] = '"'
 | |
| 	i := 1
 | |
| 	for _, b := range []byte(id) {
 | |
| 		if b == '"' {
 | |
| 			buf[i] = b
 | |
| 			i += 1
 | |
| 		}
 | |
| 		buf[i] = b
 | |
| 		i += 1
 | |
| 	}
 | |
| 	buf[i] = '"'
 | |
| 	return unsafe.String(&buf[0], len(buf))
 | |
| }
 |