Пример #1
0
func (d *Driver) clause(buf *bytes.Buffer, params *[]interface{}, m driver.Model, format string, f *query.Field, begin int) error {
	dbName, _, err := m.Map(f.Field)
	if err != nil {
		return err
	}
	if f.Value != nil {
		if field, ok := f.Value.(query.F); ok {
			fName, _, err := m.Map(string(field))
			if err != nil {
				return err
			}
			fmt.Fprintf(buf, format, dbName, fName)
			return nil
		}
		if sq, ok := f.Value.(query.Subquery); ok {
			fmt.Fprintf(buf, format, dbName, "("+string(sq)+")")
			return nil
		}
		fmt.Fprintf(buf, format, dbName, d.backend.Placeholder(len(*params)+begin))
		val, err := d.transformOutValue(f.Value)
		if err != nil {
			return err
		}
		*params = append(*params, val)
		return nil
	}
	fmt.Fprintf(buf, format, dbName)
	return nil
}
Пример #2
0
func (d *Driver) Operate(m driver.Model, q query.Q, ops []*operation.Operation) (driver.Result, error) {
	buf := getBuffer()
	buf.WriteString("UPDATE ")
	buf.WriteByte('"')
	buf.WriteString(m.Table())
	buf.WriteByte('"')
	buf.WriteString(" SET ")
	var params []interface{}
	for ii, op := range ops {
		if ii > 0 {
			buf.WriteByte(',')
		}
		dbName, _, err := m.Map(op.Field)
		if err != nil {
			return nil, err
		}
		dbName = unquote(dbName)
		buf.WriteByte('"')
		buf.WriteString(dbName)
		buf.WriteByte('"')
		buf.WriteByte('=')
		switch op.Operator {
		case operation.OpAdd, operation.OpSub:
			buf.WriteString(dbName)
			if op.Operator == operation.OpAdd {
				buf.WriteByte('+')
			} else {
				buf.WriteByte('-')
			}
			buf.WriteString(d.backend.Placeholder(len(params)))
			params = append(params, op.Value)
		case operation.OpSet:
			if f, ok := op.Value.(operation.Field); ok {
				fieldName, _, err := m.Map(string(f))
				if err != nil {
					return nil, err
				}
				buf.WriteString(unquote(fieldName))
			} else {
				buf.WriteString(d.backend.Placeholder(len(params)))
				val, err := d.transformOutValue(op.Value)
				if err != nil {
					return nil, err
				}
				params = append(params, val)
			}
		default:
			return nil, fmt.Errorf("operator %d is not supported", op.Operator)
		}
	}
	qParams, err := d.where(buf, m, q, len(params))
	if err != nil {
		return nil, err
	}
	params = append(params, qParams...)
	res, err := d.db.Exec(buftos(buf), params...)
	putBuffer(buf)
	return res, err
}
Пример #3
0
func (d *Driver) indexName(m driver.Model, idx *index.Index) (string, error) {
	if len(idx.Fields) == 0 {
		return "", fmt.Errorf("index on %v has no fields", m.Type())
	}
	buf := getBuffer()
	buf.WriteString(m.Table())
	for _, v := range idx.Fields {
		dbName, _, err := m.Map(v)
		if err != nil {
			return "", err
		}
		buf.WriteByte('_')
		// dbName is quoted and includes the table name
		// extract the unquoted field name.
		buf.WriteString(unquote(dbName))
		if DescField(idx, v) {
			buf.WriteString("_desc")
		}
	}
	s := buf.String()
	putBuffer(buf)
	return s, nil
}
Пример #4
0
func (d *Driver) Select(fields []string, quote bool, m driver.Model, q query.Q, opts driver.QueryOptions) (*bytes.Buffer, []interface{}, error) {
	buf := getBuffer()
	var params []interface{}
	if err := d.selectStmt(buf, &params, fields, quote, m, opts); err != nil {
		return nil, nil, err
	}
	qParams, err := d.where(buf, m, q, 0)
	if err != nil {
		return nil, nil, err
	}
	params = append(params, qParams...)
	if len(opts.Sort) > 0 {
		buf.WriteString(" ORDER BY ")
		for _, v := range opts.Sort {
			dbName, _, err := m.Map(v.Field())
			if err != nil {
				return nil, nil, err
			}
			buf.WriteString(dbName)
			if v.Direction() == driver.DESC {
				buf.WriteString(" DESC")
			}
			buf.WriteByte(',')
		}
		buf.Truncate(buf.Len() - 1)
	}
	if opts.Limit >= 0 {
		buf.WriteString(" LIMIT ")
		buf.WriteString(strconv.Itoa(opts.Limit))
	}
	if opts.Offset >= 0 {
		buf.WriteString(" OFFSET ")
		buf.WriteString(strconv.Itoa(opts.Offset))
	}
	return buf, params, nil
}
Пример #5
0
func (d *Driver) condition(buf *bytes.Buffer, params *[]interface{}, m driver.Model, q query.Q, begin int) error {
	var err error
	switch x := q.(type) {
	case *query.Eq:
		if isNil(x.Value) {
			x.Value = nil
			err = d.clause(buf, params, m, "%s IS NULL", &x.Field, begin)
		} else {
			err = d.clause(buf, params, m, "%s = %s", &x.Field, begin)
		}
	case *query.Neq:
		if isNil(x.Value) {
			x.Value = nil
			err = d.clause(buf, params, m, "%s IS NOT NULL", &x.Field, begin)
		} else {
			err = d.clause(buf, params, m, "%s != %s", &x.Field, begin)
		}
	case *query.Contains:
		err = d.clause(buf, params, m, "%s LIKE '%%' || %s || '%%'", &x.Field, begin)
	case *query.Lt:
		err = d.clause(buf, params, m, "%s < %s", &x.Field, begin)
	case *query.Lte:
		err = d.clause(buf, params, m, "%s <= %s", &x.Field, begin)
	case *query.Gt:
		err = d.clause(buf, params, m, "%s > %s", &x.Field, begin)
	case *query.Gte:
		err = d.clause(buf, params, m, "%s >= %s", &x.Field, begin)
	case *query.Operator:
		err = d.clause(buf, params, m, "%s "+x.Operator+" %s", &x.Field, begin)
	case *query.In:
		dbName, _, err := m.Map(x.Field.Field)
		if err != nil {
			return err
		}
		buf.WriteString(dbName)
		buf.WriteString(" IN (")
		value := reflect.ValueOf(x.Value)
		switch {
		case value.Type() == subqueryType:
			buf.WriteString(value.String())
		case value.Type().Kind() == reflect.Slice || value.Type().Kind() == reflect.Array:
			vLen := value.Len()
			if vLen == 0 {
				return fmt.Errorf("empty IN (field %s)", x.Field.Field)
			}
			jj := len(*params) + begin
			for ii := 0; ii < vLen; ii++ {
				*params = append(*params, value.Index(ii).Interface())
				buf.WriteString(d.backend.Placeholder(jj))
				buf.WriteByte(',')
				jj++
			}
			buf.Truncate(buf.Len() - 1)
		default:
			return fmt.Errorf("argument for IN must be slice or array or query.Subquery (field %s)", x.Field.Field)
		}
		buf.WriteByte(')')
	case *query.And:
		err = d.conditions(buf, params, m, x.Conditions, " AND ", begin)
	case *query.Or:
		err = d.conditions(buf, params, m, x.Conditions, " OR ", begin)
	default:
		err = fmt.Errorf("unhandled operand %T (%v)", x, x)
	}
	return err
}