github.com/RevenueMonster/sqlike@v1.0.6/examples/json.go (about)

     1  package examples
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"encoding/json"
     7  	"sort"
     8  	"testing"
     9  
    10  	"github.com/RevenueMonster/sqlike/sql/expr"
    11  	"github.com/RevenueMonster/sqlike/sqlike"
    12  	"github.com/RevenueMonster/sqlike/sqlike/actions"
    13  	"github.com/RevenueMonster/sqlike/sqlike/indexes"
    14  	"github.com/RevenueMonster/sqlike/sqlike/options"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  // JSONExamples :
    19  func JSONExamples(ctx context.Context, t *testing.T, db *sqlike.Database) {
    20  	var (
    21  		err    error
    22  		result *sqlike.Result
    23  	)
    24  
    25  	table := db.Table("JSON")
    26  	err = table.DropIfExists(ctx)
    27  	require.NoError(t, err)
    28  
    29  	// migrate
    30  	{
    31  		table.MustMigrate(ctx, jsonStruct{})
    32  	}
    33  
    34  	// create index
    35  	{
    36  		err = table.Indexes().CreateOne(ctx, indexes.Index{
    37  			Name:    "words",
    38  			Type:    indexes.MultiValued,
    39  			Cast:    "StrArr",
    40  			As:      "CHAR(50) ARRAY",
    41  			Comment: "wording index",
    42  		})
    43  		require.NoError(t, err)
    44  	}
    45  
    46  	jss := [...]jsonStruct{
    47  		newJSONStruct(),
    48  		newJSONStruct(),
    49  		{
    50  			Text:   "Hello America 🎉 !!!",
    51  			StrArr: []string{"Hello", "America", "🎉"},
    52  			IntArr: []int{6743, 88},
    53  		},
    54  	}
    55  
    56  	{
    57  		_, err = table.Insert(
    58  			ctx,
    59  			&jss,
    60  			options.Insert().
    61  				SetDebug(true))
    62  		require.NoError(t, err)
    63  	}
    64  
    65  	// JSON_EXTRACT, JSON_QUOTE, JSON_UNQUOTE and JSON_KEYS
    66  	{
    67  		var (
    68  			id int64 = 1
    69  			o  struct {
    70  				Text         string
    71  				Message      string
    72  				QuoteMessage string
    73  				ObjKeys      []string
    74  			}
    75  		)
    76  
    77  		extr := expr.JSON_EXTRACT(expr.Column("Raw"), "$.message")
    78  		err = table.FindOne(
    79  			ctx,
    80  			actions.FindOne().
    81  				Select(
    82  					expr.As(expr.JSON_QUOTE(expr.Column("Text")), "Text"),
    83  					expr.JSON_UNQUOTE(extr),
    84  					extr,
    85  					expr.JSON_KEYS(expr.Column("Raw")),
    86  				).
    87  				Where(
    88  					expr.Equal("$Key", id),
    89  				),
    90  			options.FindOne().SetDebug(true),
    91  		).Scan(&o.Text, &o.Message, &o.QuoteMessage, &o.ObjKeys)
    92  		require.NoError(t, err)
    93  		require.Equal(t, `"TEXT"`, o.Text)
    94  		require.Equal(t, `ok`, o.Message)
    95  		require.Equal(t, `"ok"`, o.QuoteMessage)
    96  
    97  		sort.Strings(o.ObjKeys)
    98  		require.ElementsMatch(t, []string{
    99  			"amountInCents", "category", "message", "status", "type",
   100  		}, o.ObjKeys)
   101  
   102  		// col = JSON_SET(col, '$.counter', JSON_EXTRACT(col, '$.counter') + 1)
   103  		if affected, err := table.UpdateOne(
   104  			ctx,
   105  			actions.UpdateOne().
   106  				Where(
   107  					expr.Equal("$Key", id),
   108  				).
   109  				Set(
   110  					expr.ColumnValue("Raw",
   111  						expr.JSON_SET(
   112  							expr.Column("Raw"),
   113  							"$.amountInCents",
   114  							expr.Raw("JSON_EXTRACT(`Raw`, '$.amountInCents') + 7689"),
   115  						),
   116  					),
   117  				),
   118  			options.UpdateOne().SetDebug(true),
   119  		); err != nil {
   120  			require.NoError(t, err)
   121  		} else if affected < 1 {
   122  			require.Greater(t, int64(0), affected)
   123  		}
   124  
   125  		var raw json.RawMessage
   126  		if err := table.FindOne(
   127  			ctx,
   128  			actions.FindOne().
   129  				Select("Raw").
   130  				Where(
   131  					expr.Equal("$Key", id),
   132  				),
   133  		).Scan(&raw); err != nil {
   134  			require.NoError(t, err)
   135  		}
   136  
   137  		var output struct {
   138  			Amount float64 `json:"amountInCents"`
   139  		}
   140  
   141  		if err := json.Unmarshal(raw, &output); err != nil {
   142  			require.NoError(t, err)
   143  		}
   144  
   145  		require.Equal(t, float64(8689), output.Amount)
   146  	}
   147  
   148  	//
   149  	{
   150  		type rawData struct {
   151  			ID           int64  `json:"id"`
   152  			UnderscoreID int64  `json:"_id"`
   153  			Text         string `json:"text"`
   154  			Emoji        string `json:"emoji"`
   155  			Flag         bool   `json:"flag"`
   156  		}
   157  
   158  		var (
   159  			id     int64
   160  			output jsonStruct
   161  			js     = newJSONStruct()
   162  			res    sql.Result
   163  		)
   164  
   165  		js.Raw = json.RawMessage(`{
   166  			"_id": 100,
   167  			"text": "Hello world",
   168  			"emoji"  : "💩💩💩"
   169  		}`)
   170  		res, err = table.InsertOne(ctx, &js)
   171  		require.NoError(t, err)
   172  		id, err = res.LastInsertId()
   173  		require.NoError(t, err)
   174  
   175  		if err := table.FindOne(
   176  			ctx,
   177  			actions.FindOne().
   178  				Where(
   179  					expr.Equal("$Key", id),
   180  				),
   181  		).Decode(&output); err != nil {
   182  			require.NoError(t, err)
   183  		}
   184  
   185  		var raw rawData
   186  		err = json.Unmarshal(output.Raw, &raw)
   187  		require.NoError(t, err)
   188  		require.Equal(t, int64(0), raw.ID)
   189  		require.Equal(t, int64(100), raw.UnderscoreID)
   190  		require.Equal(t, "💩💩💩", raw.Emoji)
   191  
   192  		// rename key `_id` to `id` of json object
   193  		if affected, err := table.UpdateOne(
   194  			ctx,
   195  			actions.UpdateOne().
   196  				Where(
   197  					expr.Equal("$Key", id),
   198  				).
   199  				Set(
   200  					expr.ColumnValue("Raw",
   201  						expr.JSON_INSERT(
   202  							expr.JSON_REMOVE(expr.Column("Raw"), "$._id"),
   203  							"$.id",
   204  							expr.JSON_EXTRACT(expr.Column("Raw"), "$._id"),
   205  						),
   206  					),
   207  				),
   208  			options.UpdateOne().SetDebug(true),
   209  		); err != nil {
   210  			require.NoError(t, err)
   211  		} else if affected > 0 {
   212  			require.Greater(t, affected, int64(0))
   213  		}
   214  
   215  		// reset the data
   216  		output = jsonStruct{}
   217  		raw = rawData{}
   218  
   219  		if err := table.FindOne(
   220  			ctx,
   221  			actions.FindOne().
   222  				Where(
   223  					expr.Equal("$Key", id),
   224  				),
   225  		).Decode(&output); err != nil {
   226  			require.NoError(t, err)
   227  		}
   228  
   229  		err = json.Unmarshal(output.Raw, &raw)
   230  		require.NoError(t, err)
   231  		require.Equal(t, int64(100), raw.ID)
   232  		require.Equal(t, int64(0), raw.UnderscoreID)
   233  		require.Equal(t, "💩💩💩", raw.Emoji)
   234  	}
   235  
   236  	// advance query
   237  	{
   238  		type output struct {
   239  			Raw     string
   240  			Message string
   241  		}
   242  
   243  		result, err = table.Find(
   244  			ctx,
   245  			actions.Find().
   246  				Select(
   247  					expr.As(
   248  						expr.Func("REPLACE", expr.Column("Raw"), "message", "msg"),
   249  						"Raw",
   250  					),
   251  					expr.As(
   252  						expr.JSON_UNQUOTE(expr.JSONColumn("Raw", "message")),
   253  						"Message",
   254  					),
   255  				).
   256  				Where(
   257  					expr.JSON_CONTAINS(
   258  						expr.Column("StrArr"),
   259  						expr.JSON_QUOTE("a"),
   260  					),
   261  					expr.Equal(
   262  						expr.JSONColumn("Raw", "message"),
   263  						"ok",
   264  					),
   265  				).
   266  				OrderBy(
   267  					expr.Desc("$Key"),
   268  				),
   269  			options.Find().
   270  				SetDebug(true).
   271  				SetNoLimit(true),
   272  		)
   273  		require.NoError(t, err)
   274  
   275  		arr := []output{}
   276  		err = result.All(&arr)
   277  		require.NoError(t, err)
   278  		require.True(t, len(arr) > 0)
   279  		require.True(t, len(arr[0].Raw) > 3)
   280  		require.Equal(t, "ok", arr[0].Message)
   281  
   282  		var out []jsonStruct
   283  
   284  		result, err = table.Find(
   285  			ctx,
   286  			actions.Find().
   287  				Where(
   288  					expr.MemberOf("🎉", "StrArr"),
   289  				),
   290  			options.Find().
   291  				SetDebug(true).
   292  				SetNoLimit(true),
   293  		)
   294  		require.NoError(t, err)
   295  
   296  		err = result.All(&out)
   297  		require.NoError(t, err)
   298  
   299  		require.Equal(t, jsonStruct{
   300  			ID:     3,
   301  			Text:   "Hello America 🎉 !!!",
   302  			StrArr: []string{"Hello", "America", "🎉"},
   303  			IntArr: []int{6743, 88},
   304  			Raw:    json.RawMessage(`null`),
   305  		}, out[0])
   306  	}
   307  }
   308  
   309  func newJSONStruct() (js jsonStruct) {
   310  	js.Text = "TEXT"
   311  	js.Raw = []byte(`{"message":"ok","type":"TNG","category":"EWALLET","status":"SUCCESS","amountInCents":1000}`)
   312  	js.StrArr = []string{"a", "b", "c", "d", "e", "f"}
   313  	js.IntArr = []int{100, 16, -2, 88, 32, -47, 25}
   314  	js.Struct.StringSlice = sort.StringSlice{"a", "b", "c"}
   315  	js.Struct.IntSlice = sort.IntSlice{0, 1, 224, 999}
   316  	return
   317  }