Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
c80b9920
Commit
c80b9920
authored
Mar 31, 2017
by
Andrew Dunstan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Transform or iterate over json(b) string values
Dmitry Dolgov, reviewed and lightly edited by me.
parent
156d3882
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
252 additions
and
0 deletions
+252
-0
src/backend/utils/adt/jsonfuncs.c
src/backend/utils/adt/jsonfuncs.c
+236
-0
src/include/utils/jsonapi.h
src/include/utils/jsonapi.h
+16
-0
No files found.
src/backend/utils/adt/jsonfuncs.c
View file @
c80b9920
...
...
@@ -52,6 +52,25 @@ typedef struct OkeysState
int
sent_count
;
}
OkeysState
;
/* state for iterate_json_string_values function */
typedef
struct
IterateJsonStringValuesState
{
JsonLexContext
*
lex
;
JsonIterateStringValuesAction
action
;
/* an action that will be applied
to each json value */
void
*
action_state
;
/* any necessary context for iteration */
}
IterateJsonStringValuesState
;
/* state for transform_json_string_values function */
typedef
struct
TransformJsonStringValuesState
{
JsonLexContext
*
lex
;
StringInfo
strval
;
/* resulting json */
JsonTransformStringValuesAction
action
;
/* an action that will be applied
to each json value */
void
*
action_state
;
/* any necessary context for transformation */
}
TransformJsonStringValuesState
;
/* state for json_get* functions */
typedef
struct
GetState
{
...
...
@@ -271,6 +290,18 @@ static void setPathArray(JsonbIterator **it, Datum *path_elems,
int
level
,
Jsonb
*
newval
,
uint32
nelems
,
int
op_type
);
static
void
addJsonbToParseState
(
JsonbParseState
**
jbps
,
Jsonb
*
jb
);
/* function supporting iterate_json_string_values */
static
void
iterate_string_values_scalar
(
void
*
state
,
char
*
token
,
JsonTokenType
tokentype
);
/* functions supporting transform_json_string_values */
static
void
transform_string_values_object_start
(
void
*
state
);
static
void
transform_string_values_object_end
(
void
*
state
);
static
void
transform_string_values_array_start
(
void
*
state
);
static
void
transform_string_values_array_end
(
void
*
state
);
static
void
transform_string_values_object_field_start
(
void
*
state
,
char
*
fname
,
bool
isnull
);
static
void
transform_string_values_array_element_start
(
void
*
state
,
bool
isnull
);
static
void
transform_string_values_scalar
(
void
*
state
,
char
*
token
,
JsonTokenType
tokentype
);
/*
* SQL function json_object_keys
...
...
@@ -4130,3 +4161,208 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
}
}
}
/*
* Iterate over jsonb string values or elements, and pass them together with an
* iteration state to a specified JsonIterateStringValuesAction.
*/
void
iterate_jsonb_string_values
(
Jsonb
*
jb
,
void
*
state
,
JsonIterateStringValuesAction
action
)
{
JsonbIterator
*
it
;
JsonbValue
v
;
JsonbIteratorToken
type
;
it
=
JsonbIteratorInit
(
&
jb
->
root
);
while
((
type
=
JsonbIteratorNext
(
&
it
,
&
v
,
false
))
!=
WJB_DONE
)
{
if
((
type
==
WJB_VALUE
||
type
==
WJB_ELEM
)
&&
v
.
type
==
jbvString
)
{
action
(
state
,
v
.
val
.
string
.
val
,
v
.
val
.
string
.
len
);
}
}
}
/*
* Iterate over json string values or elements, and pass them together with an
* iteration state to a specified JsonIterateStringValuesAction.
*/
void
iterate_json_string_values
(
text
*
json
,
void
*
action_state
,
JsonIterateStringValuesAction
action
)
{
JsonLexContext
*
lex
=
makeJsonLexContext
(
json
,
true
);
JsonSemAction
*
sem
=
palloc0
(
sizeof
(
JsonSemAction
));
IterateJsonStringValuesState
*
state
=
palloc0
(
sizeof
(
IterateJsonStringValuesState
));
state
->
lex
=
lex
;
state
->
action
=
action
;
state
->
action_state
=
action_state
;
sem
->
semstate
=
(
void
*
)
state
;
sem
->
scalar
=
iterate_string_values_scalar
;
pg_parse_json
(
lex
,
sem
);
}
/*
* An auxiliary function for iterate_json_string_values to invoke a specified
* JsonIterateStringValuesAction.
*/
static
void
iterate_string_values_scalar
(
void
*
state
,
char
*
token
,
JsonTokenType
tokentype
)
{
IterateJsonStringValuesState
*
_state
=
(
IterateJsonStringValuesState
*
)
state
;
if
(
tokentype
==
JSON_TOKEN_STRING
)
(
*
_state
->
action
)
(
_state
->
action_state
,
token
,
strlen
(
token
));
}
/*
* Iterate over a jsonb, and apply a specified JsonTransformStringValuesAction
* to every string value or element. Any necessary context for a
* JsonTransformStringValuesAction can be passed in the action_state variable.
* Function returns a copy of an original jsonb object with transformed values.
*/
Jsonb
*
transform_jsonb_string_values
(
Jsonb
*
jsonb
,
void
*
action_state
,
JsonTransformStringValuesAction
transform_action
)
{
JsonbIterator
*
it
;
JsonbValue
v
,
*
res
=
NULL
;
JsonbIteratorToken
type
;
JsonbParseState
*
st
=
NULL
;
text
*
out
;
bool
is_scalar
=
false
;
it
=
JsonbIteratorInit
(
&
jsonb
->
root
);
is_scalar
=
it
->
isScalar
;
while
((
type
=
JsonbIteratorNext
(
&
it
,
&
v
,
false
))
!=
WJB_DONE
)
{
if
((
type
==
WJB_VALUE
||
type
==
WJB_ELEM
)
&&
v
.
type
==
jbvString
)
{
out
=
transform_action
(
action_state
,
v
.
val
.
string
.
val
,
v
.
val
.
string
.
len
);
v
.
val
.
string
.
val
=
VARDATA_ANY
(
out
);
v
.
val
.
string
.
len
=
VARSIZE_ANY_EXHDR
(
out
);
res
=
pushJsonbValue
(
&
st
,
type
,
type
<
WJB_BEGIN_ARRAY
?
&
v
:
NULL
);
}
else
{
res
=
pushJsonbValue
(
&
st
,
type
,
(
type
==
WJB_KEY
||
type
==
WJB_VALUE
||
type
==
WJB_ELEM
)
?
&
v
:
NULL
);
}
}
if
(
res
->
type
==
jbvArray
)
res
->
val
.
array
.
rawScalar
=
is_scalar
;
return
JsonbValueToJsonb
(
res
);
}
/*
* Iterate over a json, and apply a specified JsonTransformStringValuesAction
* to every string value or element. Any necessary context for a
* JsonTransformStringValuesAction can be passed in the action_state variable.
* Function returns a StringInfo, which is a copy of an original json with
* transformed values.
*/
text
*
transform_json_string_values
(
text
*
json
,
void
*
action_state
,
JsonTransformStringValuesAction
transform_action
)
{
JsonLexContext
*
lex
=
makeJsonLexContext
(
json
,
true
);
JsonSemAction
*
sem
=
palloc0
(
sizeof
(
JsonSemAction
));
TransformJsonStringValuesState
*
state
=
palloc0
(
sizeof
(
TransformJsonStringValuesState
));
state
->
lex
=
lex
;
state
->
strval
=
makeStringInfo
();
state
->
action
=
transform_action
;
state
->
action_state
=
action_state
;
sem
->
semstate
=
(
void
*
)
state
;
sem
->
scalar
=
transform_string_values_scalar
;
sem
->
object_start
=
transform_string_values_object_start
;
sem
->
object_end
=
transform_string_values_object_end
;
sem
->
array_start
=
transform_string_values_array_start
;
sem
->
array_end
=
transform_string_values_array_end
;
sem
->
scalar
=
transform_string_values_scalar
;
sem
->
array_element_start
=
transform_string_values_array_element_start
;
sem
->
object_field_start
=
transform_string_values_object_field_start
;
pg_parse_json
(
lex
,
sem
);
return
cstring_to_text_with_len
(
state
->
strval
->
data
,
state
->
strval
->
len
);
}
/*
* Set of auxiliary functions for transform_json_string_values to invoke a
* specified JsonTransformStringValuesAction for all values and left everything
* else untouched.
*/
static
void
transform_string_values_object_start
(
void
*
state
)
{
TransformJsonStringValuesState
*
_state
=
(
TransformJsonStringValuesState
*
)
state
;
appendStringInfoCharMacro
(
_state
->
strval
,
'{'
);
}
static
void
transform_string_values_object_end
(
void
*
state
)
{
TransformJsonStringValuesState
*
_state
=
(
TransformJsonStringValuesState
*
)
state
;
appendStringInfoCharMacro
(
_state
->
strval
,
'}'
);
}
static
void
transform_string_values_array_start
(
void
*
state
)
{
TransformJsonStringValuesState
*
_state
=
(
TransformJsonStringValuesState
*
)
state
;
appendStringInfoCharMacro
(
_state
->
strval
,
'['
);
}
static
void
transform_string_values_array_end
(
void
*
state
)
{
TransformJsonStringValuesState
*
_state
=
(
TransformJsonStringValuesState
*
)
state
;
appendStringInfoCharMacro
(
_state
->
strval
,
']'
);
}
static
void
transform_string_values_object_field_start
(
void
*
state
,
char
*
fname
,
bool
isnull
)
{
TransformJsonStringValuesState
*
_state
=
(
TransformJsonStringValuesState
*
)
state
;
if
(
_state
->
strval
->
data
[
_state
->
strval
->
len
-
1
]
!=
'{'
)
appendStringInfoCharMacro
(
_state
->
strval
,
','
);
/*
* Unfortunately we don't have the quoted and escaped string any more, so
* we have to re-escape it.
*/
escape_json
(
_state
->
strval
,
fname
);
appendStringInfoCharMacro
(
_state
->
strval
,
':'
);
}
static
void
transform_string_values_array_element_start
(
void
*
state
,
bool
isnull
)
{
TransformJsonStringValuesState
*
_state
=
(
TransformJsonStringValuesState
*
)
state
;
if
(
_state
->
strval
->
data
[
_state
->
strval
->
len
-
1
]
!=
'['
)
appendStringInfoCharMacro
(
_state
->
strval
,
','
);
}
static
void
transform_string_values_scalar
(
void
*
state
,
char
*
token
,
JsonTokenType
tokentype
)
{
TransformJsonStringValuesState
*
_state
=
(
TransformJsonStringValuesState
*
)
state
;
if
(
tokentype
==
JSON_TOKEN_STRING
)
{
text
*
out
=
(
*
_state
->
action
)
(
_state
->
action_state
,
token
,
strlen
(
token
));
escape_json
(
_state
->
strval
,
text_to_cstring
(
out
));
}
else
appendStringInfoString
(
_state
->
strval
,
token
);
}
src/include/utils/jsonapi.h
View file @
c80b9920
...
...
@@ -14,6 +14,7 @@
#ifndef JSONAPI_H
#define JSONAPI_H
#include "jsonb.h"
#include "lib/stringinfo.h"
typedef
enum
...
...
@@ -131,4 +132,19 @@ extern JsonLexContext *makeJsonLexContextCstringLen(char *json,
*/
extern
bool
IsValidJsonNumber
(
const
char
*
str
,
int
len
);
/* an action that will be applied to each value in iterate_json(b)_string_vaues functions */
typedef
void
(
*
JsonIterateStringValuesAction
)
(
void
*
state
,
char
*
elem_value
,
int
elem_len
);
/* an action that will be applied to each value in transform_json(b)_string_values functions */
typedef
text
*
(
*
JsonTransformStringValuesAction
)
(
void
*
state
,
char
*
elem_value
,
int
elem_len
);
extern
void
iterate_jsonb_string_values
(
Jsonb
*
jb
,
void
*
state
,
JsonIterateStringValuesAction
action
);
extern
void
iterate_json_string_values
(
text
*
json
,
void
*
action_state
,
JsonIterateStringValuesAction
action
);
extern
Jsonb
*
transform_jsonb_string_values
(
Jsonb
*
jsonb
,
void
*
action_state
,
JsonTransformStringValuesAction
transform_action
);
extern
text
*
transform_json_string_values
(
text
*
json
,
void
*
action_state
,
JsonTransformStringValuesAction
transform_action
);
#endif
/* JSONAPI_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment