func TestDateRangeBuilder(t *testing.T) {

	const expected = `select * from event where key in ($1) and created >= $2 and created < $3 order by created desc;`

	q := straumur.Query{}
	q.Key = "somekey"
	q.From = time.Date(2013, time.September, 20, 9, 1, 45, 0, time.UTC)
	q.To = time.Date(2013, time.September, 20, 9, 1, 47, 0, time.UTC)

	expectedArgs := []interface{}{q.Key, q.From, q.To}

	s, args := buildSelectQuery(q)

	if s != expected {
		t.Fatalf("Expected %s, got %s", expected, s)
	}

	if len(args) != len(expectedArgs) {
		t.Fatalf("Expected %+v, got %+v", expectedArgs, args)
	}
}
func TestQueryBuilder(t *testing.T) {

	const expected = `select * from event where key in ($1, $2) and origin = $3 and entities @> ARRAY[$4, $5]::text[] order by created desc;`

	expectedArgs := []interface{}{"foo.bar", "bar.foo", "mysystem", "c/1", "c/2"}

	q := straumur.Query{}
	q.Origin = "mysystem"
	q.Entities = []string{"c/1", "c/2"}
	q.Key = "foo.bar OR bar.foo"

	s, args := buildSelectQuery(q)

	if s != expected {
		t.Fatalf("Expected %s, got %s", expected, s)
	}

	if len(args) != len(expectedArgs) {
		t.Fatalf("Expected %+v, got %+v", expectedArgs, args)
	}
}
func TestAggregateBuilder(t *testing.T) {

	const expected = `select i as name, count(*) as count from (select unnest(actors) as i from (select * from event where key in ($1, $2) and origin = $3 and entities @> ARRAY[$4, $5]::text[] order by created desc) x order by actors) t group by i order by i;`

	expectedArgs := []interface{}{"foo.bar", "bar.foo", "mysystem", "c/1", "c/2"}

	q := straumur.Query{}
	q.Origin = "mysystem"
	q.Entities = []string{"c/1", "c/2"}
	q.Key = "foo.bar OR bar.foo"

	s, args := buildAggregateQuery(q, "actors")

	if s != expected {
		t.Fatalf("Expected %s, got %s", expected, s)
	}

	if len(args) != len(expectedArgs) {
		t.Fatalf("Expected %+v, got %+v", expectedArgs, args)
	}

}
Example #4
0
func (p *PostgresDataSource) AggregateType(q straumur.Query, s string) (map[string]int, error) {

	if !q.IsValidArrayType(s) {
		return nil, errors.New("Invalid type")
	}

	query, args := buildAggregateQuery(q, s)
	m := make(map[string]int)

	err := p.wrapTransaction(func(tx *sql.Tx) error {
		rows, err := tx.Query(query, args...)
		defer rows.Close()
		for rows.Next() {
			var cStr string
			var cInt int
			rows.Scan(&cStr, &cInt)
			m[cStr] = cInt
		}
		return err
	})

	return m, err
}
Example #5
0
func TestWebSocketBroadcaster(t *testing.T) {

	url := fmt.Sprintf("ws://%s%s", serverAddr, "/ws")
	conn, err := websocket.Dial(url, "", "http://localhost/")
	if err != nil {
		t.Errorf("WebSocket handshake error: %v", err)
		return
	}

	q := straumur.Query{}
	q.Entities = []string{"ns/moo"}
	t.Logf("Query filter: %+v", q)
	websocket.JSON.Send(conn, q)

	time.Sleep(300 * time.Millisecond)

	e := straumur.NewEvent(
		"myapp.user.login",
		nil,
		nil,
		"User foobar logged in",
		3,
		"myapp",
		[]string{"ns/foo", "ns/moo"},
		nil,
		nil,
		nil)

	broadcaster.Broadcast(e)

	var event straumur.Event
	if err := websocket.JSON.Receive(conn, &event); err != nil {
		t.Errorf("Read: %v", err)
	}

	incoming := make(chan straumur.Event)
	go readEvents(conn, incoming)

	filtered := straumur.NewEvent(
		"Should filter",
		nil,
		nil,
		"This event should be filtered",
		3,
		"myapp",
		[]string{"ns/foo", "ns/boo"},
		nil,
		nil,
		nil)

	if q.Match(*filtered) == true {
		t.Errorf("Query %+v should not pass %+v", q, filtered)
	}

	broadcaster.Broadcast(filtered)

	broadcaster.Broadcast(straumur.NewEvent(
		"foo.bar",
		nil,
		nil,
		"This event should pass",
		3,
		"myapp",
		[]string{"ns/foo", "ns/moo"},
		nil,
		nil,
		nil))

	ev := <-incoming

	if ev.Key != "foo.bar" {
		t.Errorf("Unexpected %s", ev)
	}

}
Example #6
0
func buildSelectQuery(q straumur.Query) (string, []interface{}) {

	var buffer bytes.Buffer
	args := []interface{}{}
	paramCount := 1
	delimiter := " and "
	writeDelimiter := false

	buffer.WriteString("select * from event")

	//Early exit, query is empty
	if q.IsEmpty() {
		buffer.WriteString(" order by created desc;")
		return buffer.String(), args
	}

	buffer.WriteString(" where ")

	if q.Key != "" {
		buffer.WriteString("key in (")
		keys := strings.Split(q.Key, "OR")
		for arrIdx, s := range keys {
			args = append(args, strings.TrimSpace(s))
			buffer.WriteString(fmt.Sprintf("$%d", paramCount))
			paramCount++
			if arrIdx+1 < len(keys) {
				buffer.WriteString(", ")
			}
		}
		buffer.WriteString(")")
		writeDelimiter = true
	}

	if q.Origin != "" {
		if writeDelimiter {
			buffer.WriteString(delimiter)
		}
		buffer.WriteString(fmt.Sprintf("origin = $%d", paramCount))
		args = append(args, q.Origin)
		paramCount++
		writeDelimiter = true
	}

	if !q.From.IsZero() {
		if writeDelimiter {
			buffer.WriteString(delimiter)
		}
		buffer.WriteString(fmt.Sprintf("created >= $%d", paramCount))
		args = append(args, q.From)
		paramCount++
		writeDelimiter = true
	}

	if !q.To.IsZero() {
		if writeDelimiter {
			buffer.WriteString(delimiter)
		}
		buffer.WriteString(fmt.Sprintf("created < $%d", paramCount))
		args = append(args, q.To)
		paramCount++
		writeDelimiter = true
	}

	//Array fields
	array_fields := make(map[string][]string)
	array_fields["entities"] = q.Entities
	array_fields["actors"] = q.Actors

	for db_name, array_field := range array_fields {

		if len(array_field) > 0 {
			if writeDelimiter {
				buffer.WriteString(delimiter)
			}
			nextParam, s := writeArray(paramCount, &args, db_name, array_field)
			paramCount = nextParam
			buffer.WriteString(s)
			writeDelimiter = true
		}

	}

	//todo add sort to query
	buffer.WriteString(" order by created desc;")

	return buffer.String(), args
}