Exemple #1
0
// ToColumnsValuesAndArguments maps the given columnNames and columnValues into
// expr's Columns and Values, it also extracts and returns query arguments.
func (tu *templateWithUtils) ToColumnsValuesAndArguments(columnNames []string, columnValues []interface{}) (*exql.Columns, *exql.Values, []interface{}, error) {
	var arguments []interface{}

	columns := new(exql.Columns)

	columns.Columns = make([]exql.Fragment, 0, len(columnNames))
	for i := range columnNames {
		columns.Columns = append(columns.Columns, exql.ColumnWithName(columnNames[i]))
	}

	values := new(exql.Values)

	arguments = make([]interface{}, 0, len(columnValues))
	values.Values = make([]exql.Fragment, 0, len(columnValues))

	for i := range columnValues {
		switch v := columnValues[i].(type) {
		case *exql.Value:
			// Adding value.
			values.Values = append(values.Values, v)
		case exql.Value:
			// Adding value.
			values.Values = append(values.Values, &v)
		default:
			// Adding both value and placeholder.
			values.Values = append(values.Values, sqlPlaceholder)
			arguments = append(arguments, v)
		}
	}

	return columns, values, arguments, nil
}
Exemple #2
0
func (qu *updater) Set(columns ...interface{}) Updater {

	if len(columns) == 1 {
		ff, vv, err := Map(columns[0], nil)
		if err == nil {

			cvs := make([]exql.Fragment, 0, len(ff))
			args := make([]interface{}, 0, len(vv))

			for i := range ff {
				cv := &exql.ColumnValue{
					Column:   exql.ColumnWithName(ff[i]),
					Operator: qu.builder.t.AssignmentOperator,
				}

				var localArgs []interface{}
				cv.Value, localArgs = qu.builder.t.PlaceholderValue(vv[i])

				args = append(args, localArgs...)
				cvs = append(cvs, cv)
			}

			qu.columnValues.Insert(cvs...)
			qu.columnValuesArgs = append(qu.columnValuesArgs, args...)
			return qu
		}
	}

	cv, arguments := qu.builder.t.ToColumnValues(columns)
	qu.columnValues.Insert(cv.ColumnValues...)
	qu.columnValuesArgs = append(qu.columnValuesArgs, arguments...)

	return qu
}
Exemple #3
0
func (qi *inserter) columnsToFragments(dst *[]exql.Fragment, columns []string) error {
	l := len(columns)
	f := make([]exql.Fragment, l)
	for i := 0; i < l; i++ {
		f[i] = exql.ColumnWithName(columns[i])
	}
	*dst = append(*dst, f...)
	return nil
}
Exemple #4
0
func (qs *selector) As(alias string) Selector {
	if qs.table == nil {
		qs.setErr(errors.New("Cannot use As() without a preceding From() expression"))
		return qs
	}
	last := len(qs.table.Columns) - 1
	if raw, ok := qs.table.Columns[last].(*exql.Raw); ok {
		qs.table.Columns[last] = exql.RawValue("(" + raw.Value + ") AS " + exql.ColumnWithName(alias).Compile(qs.stringer.t))
	}
	return qs
}
Exemple #5
0
func columnFragments(template *templateWithUtils, columns []interface{}) ([]exql.Fragment, []interface{}, error) {
	l := len(columns)
	f := make([]exql.Fragment, l)
	args := []interface{}{}

	for i := 0; i < l; i++ {
		switch v := columns[i].(type) {
		case *selector:
			expanded, rawArgs := Preprocess(v.statement().Compile(v.stringer.t), v.Arguments())
			f[i] = exql.RawValue(expanded)
			args = append(args, rawArgs...)
		case db.Function:
			fnName, fnArgs := v.Name(), v.Arguments()
			if len(fnArgs) == 0 {
				fnName = fnName + "()"
			} else {
				fnName = fnName + "(?" + strings.Repeat("?, ", len(fnArgs)-1) + ")"
			}
			expanded, fnArgs := Preprocess(fnName, fnArgs)
			f[i] = exql.RawValue(expanded)
			args = append(args, fnArgs...)
		case db.RawValue:
			expanded, rawArgs := Preprocess(v.Raw(), v.Arguments())
			f[i] = exql.RawValue(expanded)
			args = append(args, rawArgs...)
		case exql.Fragment:
			f[i] = v
		case string:
			f[i] = exql.ColumnWithName(v)
		case interface{}:
			f[i] = exql.ColumnWithName(fmt.Sprintf("%v", v))
		default:
			return nil, nil, fmt.Errorf("Unexpected argument type %T for Select() argument.", v)
		}
	}
	return f, args, nil
}
Exemple #6
0
func (qs *selector) OrderBy(columns ...interface{}) Selector {
	var sortColumns exql.SortColumns

	for i := range columns {
		var sort *exql.SortColumn

		switch value := columns[i].(type) {
		case db.RawValue:
			col, args := Preprocess(value.Raw(), value.Arguments())
			sort = &exql.SortColumn{
				Column: exql.RawValue(col),
			}
			qs.mu.Lock()
			qs.orderByArgs = append(qs.orderByArgs, args...)
			qs.mu.Unlock()
		case db.Function:
			fnName, fnArgs := value.Name(), value.Arguments()
			if len(fnArgs) == 0 {
				fnName = fnName + "()"
			} else {
				fnName = fnName + "(?" + strings.Repeat("?, ", len(fnArgs)-1) + ")"
			}
			expanded, fnArgs := Preprocess(fnName, fnArgs)
			sort = &exql.SortColumn{
				Column: exql.RawValue(expanded),
			}
			qs.mu.Lock()
			qs.orderByArgs = append(qs.orderByArgs, fnArgs...)
			qs.mu.Unlock()
		case string:
			if strings.HasPrefix(value, "-") {
				sort = &exql.SortColumn{
					Column: exql.ColumnWithName(value[1:]),
					Order:  exql.Descendent,
				}
			} else {
				chunks := strings.SplitN(value, " ", 2)

				order := exql.Ascendent
				if len(chunks) > 1 && strings.ToUpper(chunks[1]) == "DESC" {
					order = exql.Descendent
				}

				sort = &exql.SortColumn{
					Column: exql.ColumnWithName(chunks[0]),
					Order:  order,
				}
			}
		default:
			qs.setErr(fmt.Errorf("Can't sort by type %T", value))
			return qs
		}
		sortColumns.Columns = append(sortColumns.Columns, sort)
	}

	qs.mu.Lock()
	qs.orderBy = &exql.OrderBy{
		SortColumns: &sortColumns,
	}
	qs.mu.Unlock()

	return qs
}
Exemple #7
0
// ToColumnValues converts the given conditions into a exql.ColumnValues struct.
func (tu *templateWithUtils) ToColumnValues(term interface{}) (cv exql.ColumnValues, args []interface{}) {
	args = []interface{}{}

	switch t := term.(type) {
	case []interface{}:
		l := len(t)
		for i := 0; i < l; i++ {
			column, ok := t[i].(string)

			if !ok {
				p, q := tu.ToColumnValues(t[i])
				cv.ColumnValues = append(cv.ColumnValues, p.ColumnValues...)
				args = append(args, q...)
				continue
			}

			if !strings.ContainsAny(column, "=") {
				column = fmt.Sprintf("%s = ?", column)
			}

			chunks := strings.SplitN(column, "=", 2)

			column = chunks[0]
			format := strings.TrimSpace(chunks[1])

			columnValue := exql.ColumnValue{
				Column:   exql.ColumnWithName(column),
				Operator: "=",
				Value:    exql.RawValue(format),
			}

			ps := strings.Count(format, "?")
			if i+ps < l {
				for j := 0; j < ps; j++ {
					args = append(args, t[i+j+1])
				}
				i = i + ps
			} else {
				panic(fmt.Sprintf("Format string %q has more placeholders than given arguments.", format))
			}

			cv.ColumnValues = append(cv.ColumnValues, &columnValue)
		}
		return cv, args
	case db.Constraint:
		columnValue := exql.ColumnValue{}

		// Guessing operator from input, or using a default one.
		if column, ok := t.Key().(string); ok {
			chunks := strings.SplitN(strings.TrimSpace(column), ` `, 2)
			columnValue.Column = exql.ColumnWithName(chunks[0])
			if len(chunks) > 1 {
				columnValue.Operator = chunks[1]
			}
		} else {
			if rawValue, ok := t.Key().(db.RawValue); ok {
				columnValue.Column = exql.RawValue(rawValue.Raw())
				args = append(args, rawValue.Arguments()...)
			} else {
				columnValue.Column = exql.RawValue(fmt.Sprintf("%v", t.Key()))
			}
		}

		switch value := t.Value().(type) {
		case db.Function:
			fnName, fnArgs := value.Name(), value.Arguments()
			if len(fnArgs) == 0 {
				// A function with no arguments.
				fnName = fnName + "()"
			} else {
				// A function with one or more arguments.
				fnName = fnName + "(?" + strings.Repeat("?, ", len(fnArgs)-1) + ")"
			}
			expanded, fnArgs := Preprocess(fnName, fnArgs)
			columnValue.Value = exql.RawValue(expanded)
			args = append(args, fnArgs...)
		case db.RawValue:
			expanded, rawArgs := Preprocess(value.Raw(), value.Arguments())
			columnValue.Value = exql.RawValue(expanded)
			args = append(args, rawArgs...)
		default:
			v, isSlice := toInterfaceArguments(value)

			if isSlice {
				if columnValue.Operator == "" {
					columnValue.Operator = sqlInOperator
				}
				if len(v) > 0 {
					// Array value given.
					columnValue.Value = exql.RawValue(fmt.Sprintf(`(?%s)`, strings.Repeat(`, ?`, len(v)-1)))
				} else {
					// Single value given.
					columnValue.Value = exql.RawValue(`(NULL)`)
				}
				args = append(args, v...)
			} else {
				if v == nil {
					// Nil value given.
					columnValue.Value = sqlNull
					if columnValue.Operator == "" {
						columnValue.Operator = sqlIsOperator
					}
				} else {
					columnValue.Value = sqlPlaceholder
					args = append(args, v...)
				}
			}

		}

		// Using guessed operator if no operator was given.
		if columnValue.Operator == "" {
			if tu.DefaultOperator != "" {
				columnValue.Operator = tu.DefaultOperator
			} else {
				columnValue.Operator = sqlDefaultOperator
			}
		}

		cv.ColumnValues = append(cv.ColumnValues, &columnValue)

		return cv, args
	case db.RawValue:
		columnValue := exql.ColumnValue{}
		p, q := Preprocess(t.Raw(), t.Arguments())

		columnValue.Column = exql.RawValue(p)
		args = append(args, q...)

		cv.ColumnValues = append(cv.ColumnValues, &columnValue)
		return cv, args
	case db.Constraints:
		for _, c := range t.Constraints() {
			p, q := tu.ToColumnValues(c)
			cv.ColumnValues = append(cv.ColumnValues, p.ColumnValues...)
			args = append(args, q...)
		}
		return cv, args
	}

	panic(fmt.Sprintf("Unknown term type %T.", term))
}