Refactor Jsonb operators
authorPeter Geoghegan <pg@heroku.com>
Tue, 18 Mar 2014 03:09:54 +0000 (20:09 -0700)
committerPeter Geoghegan <pg@heroku.com>
Tue, 18 Mar 2014 03:09:54 +0000 (20:09 -0700)
In keeping with the style of the operator implementations of many other
types, we do very little or nothing, other than calling worker functions
now.  In particular, no DirectFunctionCall*() call remains.

Formalize notion that @> and <@ are commutative, even though the latter
isn't part of any operator class.

src/backend/utils/adt/jsonb_op.c
src/include/catalog/pg_operator.h

index 99d2690e520b8ee155cd74123d944c90551ec31b..88bebb26588c415e89d5c442295bbcd0db6cee5e 100644 (file)
@@ -126,20 +126,34 @@ jsonb_contains(PG_FUNCTION_ARGS)
 Datum
 jsonb_contained(PG_FUNCTION_ARGS)
 {
-   /* Just invert "contains" */
-   PG_RETURN_DATUM(DirectFunctionCall2(jsonb_contains,
-                                       PG_GETARG_DATUM(1),
-                                       PG_GETARG_DATUM(0)));
+   /* Commutator of "contains" */
+   Jsonb      *tmpl = PG_GETARG_JSONB(0);
+   Jsonb      *val = PG_GETARG_JSONB(1);
+
+   JsonbIterator *it1, *it2;
+
+   if (JB_ROOT_COUNT(val) < JB_ROOT_COUNT(tmpl) ||
+       JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
+       PG_RETURN_BOOL(false);
+
+   it1 = JsonbIteratorInit(VARDATA(val));
+   it2 = JsonbIteratorInit(VARDATA(tmpl));
+
+   PG_RETURN_BOOL(deepContains(&it1, &it2));
 }
 
 Datum
 jsonb_ne(PG_FUNCTION_ARGS)
 {
-   int         res = DatumGetInt32(DirectFunctionCall2(jsonb_cmp,
-                                                       PG_GETARG_DATUM(0),
-                                                       PG_GETARG_DATUM(1)));
+   Jsonb      *jb1 = PG_GETARG_JSONB(0);
+   Jsonb      *jb2 = PG_GETARG_JSONB(1);
+   bool        res;
 
-   PG_RETURN_BOOL(res != 0);
+   res = (compareJsonbSuperHeaderValue(VARDATA(jb1), VARDATA(jb2)) != 0);
+
+   PG_FREE_IF_COPY(jb1, 0);
+   PG_FREE_IF_COPY(jb2, 1);
+   PG_RETURN_INT32(res);
 }
 
 /*
@@ -148,51 +162,72 @@ jsonb_ne(PG_FUNCTION_ARGS)
 Datum
 jsonb_lt(PG_FUNCTION_ARGS)
 {
-   int         res = DatumGetInt32(DirectFunctionCall2(jsonb_cmp,
-                                                       PG_GETARG_DATUM(0),
-                                                       PG_GETARG_DATUM(1)));
+   Jsonb      *jb1 = PG_GETARG_JSONB(0);
+   Jsonb      *jb2 = PG_GETARG_JSONB(1);
+   bool        res;
+
+   res = (compareJsonbSuperHeaderValue(VARDATA(jb1), VARDATA(jb2)) < 0);
 
-   PG_RETURN_BOOL(res < 0);
+   PG_FREE_IF_COPY(jb1, 0);
+   PG_FREE_IF_COPY(jb2, 1);
+   PG_RETURN_INT32(res);
 }
 
 Datum
 jsonb_gt(PG_FUNCTION_ARGS)
 {
-   int         res = DatumGetInt32(DirectFunctionCall2(jsonb_cmp,
-                                                       PG_GETARG_DATUM(0),
-                                                       PG_GETARG_DATUM(1)));
+   Jsonb      *jb1 = PG_GETARG_JSONB(0);
+   Jsonb      *jb2 = PG_GETARG_JSONB(1);
+   bool        res;
+
+   res = (compareJsonbSuperHeaderValue(VARDATA(jb1), VARDATA(jb2)) > 0);
 
-   PG_RETURN_BOOL(res > 0);
+   PG_FREE_IF_COPY(jb1, 0);
+   PG_FREE_IF_COPY(jb2, 1);
+   PG_RETURN_INT32(res);
 }
 
 Datum
 jsonb_le(PG_FUNCTION_ARGS)
 {
-   int         res = DatumGetInt32(DirectFunctionCall2(jsonb_cmp,
-                                                       PG_GETARG_DATUM(0),
-                                                       PG_GETARG_DATUM(1)));
+   Jsonb      *jb1 = PG_GETARG_JSONB(0);
+   Jsonb      *jb2 = PG_GETARG_JSONB(1);
+   bool        res;
+
+   res = (compareJsonbSuperHeaderValue(VARDATA(jb1), VARDATA(jb2)) <= 0);
 
-   PG_RETURN_BOOL(res <= 0);
+   PG_FREE_IF_COPY(jb1, 0);
+   PG_FREE_IF_COPY(jb2, 1);
+   PG_RETURN_INT32(res);
 }
 
 Datum
 jsonb_ge(PG_FUNCTION_ARGS)
 {
-   int         res = DatumGetInt32(DirectFunctionCall2(jsonb_cmp,
-                                                       PG_GETARG_DATUM(0),
-                                                       PG_GETARG_DATUM(1)));
 
-   PG_RETURN_BOOL(res >= 0);
+   Jsonb      *jb1 = PG_GETARG_JSONB(0);
+   Jsonb      *jb2 = PG_GETARG_JSONB(1);
+   bool        res;
+
+   res = (compareJsonbSuperHeaderValue(VARDATA(jb1), VARDATA(jb2)) >= 0);
+
+   PG_FREE_IF_COPY(jb1, 0);
+   PG_FREE_IF_COPY(jb2, 1);
+   PG_RETURN_INT32(res);
 }
 
 Datum
 jsonb_eq(PG_FUNCTION_ARGS)
 {
-   int         res = DatumGetInt32(DirectFunctionCall2(jsonb_cmp,
-                                                       PG_GETARG_DATUM(0),
-                                                       PG_GETARG_DATUM(1)));
+   Jsonb      *jb1 = PG_GETARG_JSONB(0);
+   Jsonb      *jb2 = PG_GETARG_JSONB(1);
+   bool        res;
+
+   res = (compareJsonbSuperHeaderValue(VARDATA(jb1), VARDATA(jb2)) == 0);
 
-   PG_RETURN_BOOL(res == 0);
+   PG_FREE_IF_COPY(jb1, 0);
+   PG_FREE_IF_COPY(jb2, 1);
+   PG_RETURN_INT32(res);
 }
 
 Datum
@@ -200,15 +235,10 @@ jsonb_cmp(PG_FUNCTION_ARGS)
 {
    Jsonb      *jb1 = PG_GETARG_JSONB(0);
    Jsonb      *jb2 = PG_GETARG_JSONB(1);
-
    int         res;
 
    res = compareJsonbSuperHeaderValue(VARDATA(jb1), VARDATA(jb2));
 
-   /*
-    * This is a btree support function; this is one of the few places where
-    * memory needs to be explicitly freed.
-    */
    PG_FREE_IF_COPY(jb1, 0);
    PG_FREE_IF_COPY(jb2, 1);
    PG_RETURN_INT32(res);
index fd19ffa41ef1981d76acbe8075ba0249657f7110..ac09034f3d0e5eb1d522f2e84654d479dbfb9003 100644 (file)
@@ -1794,7 +1794,7 @@ DESCR("less than or equal to");
 DATA(insert OID = 3245 (  ">=" PGNSP PGUID b f f 3802 3802 16 3244 3242 jsonb_ge scalargtsel scalargtjoinsel ));
 DESCR("greater than or equal to");
 /* No commutator? */
-DATA(insert OID = 3246 (  "@>"    PGNSP PGUID b f f 3802 3802 16 0 0 jsonb_contains contsel contjoinsel ));
+DATA(insert OID = 3246 (  "@>"    PGNSP PGUID b f f 3802 3802 16 0 3250 jsonb_contains contsel contjoinsel ));
 DESCR("contains");
 DATA(insert OID = 3247 (  "?"     PGNSP PGUID b f f 3802 25 16 0 0 jsonb_exists contsel contjoinsel ));
 DESCR("exists");
@@ -1802,7 +1802,7 @@ DATA(insert OID = 3248 (  "?|"       PGNSP PGUID b f f 3802 1009 16 0 0 jsonb_exist
 DESCR("exists any");
 DATA(insert OID = 3249 (  "?&"    PGNSP PGUID b f f 3802 1009 16 0 0 jsonb_exists_all contsel contjoinsel ));
 DESCR("exists all");
-DATA(insert OID = 3250 (  "<@"    PGNSP PGUID b f f 3802 3802 16 0 0 jsonb_contained contsel contjoinsel ));
+DATA(insert OID = 3250 (  "<@"    PGNSP PGUID b f f 3802 3802 16 0 3246 jsonb_contained contsel contjoinsel ));
 DESCR("contained");
 
 /*