// Invariant: only called when len(fragments) > 0 func writeWhereFragmentsToSql(buf common.BufferWriter, fragments []*whereFragment, args *[]interface{}, pos *int64) { hasConditions := false for _, f := range fragments { if f.Condition != "" { if hasConditions { buf.WriteString(" AND (") } else { buf.WriteRune('(') hasConditions = true } if len(f.Values) > 0 { // map relative $1, $2 placeholders to absolute replaced := remapPlaceholders(buf, f.Condition, *pos) *pos += replaced *args = append(*args, f.Values...) } else { buf.WriteString(f.Condition) } buf.WriteRune(')') } else if f.EqualityMap != nil { hasConditions = writeEqualityMapToSql(buf, f.EqualityMap, args, hasConditions, pos) } else { panic("invalid equality map") } } }
func writePlaceholder64(buf common.BufferWriter, pos int64) { if pos < maxLookup { buf.WriteString(placeholderTab[pos]) } else { buf.WriteRune('$') buf.WriteString(strconv.FormatInt(pos, 10)) } }
func writePlaceholder(buf common.BufferWriter, pos int) { if pos < maxLookup { buf.WriteString(placeholderTab[pos]) } else { buf.WriteRune('$') buf.WriteString(strconv.Itoa(pos)) } }
// Invariant: for scope conditions only func writeScopeCondition(buf common.BufferWriter, f *whereFragment, args *[]interface{}, pos *int64) { buf.WriteRune(' ') if len(f.Values) > 0 { // map relative $1, $2 placeholders to absolute replaced := remapPlaceholders(buf, f.Condition, *pos) *pos += replaced *args = append(*args, f.Values...) } else { buf.WriteString(f.Condition) } }
func writeWhereCondition(buf common.BufferWriter, k string, pred string, anyConditions bool) bool { if anyConditions { buf.WriteString(" AND (") } else { buf.WriteRune('(') anyConditions = true } Dialect.WriteIdentifier(buf, k) buf.WriteString(pred) buf.WriteRune(')') return anyConditions }
// WriteIdentifier writes escaped identifier. func (pd *Postgres) WriteIdentifier(buf common.BufferWriter, ident string) { if ident == "" { panic("Identifier is empty string") } buf.WriteRune('"') if strings.Contains(ident, ".") { for _, char := range ident { if char == '.' { buf.WriteString("\".\"") } else { buf.WriteRune(char) } } } else { buf.WriteString(ident) } buf.WriteRune('"') }
// WriteStringLiteral writes an escaped string. No escape characters // are allowed. // // Postgres 9.1+ does not allow any escape // sequences by default. See http://www.postgresql.org/docs/9.3/interactive/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE // In short, all backslashes are treated literally not as escape sequences. func (pd *Postgres) WriteStringLiteral(buf common.BufferWriter, val string) { if val == "" { buf.WriteString("''") return } hasTag := true // don't use double dollar quote strings unless the string is long enough if len(val) > 64 { // if pgDollarTag unique tag is in string, try to create a new one (only once though) hasTag = strings.Contains(val, pgDollarTag) if hasTag { randomizePgDollarTag() hasTag = strings.Contains(val, pgDollarTag) } } if hasTag { buf.WriteRune('\'') if strings.Contains(val, "'") { for _, char := range val { // apos if char == '\'' { buf.WriteString(`''`) } else if char == 0 { panic("postgres doesn't support NULL char in text, see http://stackoverflow.com/questions/1347646/postgres-error-on-insert-error-invalid-byte-sequence-for-encoding-utf8-0x0") } else { buf.WriteRune(char) } } } else { buf.WriteString(val) } buf.WriteRune('\'') } else { buf.WriteString(pgDollarTag) buf.WriteString(val) buf.WriteString(pgDollarTag) } }