// String formats according to a format specifier and sends text response with // status code. func (p Print) String(code int, format string, a ...interface{}) (err error) { buf := bufferpool.Get() defer bufferpool.Put(buf) _, err = fmt.Fprintf(buf, format, a...) if err != nil { return err } return p.string(code, buf.Bytes()) }
// HTML formats according to a format specifier and sends HTML response with // status code. func (p Print) HTML(code int, format string, a ...interface{}) error { buf := bufferpool.Get() defer bufferpool.Put(buf) _, err := fmt.Fprintf(buf, format, a...) if err != nil { return err } return p.html(code, buf.Bytes()) }
// XML sends an XML response with status code. func (p Print) XML(code int, i interface{}) (err error) { buf := bufferpool.Get() defer bufferpool.Put(buf) if err := xml.NewEncoder(buf).Encode(i); err != nil { return errgo.Mask(err) } return p.xml(code, buf.Bytes()) }
// MarshalJSON encodes a pair into JSON func (p Pair) MarshalJSON() ([]byte, error) { var data []byte var err error switch p.NotNull { case NotNullString: data, err = json.Marshal(p.String) if err != nil { return nil, err } case NotNullInt: data, err = json.Marshal(p.Int) if err != nil { return nil, err } case NotNullFloat64: var n = p.Float64 switch { case math.IsInf(p.Float64, 1): n = math.MaxFloat64 case math.IsInf(p.Float64, -1): n = -math.MaxFloat64 case math.IsNaN(p.Float64): n = 0.0 } data, err = json.Marshal(n) if err != nil { return nil, err } case NotNullBool: data, err = json.Marshal(p.Bool) if err != nil { return nil, err } } labelData, err := json.Marshal(p.Label()) if err != nil { return nil, err } var buf = bufferpool.Get() defer bufferpool.Put(buf) buf.WriteString(`{"Value":`) if len(data) == 0 { buf.WriteByte('"') buf.WriteByte('"') } else { buf.Write(data) } buf.WriteString(`,"Label":`) buf.Write(labelData) buf.WriteByte('}') return buf.Bytes(), nil }
// Render renders a template with data and sends a text/html response with status // code. Templates can be registered during `Print` creation. func (p Print) Render(code int, name string, data interface{}) error { if p.Renderer == nil { return ErrRendererNotRegistered } buf := bufferpool.Get() defer bufferpool.Put(buf) if err := p.Renderer.ExecuteTemplate(buf, name, data); err != nil { return err } return p.html(code, buf.Bytes()) }
// ToJSON returns a JSON string, convenience function. func (s Slice) ToJSON() (string, error) { var buf = bufferpool.Get() defer bufferpool.Put(buf) if err := json.NewEncoder(buf).Encode(s); err != nil { if PkgLog.IsDebug() { PkgLog.Debug("config.ValueLabelSlice.ToJSON.Encode", "err", err, "slice", s) } return "", errgo.Mask(err) } return buf.String(), nil }
// Preprocess takes an SQL string with placeholders and a list of arguments to // replace them with. It returns a blank string and error if the number of placeholders // does not match the number of arguments. func Preprocess(sql string, vals []interface{}) (string, error) { // Get the number of arguments to add to this query if sql == "" { if len(vals) != 0 { return "", ErrArgumentMismatch } return "", nil } curVal := 0 var buf = bufferpool.Get() defer bufferpool.Put(buf) pos := 0 for pos < len(sql) { r, w := utf8.DecodeRuneInString(sql[pos:]) pos += w switch { case r == '?': if curVal >= len(vals) { return "", ErrArgumentMismatch } if err := interpolate(buf, vals[curVal]); err != nil { return "", err } curVal++ case r == '`', r == '\'', r == '"': p := strings.IndexRune(sql[pos:], r) if p == -1 { return "", ErrInvalidSyntax } if r == '"' { r = '\'' } buf.WriteRune(r) buf.WriteString(sql[pos : pos+p]) buf.WriteRune(r) pos += p + 1 case r == '[': w := strings.IndexRune(sql[pos:], ']') col := sql[pos : pos+w] D.EscapeIdent(buf, col) pos += w + 1 // size of ']' default: buf.WriteRune(r) } } if curVal != len(vals) { return "", ErrArgumentMismatch } return buf.String(), nil }
// String readable representation of the permissions func (bits Perm) String() string { buf := bufferpool.Get() defer bufferpool.Put(buf) for i := uint(0); i < 64; i++ { if (bits & (1 << i)) != 0 { buf.WriteString(Scope(i).String()) buf.WriteByte(',') } } buf.Truncate(buf.Len() - 1) // remove last colon return buf.String() }
// FQPath returns the fully qualified path. scopeID is an int string. Paths is // either one path (system/smtp/host) including path separators or three // parts ("system", "smtp", "host"). func (s StrScope) FQPath(scopeID string, paths ...string) string { if s == StrDefault && scopeID != strDefaultID { scopeID = strDefaultID // default scope is always 0 } buf := bufferpool.Get() defer bufferpool.Put(buf) buf.WriteString(string(s)) buf.WriteString(PS) buf.WriteString(scopeID) buf.WriteString(PS) for i, p := range paths { buf.WriteString(p) if i < (len(paths) - 1) { buf.WriteString(PS) } } return buf.String() }
// JSONP sends a JSONP response with status code. It uses `callback` to construct // the JSONP payload. func (p Print) JSONP(code int, callback string, i interface{}) (err error) { buf := bufferpool.Get() defer bufferpool.Put(buf) if err := json.NewEncoder(buf).Encode(i); err != nil { return errgo.Mask(err) } p.Response.Header().Set(ContentType, ApplicationJavaScriptCharsetUTF8) p.Response.WriteHeader(code) _, err = p.Response.Write([]byte(callback + "(")) if err != nil { return errgo.Mask(err) } _, err = p.Response.Write(buf.Bytes()) if err != nil { return errgo.Mask(err) } _, err = p.Response.Write([]byte(");")) return errgo.Mask(err) }
// MapToSql serialized the InsertBuilder to a SQL string // It goes through the Maps param and combined its keys/values into the SQL query string // It returns the string with placeholders and a slice of query arguments func (b *InsertBuilder) MapToSql(sql *bytes.Buffer) (string, []interface{}, error) { defer bufferpool.Put(sql) keys := make([]string, len(b.Maps)) vals := make([]interface{}, len(b.Maps)) i := 0 for k, v := range b.Maps { keys[i] = k if dbVal, ok := v.(driver.Valuer); ok { if val, err := dbVal.Value(); err == nil { vals[i] = val } else { return "", nil, errgo.Mask(err) } } else { vals[i] = v } i++ } var args []interface{} var placeholder = bufferpool.Get() // Build the placeholder like "(?,?,?)" defer bufferpool.Put(placeholder) placeholder.WriteRune('(') for i, c := range keys { if i > 0 { sql.WriteRune(',') placeholder.WriteRune(',') } Quoter.writeQuotedColumn(c, sql) placeholder.WriteRune('?') } sql.WriteString(") VALUES ") placeholder.WriteRune(')') sql.WriteString(placeholder.String()) for _, row := range vals { args = append(args, row) } return sql.String(), args, nil }
// ToSql serialized the InsertBuilder to a SQL string // It returns the string with placeholders and a slice of query arguments func (b *InsertBuilder) ToSql() (string, []interface{}, error) { if len(b.Into) == 0 { return "", nil, ErrMissingTable } if len(b.Cols) == 0 && len(b.Maps) == 0 { return "", nil, errgo.New("no columns or map specified") } else if len(b.Maps) == 0 { if len(b.Vals) == 0 && len(b.Recs) == 0 { return "", nil, errgo.New("no values or records specified") } if len(b.Cols) == 0 && (len(b.Vals) > 0 || len(b.Recs) > 0) { return "", nil, errgo.New("no columns specified") } } var sql = bufferpool.Get() sql.WriteString("INSERT INTO ") sql.WriteString(b.Into) sql.WriteString(" (") if len(b.Maps) != 0 { return b.MapToSql(sql) } defer bufferpool.Put(sql) var args []interface{} var placeholder = bufferpool.Get() // Build the placeholder like "(?,?,?)" defer bufferpool.Put(placeholder) // Simulataneously write the cols to the sql buffer, and build a placeholder placeholder.WriteRune('(') for i, c := range b.Cols { if i > 0 { sql.WriteRune(',') placeholder.WriteRune(',') } Quoter.writeQuotedColumn(c, sql) placeholder.WriteRune('?') } sql.WriteString(") VALUES ") placeholder.WriteRune(')') placeholderStr := placeholder.String() // Go thru each value we want to insert. Write the placeholders, and collect args for i, row := range b.Vals { if i > 0 { sql.WriteRune(',') } sql.WriteString(placeholderStr) for _, v := range row { args = append(args, v) } } anyVals := len(b.Vals) > 0 // Go thru the records. Write the placeholders, and do reflection on the records to extract args for i, rec := range b.Recs { if i > 0 || anyVals { sql.WriteRune(',') } sql.WriteString(placeholderStr) ind := reflect.Indirect(reflect.ValueOf(rec)) vals, err := b.valuesFor(ind.Type(), ind, b.Cols) if err != nil { return "", nil, errgo.Mask(err) } for _, v := range vals { args = append(args, v) } } return sql.String(), args, nil }
func interpolate(w QueryWriter, v interface{}) error { valuer, ok := v.(driver.Valuer) if ok { val, err := valuer.Value() if err != nil { return err } v = val } valueOfV := reflect.ValueOf(v) kindOfV := valueOfV.Kind() switch { case v == nil: w.WriteString("NULL") case isInt(kindOfV): var ival = valueOfV.Int() w.WriteString(strconv.FormatInt(ival, 10)) case isUint(kindOfV): var uival = valueOfV.Uint() w.WriteString(strconv.FormatUint(uival, 10)) case kindOfV == reflect.String: var str = valueOfV.String() if !utf8.ValidString(str) { return ErrNotUTF8 } D.EscapeString(w, str) case isFloat(kindOfV): var fval = valueOfV.Float() w.WriteString(strconv.FormatFloat(fval, 'f', -1, 64)) case kindOfV == reflect.Bool: D.EscapeBool(w, valueOfV.Bool()) case kindOfV == reflect.Struct: if typeOfV := valueOfV.Type(); typeOfV == typeOfTime { t := valueOfV.Interface().(time.Time) D.EscapeTime(w, t) } else { return ErrInvalidValue } case kindOfV == reflect.Slice: typeOfV := reflect.TypeOf(v) subtype := typeOfV.Elem() kindOfSubtype := subtype.Kind() sliceLen := valueOfV.Len() stringSlice := make([]string, 0, sliceLen) switch { case sliceLen == 0: return ErrInvalidSliceLength case isInt(kindOfSubtype): for i := 0; i < sliceLen; i++ { var ival = valueOfV.Index(i).Int() stringSlice = append(stringSlice, strconv.FormatInt(ival, 10)) } case isUint(kindOfSubtype): for i := 0; i < sliceLen; i++ { var uival = valueOfV.Index(i).Uint() stringSlice = append(stringSlice, strconv.FormatUint(uival, 10)) } case kindOfSubtype == reflect.String: for i := 0; i < sliceLen; i++ { var str = valueOfV.Index(i).String() if !utf8.ValidString(str) { return ErrNotUTF8 } var buf = bufferpool.Get() D.EscapeString(buf, str) stringSlice = append(stringSlice, buf.String()) bufferpool.Put(buf) } default: return ErrInvalidSliceValue } w.WriteRune('(') w.WriteString(strings.Join(stringSlice, ",")) w.WriteRune(')') default: return ErrInvalidValue } return nil }
// ToSql serialized the UpdateBuilder to a SQL string // It returns the string with placeholders and a slice of query arguments func (b *UpdateBuilder) ToSql() (string, []interface{}, error) { if b.RawFullSql != "" { return b.RawFullSql, b.RawArguments, nil } if len(b.Table.Expression) == 0 { return "", nil, ErrMissingTable } if len(b.SetClauses) == 0 { return "", nil, ErrMissingSet } var sql = bufferpool.Get() defer bufferpool.Put(sql) var args []interface{} sql.WriteString("UPDATE ") sql.WriteString(b.Table.QuoteAs()) sql.WriteString(" SET ") // Build SET clause SQL with placeholders and add values to args for i, c := range b.SetClauses { if i > 0 { sql.WriteString(", ") } Quoter.writeQuotedColumn(c.column, sql) if e, ok := c.value.(*expr); ok { sql.WriteString(" = ") sql.WriteString(e.Sql) args = append(args, e.Values...) } else { sql.WriteString(" = ?") args = append(args, c.value) } } // Write WHERE clause if we have any fragments if len(b.WhereFragments) > 0 { sql.WriteString(" WHERE ") writeWhereFragmentsToSql(b.WhereFragments, sql, &args) } // Ordering and limiting if len(b.OrderBys) > 0 { sql.WriteString(" ORDER BY ") for i, s := range b.OrderBys { if i > 0 { sql.WriteString(", ") } sql.WriteString(s) } } if b.LimitValid { sql.WriteString(" LIMIT ") fmt.Fprint(sql, b.LimitCount) } if b.OffsetValid { sql.WriteString(" OFFSET ") fmt.Fprint(sql, b.OffsetCount) } return sql.String(), args, nil }
// ToSql serialized the SelectBuilder to a SQL string // It returns the string with placeholders and a slice of query arguments func (b *SelectBuilder) ToSql() (string, []interface{}, error) { if b.RawFullSql != "" { return b.RawFullSql, b.RawArguments, nil } if len(b.Columns) == 0 { panic("no columns specified") } if len(b.FromTable.Expression) == 0 { panic("no table specified") } var sql = bufferpool.Get() defer bufferpool.Put(sql) var args []interface{} sql.WriteString("SELECT ") if b.IsDistinct { sql.WriteString("DISTINCT ") } for i, s := range b.Columns { if i > 0 { sql.WriteString(", ") } sql.WriteString(s) } if len(b.JoinFragments) > 0 { for _, f := range b.JoinFragments { for _, c := range f.Columns { sql.WriteString(", ") sql.WriteString(c) } } } sql.WriteString(" FROM ") sql.WriteString(b.FromTable.QuoteAs()) if len(b.JoinFragments) > 0 { for _, f := range b.JoinFragments { sql.WriteRune(' ') sql.WriteString(f.JoinType) sql.WriteString(" JOIN ") sql.WriteString(f.Table.QuoteAs()) sql.WriteString(" ON ") writeWhereFragmentsToSql(f.OnConditions, sql, &args) } } if len(b.WhereFragments) > 0 { sql.WriteString(" WHERE ") writeWhereFragmentsToSql(b.WhereFragments, sql, &args) } if len(b.GroupBys) > 0 { sql.WriteString(" GROUP BY ") for i, s := range b.GroupBys { if i > 0 { sql.WriteString(", ") } sql.WriteString(s) } } if len(b.HavingFragments) > 0 { sql.WriteString(" HAVING ") writeWhereFragmentsToSql(b.HavingFragments, sql, &args) } if len(b.OrderBys) > 0 { sql.WriteString(" ORDER BY ") for i, s := range b.OrderBys { if i > 0 { sql.WriteString(", ") } sql.WriteString(s) } } if b.LimitValid { sql.WriteString(" LIMIT ") fmt.Fprint(sql, b.LimitCount) } if b.OffsetValid { sql.WriteString(" OFFSET ") fmt.Fprint(sql, b.OffsetCount) } return sql.String(), args, nil }