mirror of https://github.com/jackc/pgx.git
Use Go casing convention for JSON(B)
parent
3bdc94cee2
commit
6688466123
|
@ -6,44 +6,44 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
type Json struct {
|
||||
type JSON struct {
|
||||
Bytes []byte
|
||||
Status Status
|
||||
}
|
||||
|
||||
func (dst *Json) Set(src interface{}) error {
|
||||
func (dst *JSON) Set(src interface{}) error {
|
||||
if src == nil {
|
||||
*dst = Json{Status: Null}
|
||||
*dst = JSON{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch value := src.(type) {
|
||||
case string:
|
||||
*dst = Json{Bytes: []byte(value), Status: Present}
|
||||
*dst = JSON{Bytes: []byte(value), Status: Present}
|
||||
case *string:
|
||||
if value == nil {
|
||||
*dst = Json{Status: Null}
|
||||
*dst = JSON{Status: Null}
|
||||
} else {
|
||||
*dst = Json{Bytes: []byte(*value), Status: Present}
|
||||
*dst = JSON{Bytes: []byte(*value), Status: Present}
|
||||
}
|
||||
case []byte:
|
||||
if value == nil {
|
||||
*dst = Json{Status: Null}
|
||||
*dst = JSON{Status: Null}
|
||||
} else {
|
||||
*dst = Json{Bytes: value, Status: Present}
|
||||
*dst = JSON{Bytes: value, Status: Present}
|
||||
}
|
||||
default:
|
||||
buf, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*dst = Json{Bytes: buf, Status: Present}
|
||||
*dst = JSON{Bytes: buf, Status: Present}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *Json) Get() interface{} {
|
||||
func (dst *JSON) Get() interface{} {
|
||||
switch dst.Status {
|
||||
case Present:
|
||||
var i interface{}
|
||||
|
@ -59,7 +59,7 @@ func (dst *Json) Get() interface{} {
|
|||
}
|
||||
}
|
||||
|
||||
func (src *Json) AssignTo(dst interface{}) error {
|
||||
func (src *JSON) AssignTo(dst interface{}) error {
|
||||
switch v := dst.(type) {
|
||||
case *string:
|
||||
if src.Status != Present {
|
||||
|
@ -90,21 +90,21 @@ func (src *Json) AssignTo(dst interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (dst *Json) DecodeText(ci *ConnInfo, src []byte) error {
|
||||
func (dst *JSON) DecodeText(ci *ConnInfo, src []byte) error {
|
||||
if src == nil {
|
||||
*dst = Json{Status: Null}
|
||||
*dst = JSON{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
*dst = Json{Bytes: src, Status: Present}
|
||||
*dst = JSON{Bytes: src, Status: Present}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dst *Json) DecodeBinary(ci *ConnInfo, src []byte) error {
|
||||
func (dst *JSON) DecodeBinary(ci *ConnInfo, src []byte) error {
|
||||
return dst.DecodeText(ci, src)
|
||||
}
|
||||
|
||||
func (src *Json) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
func (src *JSON) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
switch src.Status {
|
||||
case Null:
|
||||
return nil, nil
|
||||
|
@ -115,14 +115,14 @@ func (src *Json) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
|
|||
return append(buf, src.Bytes...), nil
|
||||
}
|
||||
|
||||
func (src *Json) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
func (src *JSON) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
return src.EncodeText(ci, buf)
|
||||
}
|
||||
|
||||
// Scan implements the database/sql Scanner interface.
|
||||
func (dst *Json) Scan(src interface{}) error {
|
||||
func (dst *JSON) Scan(src interface{}) error {
|
||||
if src == nil {
|
||||
*dst = Json{Status: Null}
|
||||
*dst = JSON{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ func (dst *Json) Scan(src interface{}) error {
|
|||
}
|
||||
|
||||
// Value implements the database/sql/driver Valuer interface.
|
||||
func (src *Json) Value() (driver.Value, error) {
|
||||
func (src *JSON) Value() (driver.Value, error) {
|
||||
switch src.Status {
|
||||
case Present:
|
||||
return string(src.Bytes), nil
|
||||
|
|
|
@ -9,31 +9,31 @@ import (
|
|||
"github.com/jackc/pgx/pgtype/testutil"
|
||||
)
|
||||
|
||||
func TestJsonTranscode(t *testing.T) {
|
||||
func TestJSONTranscode(t *testing.T) {
|
||||
testutil.TestSuccessfulTranscode(t, "json", []interface{}{
|
||||
&pgtype.Json{Bytes: []byte("{}"), Status: pgtype.Present},
|
||||
&pgtype.Json{Bytes: []byte("null"), Status: pgtype.Present},
|
||||
&pgtype.Json{Bytes: []byte("42"), Status: pgtype.Present},
|
||||
&pgtype.Json{Bytes: []byte(`"hello"`), Status: pgtype.Present},
|
||||
&pgtype.Json{Status: pgtype.Null},
|
||||
&pgtype.JSON{Bytes: []byte("{}"), Status: pgtype.Present},
|
||||
&pgtype.JSON{Bytes: []byte("null"), Status: pgtype.Present},
|
||||
&pgtype.JSON{Bytes: []byte("42"), Status: pgtype.Present},
|
||||
&pgtype.JSON{Bytes: []byte(`"hello"`), Status: pgtype.Present},
|
||||
&pgtype.JSON{Status: pgtype.Null},
|
||||
})
|
||||
}
|
||||
|
||||
func TestJsonSet(t *testing.T) {
|
||||
func TestJSONSet(t *testing.T) {
|
||||
successfulTests := []struct {
|
||||
source interface{}
|
||||
result pgtype.Json
|
||||
result pgtype.JSON
|
||||
}{
|
||||
{source: "{}", result: pgtype.Json{Bytes: []byte("{}"), Status: pgtype.Present}},
|
||||
{source: []byte("{}"), result: pgtype.Json{Bytes: []byte("{}"), Status: pgtype.Present}},
|
||||
{source: ([]byte)(nil), result: pgtype.Json{Status: pgtype.Null}},
|
||||
{source: (*string)(nil), result: pgtype.Json{Status: pgtype.Null}},
|
||||
{source: []int{1, 2, 3}, result: pgtype.Json{Bytes: []byte("[1,2,3]"), Status: pgtype.Present}},
|
||||
{source: map[string]interface{}{"foo": "bar"}, result: pgtype.Json{Bytes: []byte(`{"foo":"bar"}`), Status: pgtype.Present}},
|
||||
{source: "{}", result: pgtype.JSON{Bytes: []byte("{}"), Status: pgtype.Present}},
|
||||
{source: []byte("{}"), result: pgtype.JSON{Bytes: []byte("{}"), Status: pgtype.Present}},
|
||||
{source: ([]byte)(nil), result: pgtype.JSON{Status: pgtype.Null}},
|
||||
{source: (*string)(nil), result: pgtype.JSON{Status: pgtype.Null}},
|
||||
{source: []int{1, 2, 3}, result: pgtype.JSON{Bytes: []byte("[1,2,3]"), Status: pgtype.Present}},
|
||||
{source: map[string]interface{}{"foo": "bar"}, result: pgtype.JSON{Bytes: []byte(`{"foo":"bar"}`), Status: pgtype.Present}},
|
||||
}
|
||||
|
||||
for i, tt := range successfulTests {
|
||||
var d pgtype.Json
|
||||
var d pgtype.JSON
|
||||
err := d.Set(tt.source)
|
||||
if err != nil {
|
||||
t.Errorf("%d: %v", i, err)
|
||||
|
@ -45,17 +45,17 @@ func TestJsonSet(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestJsonAssignTo(t *testing.T) {
|
||||
func TestJSONAssignTo(t *testing.T) {
|
||||
var s string
|
||||
var ps *string
|
||||
var b []byte
|
||||
|
||||
rawStringTests := []struct {
|
||||
src pgtype.Json
|
||||
src pgtype.JSON
|
||||
dst *string
|
||||
expected string
|
||||
}{
|
||||
{src: pgtype.Json{Bytes: []byte("{}"), Status: pgtype.Present}, dst: &s, expected: "{}"},
|
||||
{src: pgtype.JSON{Bytes: []byte("{}"), Status: pgtype.Present}, dst: &s, expected: "{}"},
|
||||
}
|
||||
|
||||
for i, tt := range rawStringTests {
|
||||
|
@ -70,12 +70,12 @@ func TestJsonAssignTo(t *testing.T) {
|
|||
}
|
||||
|
||||
rawBytesTests := []struct {
|
||||
src pgtype.Json
|
||||
src pgtype.JSON
|
||||
dst *[]byte
|
||||
expected []byte
|
||||
}{
|
||||
{src: pgtype.Json{Bytes: []byte("{}"), Status: pgtype.Present}, dst: &b, expected: []byte("{}")},
|
||||
{src: pgtype.Json{Status: pgtype.Null}, dst: &b, expected: (([]byte)(nil))},
|
||||
{src: pgtype.JSON{Bytes: []byte("{}"), Status: pgtype.Present}, dst: &b, expected: []byte("{}")},
|
||||
{src: pgtype.JSON{Status: pgtype.Null}, dst: &b, expected: (([]byte)(nil))},
|
||||
}
|
||||
|
||||
for i, tt := range rawBytesTests {
|
||||
|
@ -97,12 +97,12 @@ func TestJsonAssignTo(t *testing.T) {
|
|||
var strDst structDst
|
||||
|
||||
unmarshalTests := []struct {
|
||||
src pgtype.Json
|
||||
src pgtype.JSON
|
||||
dst interface{}
|
||||
expected interface{}
|
||||
}{
|
||||
{src: pgtype.Json{Bytes: []byte(`{"foo":"bar"}`), Status: pgtype.Present}, dst: &mapDst, expected: map[string]interface{}{"foo": "bar"}},
|
||||
{src: pgtype.Json{Bytes: []byte(`{"name":"John","age":42}`), Status: pgtype.Present}, dst: &strDst, expected: structDst{Name: "John", Age: 42}},
|
||||
{src: pgtype.JSON{Bytes: []byte(`{"foo":"bar"}`), Status: pgtype.Present}, dst: &mapDst, expected: map[string]interface{}{"foo": "bar"}},
|
||||
{src: pgtype.JSON{Bytes: []byte(`{"name":"John","age":42}`), Status: pgtype.Present}, dst: &strDst, expected: structDst{Name: "John", Age: 42}},
|
||||
}
|
||||
for i, tt := range unmarshalTests {
|
||||
err := tt.src.AssignTo(tt.dst)
|
||||
|
@ -116,11 +116,11 @@ func TestJsonAssignTo(t *testing.T) {
|
|||
}
|
||||
|
||||
pointerAllocTests := []struct {
|
||||
src pgtype.Json
|
||||
src pgtype.JSON
|
||||
dst **string
|
||||
expected *string
|
||||
}{
|
||||
{src: pgtype.Json{Status: pgtype.Null}, dst: &ps, expected: ((*string)(nil))},
|
||||
{src: pgtype.JSON{Status: pgtype.Null}, dst: &ps, expected: ((*string)(nil))},
|
||||
}
|
||||
|
||||
for i, tt := range pointerAllocTests {
|
||||
|
|
|
@ -5,27 +5,27 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
type Jsonb Json
|
||||
type JSONB JSON
|
||||
|
||||
func (dst *Jsonb) Set(src interface{}) error {
|
||||
return (*Json)(dst).Set(src)
|
||||
func (dst *JSONB) Set(src interface{}) error {
|
||||
return (*JSON)(dst).Set(src)
|
||||
}
|
||||
|
||||
func (dst *Jsonb) Get() interface{} {
|
||||
return (*Json)(dst).Get()
|
||||
func (dst *JSONB) Get() interface{} {
|
||||
return (*JSON)(dst).Get()
|
||||
}
|
||||
|
||||
func (src *Jsonb) AssignTo(dst interface{}) error {
|
||||
return (*Json)(src).AssignTo(dst)
|
||||
func (src *JSONB) AssignTo(dst interface{}) error {
|
||||
return (*JSON)(src).AssignTo(dst)
|
||||
}
|
||||
|
||||
func (dst *Jsonb) DecodeText(ci *ConnInfo, src []byte) error {
|
||||
return (*Json)(dst).DecodeText(ci, src)
|
||||
func (dst *JSONB) DecodeText(ci *ConnInfo, src []byte) error {
|
||||
return (*JSON)(dst).DecodeText(ci, src)
|
||||
}
|
||||
|
||||
func (dst *Jsonb) DecodeBinary(ci *ConnInfo, src []byte) error {
|
||||
func (dst *JSONB) DecodeBinary(ci *ConnInfo, src []byte) error {
|
||||
if src == nil {
|
||||
*dst = Jsonb{Status: Null}
|
||||
*dst = JSONB{Status: Null}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -37,16 +37,16 @@ func (dst *Jsonb) DecodeBinary(ci *ConnInfo, src []byte) error {
|
|||
return fmt.Errorf("unknown jsonb version number %d", src[0])
|
||||
}
|
||||
|
||||
*dst = Jsonb{Bytes: src[1:], Status: Present}
|
||||
*dst = JSONB{Bytes: src[1:], Status: Present}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (src *Jsonb) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
return (*Json)(src).EncodeText(ci, buf)
|
||||
func (src *JSONB) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
return (*JSON)(src).EncodeText(ci, buf)
|
||||
}
|
||||
|
||||
func (src *Jsonb) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
func (src *JSONB) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
|
||||
switch src.Status {
|
||||
case Null:
|
||||
return nil, nil
|
||||
|
@ -59,11 +59,11 @@ func (src *Jsonb) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
// Scan implements the database/sql Scanner interface.
|
||||
func (dst *Jsonb) Scan(src interface{}) error {
|
||||
return (*Json)(dst).Scan(src)
|
||||
func (dst *JSONB) Scan(src interface{}) error {
|
||||
return (*JSON)(dst).Scan(src)
|
||||
}
|
||||
|
||||
// Value implements the database/sql/driver Valuer interface.
|
||||
func (src *Jsonb) Value() (driver.Value, error) {
|
||||
return (*Json)(src).Value()
|
||||
func (src *JSONB) Value() (driver.Value, error) {
|
||||
return (*JSON)(src).Value()
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/jackc/pgx/pgtype/testutil"
|
||||
)
|
||||
|
||||
func TestJsonbTranscode(t *testing.T) {
|
||||
func TestJSONBTranscode(t *testing.T) {
|
||||
conn := testutil.MustConnectPgx(t)
|
||||
defer testutil.MustClose(t, conn)
|
||||
if _, ok := conn.ConnInfo.DataTypeForName("jsonb"); !ok {
|
||||
|
@ -17,29 +17,29 @@ func TestJsonbTranscode(t *testing.T) {
|
|||
}
|
||||
|
||||
testutil.TestSuccessfulTranscode(t, "jsonb", []interface{}{
|
||||
&pgtype.Jsonb{Bytes: []byte("{}"), Status: pgtype.Present},
|
||||
&pgtype.Jsonb{Bytes: []byte("null"), Status: pgtype.Present},
|
||||
&pgtype.Jsonb{Bytes: []byte("42"), Status: pgtype.Present},
|
||||
&pgtype.Jsonb{Bytes: []byte(`"hello"`), Status: pgtype.Present},
|
||||
&pgtype.Jsonb{Status: pgtype.Null},
|
||||
&pgtype.JSONB{Bytes: []byte("{}"), Status: pgtype.Present},
|
||||
&pgtype.JSONB{Bytes: []byte("null"), Status: pgtype.Present},
|
||||
&pgtype.JSONB{Bytes: []byte("42"), Status: pgtype.Present},
|
||||
&pgtype.JSONB{Bytes: []byte(`"hello"`), Status: pgtype.Present},
|
||||
&pgtype.JSONB{Status: pgtype.Null},
|
||||
})
|
||||
}
|
||||
|
||||
func TestJsonbSet(t *testing.T) {
|
||||
func TestJSONBSet(t *testing.T) {
|
||||
successfulTests := []struct {
|
||||
source interface{}
|
||||
result pgtype.Jsonb
|
||||
result pgtype.JSONB
|
||||
}{
|
||||
{source: "{}", result: pgtype.Jsonb{Bytes: []byte("{}"), Status: pgtype.Present}},
|
||||
{source: []byte("{}"), result: pgtype.Jsonb{Bytes: []byte("{}"), Status: pgtype.Present}},
|
||||
{source: ([]byte)(nil), result: pgtype.Jsonb{Status: pgtype.Null}},
|
||||
{source: (*string)(nil), result: pgtype.Jsonb{Status: pgtype.Null}},
|
||||
{source: []int{1, 2, 3}, result: pgtype.Jsonb{Bytes: []byte("[1,2,3]"), Status: pgtype.Present}},
|
||||
{source: map[string]interface{}{"foo": "bar"}, result: pgtype.Jsonb{Bytes: []byte(`{"foo":"bar"}`), Status: pgtype.Present}},
|
||||
{source: "{}", result: pgtype.JSONB{Bytes: []byte("{}"), Status: pgtype.Present}},
|
||||
{source: []byte("{}"), result: pgtype.JSONB{Bytes: []byte("{}"), Status: pgtype.Present}},
|
||||
{source: ([]byte)(nil), result: pgtype.JSONB{Status: pgtype.Null}},
|
||||
{source: (*string)(nil), result: pgtype.JSONB{Status: pgtype.Null}},
|
||||
{source: []int{1, 2, 3}, result: pgtype.JSONB{Bytes: []byte("[1,2,3]"), Status: pgtype.Present}},
|
||||
{source: map[string]interface{}{"foo": "bar"}, result: pgtype.JSONB{Bytes: []byte(`{"foo":"bar"}`), Status: pgtype.Present}},
|
||||
}
|
||||
|
||||
for i, tt := range successfulTests {
|
||||
var d pgtype.Jsonb
|
||||
var d pgtype.JSONB
|
||||
err := d.Set(tt.source)
|
||||
if err != nil {
|
||||
t.Errorf("%d: %v", i, err)
|
||||
|
@ -51,17 +51,17 @@ func TestJsonbSet(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestJsonbAssignTo(t *testing.T) {
|
||||
func TestJSONBAssignTo(t *testing.T) {
|
||||
var s string
|
||||
var ps *string
|
||||
var b []byte
|
||||
|
||||
rawStringTests := []struct {
|
||||
src pgtype.Jsonb
|
||||
src pgtype.JSONB
|
||||
dst *string
|
||||
expected string
|
||||
}{
|
||||
{src: pgtype.Jsonb{Bytes: []byte("{}"), Status: pgtype.Present}, dst: &s, expected: "{}"},
|
||||
{src: pgtype.JSONB{Bytes: []byte("{}"), Status: pgtype.Present}, dst: &s, expected: "{}"},
|
||||
}
|
||||
|
||||
for i, tt := range rawStringTests {
|
||||
|
@ -76,12 +76,12 @@ func TestJsonbAssignTo(t *testing.T) {
|
|||
}
|
||||
|
||||
rawBytesTests := []struct {
|
||||
src pgtype.Jsonb
|
||||
src pgtype.JSONB
|
||||
dst *[]byte
|
||||
expected []byte
|
||||
}{
|
||||
{src: pgtype.Jsonb{Bytes: []byte("{}"), Status: pgtype.Present}, dst: &b, expected: []byte("{}")},
|
||||
{src: pgtype.Jsonb{Status: pgtype.Null}, dst: &b, expected: (([]byte)(nil))},
|
||||
{src: pgtype.JSONB{Bytes: []byte("{}"), Status: pgtype.Present}, dst: &b, expected: []byte("{}")},
|
||||
{src: pgtype.JSONB{Status: pgtype.Null}, dst: &b, expected: (([]byte)(nil))},
|
||||
}
|
||||
|
||||
for i, tt := range rawBytesTests {
|
||||
|
@ -103,12 +103,12 @@ func TestJsonbAssignTo(t *testing.T) {
|
|||
var strDst structDst
|
||||
|
||||
unmarshalTests := []struct {
|
||||
src pgtype.Jsonb
|
||||
src pgtype.JSONB
|
||||
dst interface{}
|
||||
expected interface{}
|
||||
}{
|
||||
{src: pgtype.Jsonb{Bytes: []byte(`{"foo":"bar"}`), Status: pgtype.Present}, dst: &mapDst, expected: map[string]interface{}{"foo": "bar"}},
|
||||
{src: pgtype.Jsonb{Bytes: []byte(`{"name":"John","age":42}`), Status: pgtype.Present}, dst: &strDst, expected: structDst{Name: "John", Age: 42}},
|
||||
{src: pgtype.JSONB{Bytes: []byte(`{"foo":"bar"}`), Status: pgtype.Present}, dst: &mapDst, expected: map[string]interface{}{"foo": "bar"}},
|
||||
{src: pgtype.JSONB{Bytes: []byte(`{"name":"John","age":42}`), Status: pgtype.Present}, dst: &strDst, expected: structDst{Name: "John", Age: 42}},
|
||||
}
|
||||
for i, tt := range unmarshalTests {
|
||||
err := tt.src.AssignTo(tt.dst)
|
||||
|
@ -122,11 +122,11 @@ func TestJsonbAssignTo(t *testing.T) {
|
|||
}
|
||||
|
||||
pointerAllocTests := []struct {
|
||||
src pgtype.Jsonb
|
||||
src pgtype.JSONB
|
||||
dst **string
|
||||
expected *string
|
||||
}{
|
||||
{src: pgtype.Jsonb{Status: pgtype.Null}, dst: &ps, expected: ((*string)(nil))},
|
||||
{src: pgtype.JSONB{Status: pgtype.Null}, dst: &ps, expected: ((*string)(nil))},
|
||||
}
|
||||
|
||||
for i, tt := range pointerAllocTests {
|
||||
|
|
|
@ -19,7 +19,7 @@ const (
|
|||
TidOID = 27
|
||||
XidOID = 28
|
||||
CidOID = 29
|
||||
JsonOID = 114
|
||||
JSONOID = 114
|
||||
CidrOID = 650
|
||||
CidrArrayOID = 651
|
||||
Float4OID = 700
|
||||
|
@ -47,7 +47,7 @@ const (
|
|||
TimestamptzArrayOID = 1185
|
||||
RecordOID = 2249
|
||||
UUIDOID = 2950
|
||||
JsonbOID = 3802
|
||||
JSONBOID = 3802
|
||||
)
|
||||
|
||||
type Status byte
|
||||
|
@ -242,8 +242,8 @@ func init() {
|
|||
"int4range": &Int4range{},
|
||||
"int8": &Int8{},
|
||||
"int8range": &Int8range{},
|
||||
"json": &Json{},
|
||||
"jsonb": &Jsonb{},
|
||||
"json": &JSON{},
|
||||
"jsonb": &JSONB{},
|
||||
"line": &Line{},
|
||||
"lseg": &Lseg{},
|
||||
"macaddr": &Macaddr{},
|
||||
|
|
Loading…
Reference in New Issue