func readFilters()

in pkg/data-query/parser.go [210:279]


func readFilters(list []*fastjson.Value, query *Query) error {
	for _, v := range list {
		t := QueryFilter{
			Field:    string(v.GetStringBytes("f")),
			Sql:      string(v.GetStringBytes("q")),
			Operator: string(v.GetStringBytes("o")),
			Split:    false,
		}

		if t.Sql == "" {
			t.Sql = string(v.GetStringBytes("sql"))
		}

		value := v.Get("v")
		t.Split = v.GetBool("s")
		if value == nil {
			value = v.Get("value")
		}

		if !isValidFilterFieldName(t.Field) && t.Sql == "" {
			return http_error.NewHttpError(400, t.Field+" is not a valid filter field name")
		}

		if t.Sql == "" && value == nil {
			return errors.New("filter value is not specified")
		}
		if t.Sql == "" {
			switch value.Type() {
			case fastjson.TypeString:
				t.Value = string(value.GetStringBytes())
			case fastjson.TypeNumber:
				number, err := value.Float64()
				if err != nil {
					return fmt.Errorf("cannot parse filter value %s: %w", value, err)
				}
				if number == math.Trunc(number) {
					// convert to int (to be able to use time unix timestamps from client side)
					t.Value = int(number)
				} else {
					t.Value = number
				}
			case fastjson.TypeArray:
				t.Value = readArray(value)
			case fastjson.TypeFalse:
				t.Value = value.GetBool()
			case fastjson.TypeTrue:
				t.Value = value.GetBool()
			default:
				return fmt.Errorf("filter value %v is not supported", value)
			}

			if t.Operator == "" {
				t.Operator = "="
			} else if t.Operator != ">" && t.Operator != "<" && t.Operator != "=" && t.Operator != "!=" && t.Operator != "like" {
				return fmt.Errorf("operator %s is not supported", t.Operator)
			}
		} else {
			// by intention sql string is not validated
			if t.Operator != "" {
				return http_error.NewHttpError(400, fmt.Sprintf("sql and operator are mutually exclusive (filter=%s)", t.Field))
			}
			if t.Value != nil {
				return http_error.NewHttpError(400, fmt.Sprintf("sql and value are mutually exclusive (filter=%s)", t.Field))
			}
		}

		query.Filters = append(query.Filters, t)
	}
	return nil
}