***Optimzation**: Never issue refresh event when Grafana tab is not visible [#7218](https://github.com/grafana/grafana/issues/7218), thx [@mtanda](https://github.com/mtanda)
***Browser History**: Browser back/forward now works time ranges / zoom, [#7259](https://github.com/grafana/grafana/issues/7259)
## Bugfixes
***Alerting**: Fixes missing support for no_data and execution error when testing alerts [#7149](https://github.com/grafana/grafana/issues/7149)
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
null is a library with reasonable options for dealing with nullable SQL and JSON values
There are two packages: `null` and its subpackage `zero`.
Types in `null` will only be considered null on null input, and will JSON encode to `null`. If you need zero and null be considered separate values, use these.
Types in `zero` are treated like zero values in Go: blank string input will produce a null `zero.String`, and null Strings will JSON encode to `""`. Zero values of these types will be considered null to SQL. If you need zero and null treated the same, use these.
All types implement `sql.Scanner` and `driver.Valuer`, so you can use this library in place of `sql.NullXXX`. All types also implement: `encoding.TextMarshaler`, `encoding.TextUnmarshaler`, `json.Marshaler`, and `json.Unmarshaler`.
### null package
`import "gopkg.in/guregu/null.v3"`
#### null.String
Nullable string.
Marshals to JSON null if SQL source data is null. Zero (blank) input will not produce a null String. Can unmarshal from `sql.NullString` JSON input or string input.
#### null.Int
Nullable int64.
Marshals to JSON null if SQL source data is null. Zero input will not produce a null Int. Can unmarshal from `sql.NullInt64` JSON input.
#### null.Float
Nullable float64.
Marshals to JSON null if SQL source data is null. Zero input will not produce a null Float. Can unmarshal from `sql.NullFloat64` JSON input.
#### null.Bool
Nullable bool.
Marshals to JSON null if SQL source data is null. False input will not produce a null Bool. Can unmarshal from `sql.NullBool` JSON input.
#### null.Time
Marshals to JSON null if SQL source data is null. Uses `time.Time`'s marshaler. Can unmarshal from `pq.NullTime` and similar JSON input.
### zero package
`import "gopkg.in/guregu/null.v3/zero"`
#### zero.String
Nullable string.
Will marshal to a blank string if null. Blank string input produces a null String. Null values and zero values are considered equivalent. Can unmarshal from `sql.NullString` JSON input.
#### zero.Int
Nullable int64.
Will marshal to 0 if null. 0 produces a null Int. Null values and zero values are considered equivalent. Can unmarshal from `sql.NullInt64` JSON input.
#### zero.Float
Nullable float64.
Will marshal to 0 if null. 0.0 produces a null Float. Null values and zero values are considered equivalent. Can unmarshal from `sql.NullFloat64` JSON input.
#### zero.Bool
Nullable bool.
Will marshal to false if null. `false` produces a null Float. Null values and zero values are considered equivalent. Can unmarshal from `sql.NullBool` JSON input.
#### zero.Time
Will marshal to the zero time if null. Uses `time.Time`'s marshaler. Can unmarshal from `pq.NullTime` and similar JSON input.
### Bugs
`json`'s `",omitempty"` struct tag does not work correctly right now. It will never omit a null or empty String. This might be [fixed eventually](https://github.com/golang/go/issues/4357).
// Time is a nullable time.Time. It supports SQL and JSON serialization.
// It will marshal to null if null.
typeTimestruct{
Timetime.Time
Validbool
}
// Scan implements the Scanner interface.
func(t*Time)Scan(valueinterface{})error{
varerrerror
switchx:=value.(type){
casetime.Time:
t.Time=x
casenil:
t.Valid=false
returnnil
default:
err=fmt.Errorf("null: cannot scan type %T into null.Time: %v",value,value)
}
t.Valid=err==nil
returnerr
}
// Value implements the driver Valuer interface.
func(tTime)Value()(driver.Value,error){
if!t.Valid{
returnnil,nil
}
returnt.Time,nil
}
// NewTime creates a new Time.
funcNewTime(ttime.Time,validbool)Time{
returnTime{
Time:t,
Valid:valid,
}
}
// TimeFrom creates a new Time that will always be valid.
funcTimeFrom(ttime.Time)Time{
returnNewTime(t,true)
}
// TimeFromPtr creates a new Time that will be null if t is nil.
funcTimeFromPtr(t*time.Time)Time{
ift==nil{
returnNewTime(time.Time{},false)
}
returnNewTime(*t,true)
}
// MarshalJSON implements json.Marshaler.
// It will encode null if this time is null.
func(tTime)MarshalJSON()([]byte,error){
if!t.Valid{
return[]byte("null"),nil
}
returnt.Time.MarshalJSON()
}
// UnmarshalJSON implements json.Unmarshaler.
// It supports string, object (e.g. pq.NullTime and friends)
// and null input.
func(t*Time)UnmarshalJSON(data[]byte)error{
varerrerror
varvinterface{}
iferr=json.Unmarshal(data,&v);err!=nil{
returnerr
}
switchx:=v.(type){
casestring:
err=t.Time.UnmarshalJSON(data)
casemap[string]interface{}:
ti,tiOK:=x["Time"].(string)
valid,validOK:=x["Valid"].(bool)
if!tiOK||!validOK{
returnfmt.Errorf(`json: unmarshalling object into Go value of type null.Time requires key "Time" to be of type string and key "Valid" to be of type bool; found %T and %T, respectively`,x["Time"],x["Valid"])
}
err=t.Time.UnmarshalText([]byte(ti))
t.Valid=valid
returnerr
casenil:
t.Valid=false
returnnil
default:
err=fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Time",reflect.TypeOf(v).Name())
}
t.Valid=err==nil
returnerr
}
func(tTime)MarshalText()([]byte,error){
if!t.Valid{
return[]byte("null"),nil
}
returnt.Time.MarshalText()
}
func(t*Time)UnmarshalText(text[]byte)error{
str:=string(text)
ifstr==""||str=="null"{
t.Valid=false
returnnil
}
iferr:=t.Time.UnmarshalText(text);err!=nil{
returnerr
}
t.Valid=true
returnnil
}
// SetValid changes this Time's value and sets it to be non-null.
func(t*Time)SetValid(vtime.Time){
t.Time=v
t.Valid=true
}
// Ptr returns a pointer to this Time's value, or a nil pointer if this Time is null.