Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
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
nexedi
MariaDB
Commits
cba46c99
Commit
cba46c99
authored
Dec 31, 2020
by
Olivier Bertrand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- Fix jfile_convert crash on error. modified: jsonudf.cpp (plus BSON UDF's)
parent
a3542482
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
3077 additions
and
368 deletions
+3077
-368
storage/connect/bson.cpp
storage/connect/bson.cpp
+21
-17
storage/connect/bson.h
storage/connect/bson.h
+4
-2
storage/connect/bsonudf.cpp
storage/connect/bsonudf.cpp
+2851
-334
storage/connect/bsonudf.h
storage/connect/bsonudf.h
+187
-2
storage/connect/filamtxt.cpp
storage/connect/filamtxt.cpp
+1
-1
storage/connect/jsonudf.cpp
storage/connect/jsonudf.cpp
+13
-12
No files found.
storage/connect/bson.cpp
View file @
cba46c99
...
@@ -808,17 +808,17 @@ void* BJSON::BsonSubAlloc(size_t size)
...
@@ -808,17 +808,17 @@ void* BJSON::BsonSubAlloc(size_t size)
/*********************************************************************************/
/*********************************************************************************/
/* Program for SubSet re-initialization of the memory pool. */
/* Program for SubSet re-initialization of the memory pool. */
/*********************************************************************************/
/*********************************************************************************/
OFFSET
BJSON
::
Dup
Str
(
PSZ
str
)
PSZ
BJSON
::
New
Str
(
PSZ
str
)
{
{
if
(
str
)
{
if
(
str
)
{
PSZ
sm
=
(
PSZ
)
BsonSubAlloc
(
strlen
(
str
)
+
1
);
PSZ
sm
=
(
PSZ
)
BsonSubAlloc
(
strlen
(
str
)
+
1
);
strcpy
(
sm
,
str
);
strcpy
(
sm
,
str
);
return
MOF
(
sm
)
;
return
sm
;
}
else
}
else
return
NULL
;
return
NULL
;
}
// end of
Dup
Str
}
// end of
New
Str
/*********************************************************************************/
/*********************************************************************************/
/* Program for SubSet re-initialization of the memory pool. */
/* Program for SubSet re-initialization of the memory pool. */
...
@@ -940,7 +940,7 @@ PBVAL BJSON::GetObjectValList(PBVAL bop)
...
@@ -940,7 +940,7 @@ PBVAL BJSON::GetObjectValList(PBVAL bop)
PBVAL
arp
=
NewVal
(
TYPE_JAR
);
PBVAL
arp
=
NewVal
(
TYPE_JAR
);
for
(
PBPR
brp
=
GetObject
(
bop
);
brp
;
brp
=
GetNext
(
brp
))
for
(
PBPR
brp
=
GetObject
(
bop
);
brp
;
brp
=
GetNext
(
brp
))
AddArrayValue
(
arp
,
GetVlp
(
brp
));
AddArrayValue
(
arp
,
DupVal
(
GetVlp
(
brp
)
));
return
arp
;
return
arp
;
}
// end of GetObjectValList
}
// end of GetObjectValList
...
@@ -1135,24 +1135,28 @@ PBVAL BJSON::GetArrayValue(PBVAL bap, int n)
...
@@ -1135,24 +1135,28 @@ PBVAL BJSON::GetArrayValue(PBVAL bap, int n)
/***********************************************************************/
/***********************************************************************/
/* Add a Value to the Array Value list. */
/* Add a Value to the Array Value list. */
/***********************************************************************/
/***********************************************************************/
void
BJSON
::
AddArrayValue
(
PBVAL
bap
,
OFFSET
n
vp
,
int
*
x
)
void
BJSON
::
AddArrayValue
(
PBVAL
bap
,
OFFSET
n
bv
,
int
*
x
)
{
{
CheckType
(
bap
,
TYPE_JAR
);
CheckType
(
bap
,
TYPE_JAR
);
i
f
(
!
nvp
)
i
nt
i
=
0
;
nvp
=
MOF
(
NewVal
())
;
PBVAL
bvp
,
lbp
=
NULL
;
if
(
bap
->
To_Val
)
{
if
(
!
nbv
)
int
i
=
0
,
n
=
(
x
)
?
*
x
:
INT_MAX32
;
nbv
=
MOF
(
NewVal
())
;
for
(
PBVAL
bvp
=
GetArray
(
bap
);
bvp
;
bvp
=
GetNext
(
bvp
),
i
++
)
for
(
bvp
=
GetArray
(
bap
);
bvp
;
bvp
=
GetNext
(
bvp
),
i
++
)
if
(
!
bvp
->
Next
||
(
x
&&
i
==
n
))
{
if
(
x
&&
i
==
*
x
)
MVP
(
nvp
)
->
Next
=
bvp
->
Next
;
break
;
bvp
->
Next
=
nvp
;
else
break
;
lbp
=
bvp
;
}
// endif Next
}
else
if
(
lbp
)
{
bap
->
To_Val
=
nvp
;
MVP
(
nbv
)
->
Next
=
lbp
->
Next
;
lbp
->
Next
=
nbv
;
}
else
{
MVP
(
nbv
)
->
Next
=
bap
->
To_Val
;
bap
->
To_Val
=
nbv
;
}
// endif lbp
bap
->
Nd
++
;
bap
->
Nd
++
;
}
// end of AddArrayValue
}
// end of AddArrayValue
...
...
storage/connect/bson.h
View file @
cba46c99
...
@@ -93,7 +93,8 @@ class BJSON : public BLOCK {
...
@@ -93,7 +93,8 @@ class BJSON : public BLOCK {
PBVAL
SubAllocStr
(
PSZ
str
,
short
nd
=
0
)
PBVAL
SubAllocStr
(
PSZ
str
,
short
nd
=
0
)
{
return
SubAllocStr
(
DupStr
(
str
),
nd
);}
{
return
SubAllocStr
(
DupStr
(
str
),
nd
);}
PBVAL
DupVal
(
PBVAL
bvp
);
PBVAL
DupVal
(
PBVAL
bvp
);
OFFSET
DupStr
(
PSZ
str
);
OFFSET
DupStr
(
PSZ
str
)
{
return
MOF
(
NewStr
(
str
));
}
PSZ
NewStr
(
PSZ
str
);
// Array functions
// Array functions
inline
PBVAL
GetArray
(
PBVAL
vlp
)
{
return
MVP
(
vlp
->
To_Val
);}
inline
PBVAL
GetArray
(
PBVAL
vlp
)
{
return
MVP
(
vlp
->
To_Val
);}
...
@@ -150,7 +151,8 @@ class BJSON : public BLOCK {
...
@@ -150,7 +151,8 @@ class BJSON : public BLOCK {
void
SetBool
(
PBVAL
vlp
,
bool
b
);
void
SetBool
(
PBVAL
vlp
,
bool
b
);
void
Clear
(
PBVAL
vlp
)
{
vlp
->
N
=
0
;
vlp
->
Nd
=
0
;
vlp
->
Next
=
0
;
}
void
Clear
(
PBVAL
vlp
)
{
vlp
->
N
=
0
;
vlp
->
Nd
=
0
;
vlp
->
Next
=
0
;
}
bool
IsValueNull
(
PBVAL
vlp
);
bool
IsValueNull
(
PBVAL
vlp
);
bool
IsJson
(
PBVAL
vlp
)
{
return
(
vlp
->
Type
==
TYPE_JAR
||
vlp
->
Type
==
TYPE_JOB
);}
bool
IsJson
(
PBVAL
vlp
)
{
return
vlp
?
vlp
->
Type
==
TYPE_JAR
||
vlp
->
Type
==
TYPE_JOB
:
false
;}
// Members
// Members
PGLOBAL
G
;
PGLOBAL
G
;
...
...
storage/connect/bsonudf.cpp
View file @
cba46c99
...
@@ -27,6 +27,8 @@
...
@@ -27,6 +27,8 @@
#endif
#endif
#define M 6
#define M 6
int
IsArgJson
(
UDF_ARGS
*
args
,
uint
i
);
/* --------------------------------- JSON UDF ---------------------------------- */
/* --------------------------------- JSON UDF ---------------------------------- */
/*********************************************************************************/
/*********************************************************************************/
...
@@ -68,6 +70,35 @@ static PBJNX BjnxNew(PGLOBAL g, PBVAL vlp, int type, int len)
...
@@ -68,6 +70,35 @@ static PBJNX BjnxNew(PGLOBAL g, PBVAL vlp, int type, int len)
/* ----------------------------------- BSNX ------------------------------------ */
/* ----------------------------------- BSNX ------------------------------------ */
/*********************************************************************************/
/* BSNX public constructor. */
/*********************************************************************************/
BJNX
::
BJNX
(
PGLOBAL
g
)
:
BDOC
(
g
)
{
Row
=
NULL
;
Bvalp
=
NULL
;
Jpnp
=
NULL
;
Jp
=
NULL
;
Nodes
=
NULL
;
Value
=
NULL
;
MulVal
=
NULL
;
Jpath
=
NULL
;
Buf_Type
=
TYPE_NULL
;
Long
=
len
;
Prec
=
0
;
Nod
=
0
;
Xnod
=
-
1
;
K
=
0
;
I
=
-
1
;
Imax
=
9
;
B
=
0
;
Xpd
=
false
;
Parsed
=
false
;
Found
=
false
;
Wr
=
false
;
Jb
=
false
;
}
// end of BJNX constructor
/*********************************************************************************/
/*********************************************************************************/
/* BSNX public constructor. */
/* BSNX public constructor. */
/*********************************************************************************/
/*********************************************************************************/
...
@@ -330,6 +361,51 @@ my_bool BJNX::ParseJpath(PGLOBAL g)
...
@@ -330,6 +361,51 @@ my_bool BJNX::ParseJpath(PGLOBAL g)
return
false
;
return
false
;
}
// end of ParseJpath
}
// end of ParseJpath
/*********************************************************************************/
/* Make a valid key from the passed argument. */
/*********************************************************************************/
PSZ
BJNX
::
MakeKey
(
UDF_ARGS
*
args
,
int
i
)
{
if
(
args
->
arg_count
>
(
unsigned
)
i
)
{
int
j
=
0
,
n
=
args
->
attribute_lengths
[
i
];
my_bool
b
;
// true if attribute is zero terminated
PSZ
p
;
PCSZ
s
=
args
->
attributes
[
i
];
if
(
s
&&
*
s
&&
(
n
||
*
s
==
'\''
))
{
if
((
b
=
(
!
n
||
!
s
[
n
])))
n
=
strlen
(
s
);
if
(
IsArgJson
(
args
,
i
))
j
=
(
int
)(
strchr
(
s
,
'_'
)
-
s
+
1
);
if
(
j
&&
n
>
j
)
{
s
+=
j
;
n
-=
j
;
}
else
if
(
*
s
==
'\''
&&
s
[
n
-
1
]
==
'\''
)
{
s
++
;
n
-=
2
;
b
=
false
;
}
// endif *s
if
(
n
<
1
)
return
NewStr
(
"Key"
);
if
(
!
b
)
{
p
=
(
PSZ
)
BsonSubAlloc
(
n
+
1
);
memcpy
(
p
,
s
,
n
);
p
[
n
]
=
0
;
return
p
;
}
// endif b
}
// endif s
return
NewStr
((
PSZ
)
s
);
}
// endif count
return
NewStr
(
"Key"
);
}
// end of MakeKey
/*********************************************************************************/
/*********************************************************************************/
/* MakeJson: Serialize the json item and set value to it. */
/* MakeJson: Serialize the json item and set value to it. */
/*********************************************************************************/
/*********************************************************************************/
...
@@ -367,6 +443,7 @@ void BJNX::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL vlp)
...
@@ -367,6 +443,7 @@ void BJNX::SetJsonValue(PGLOBAL g, PVAL vp, PBVAL vlp)
vp
->
SetValue
(
GetInteger
(
vlp
));
vp
->
SetValue
(
GetInteger
(
vlp
));
break
;
break
;
case
TYPE_DBL
:
case
TYPE_DBL
:
case
TYPE_FLOAT
:
if
(
vp
->
IsTypeNum
())
if
(
vp
->
IsTypeNum
())
vp
->
SetValue
(
GetDouble
(
vlp
));
vp
->
SetValue
(
GetDouble
(
vlp
));
else
// Get the proper number of decimals
else
// Get the proper number of decimals
...
@@ -509,7 +586,6 @@ PVAL BJNX::ExpandArray(PGLOBAL g, PBVAL arp, int n)
...
@@ -509,7 +586,6 @@ PVAL BJNX::ExpandArray(PGLOBAL g, PBVAL arp, int n)
/*********************************************************************************/
/*********************************************************************************/
PVAL
BJNX
::
CalculateArray
(
PGLOBAL
g
,
PBVAL
bap
,
int
n
)
PVAL
BJNX
::
CalculateArray
(
PGLOBAL
g
,
PBVAL
bap
,
int
n
)
{
{
#if 0
int
i
,
ars
=
GetArraySize
(
bap
),
nv
=
0
;
int
i
,
ars
=
GetArraySize
(
bap
),
nv
=
0
;
bool
err
;
bool
err
;
OPVAL
op
=
Nodes
[
n
].
Op
;
OPVAL
op
=
Nodes
[
n
].
Op
;
...
@@ -526,45 +602,45 @@ PVAL BJNX::CalculateArray(PGLOBAL g, PBVAL bap, int n)
...
@@ -526,45 +602,45 @@ PVAL BJNX::CalculateArray(PGLOBAL g, PBVAL bap, int n)
if
(
!
IsValueNull
(
bvrp
)
||
(
op
==
OP_CNC
&&
GetJsonNull
()))
{
if
(
!
IsValueNull
(
bvrp
)
||
(
op
==
OP_CNC
&&
GetJsonNull
()))
{
if
(
IsValueNull
(
bvrp
))
{
if
(
IsValueNull
(
bvrp
))
{
SetString(bvrp,
GetJsonNull(
), 0);
SetString
(
bvrp
,
NewStr
(
GetJsonNull
()
),
0
);
bvp
=
bvrp
;
bvp
=
bvrp
;
} else if (n < Nod - 1 &&
bvrp->GetJson(
)) {
}
else
if
(
n
<
Nod
-
1
&&
IsJson
(
bvrp
))
{
bval.SetValue(g, GetColumnValue(g, jvrp->GetJson()
, n + 1));
SetValue
(
&
bval
,
GetColumnValue
(
g
,
bvrp
,
n
+
1
));
bvp
=
&
bval
;
bvp
=
&
bval
;
}
else
}
else
jvp = j
vrp;
bvp
=
b
vrp
;
if
(
trace
(
1
))
if
(
trace
(
1
))
htrc("
j
vp=%s null=%d\n",
htrc
(
"
b
vp=%s null=%d
\n
"
,
jvp->GetString(g), jvp->IsNull(
) ? 1 : 0);
GetString
(
bvp
),
IsValueNull
(
bvp
)
?
1
:
0
);
if
(
!
nv
++
)
{
if
(
!
nv
++
)
{
SetJsonValue(g, vp,
j
vp);
SetJsonValue
(
g
,
vp
,
b
vp
);
continue
;
continue
;
}
else
}
else
SetJsonValue(g, MulVal,
j
vp);
SetJsonValue
(
g
,
MulVal
,
b
vp
);
if
(
!
MulVal
->
IsNull
())
{
if
(
!
MulVal
->
IsNull
())
{
switch
(
op
)
{
switch
(
op
)
{
case OP_CNC:
case
OP_CNC
:
if (Nodes[n].CncVal) {
if
(
Nodes
[
n
].
CncVal
)
{
val[0] = Nodes[n].CncVal;
val
[
0
]
=
Nodes
[
n
].
CncVal
;
err = vp->Compute(g, val, 1, op);
err
=
vp
->
Compute
(
g
,
val
,
1
,
op
);
} // endif CncVal
}
// endif CncVal
val[0] = MulVal;
val
[
0
]
=
MulVal
;
err = vp->Compute(g, val, 1, op);
err
=
vp
->
Compute
(
g
,
val
,
1
,
op
);
break;
break
;
//
case OP_NUM:
//
case OP_NUM:
case OP_SEP:
case
OP_SEP
:
val[0] = Nodes[n].Valp;
val
[
0
]
=
Nodes
[
n
].
Valp
;
val[1] = MulVal;
val
[
1
]
=
MulVal
;
err = vp->Compute(g, val, 2, OP_ADD);
err
=
vp
->
Compute
(
g
,
val
,
2
,
OP_ADD
);
break;
break
;
default:
default:
val[0] = Nodes[n].Valp;
val
[
0
]
=
Nodes
[
n
].
Valp
;
val[1] = MulVal;
val
[
1
]
=
MulVal
;
err = vp->Compute(g, val, 2, op);
err
=
vp
->
Compute
(
g
,
val
,
2
,
op
);
}
// endswitch Op
}
// endswitch Op
if
(
err
)
if
(
err
)
...
@@ -595,53 +671,8 @@ PVAL BJNX::CalculateArray(PGLOBAL g, PBVAL bap, int n)
...
@@ -595,53 +671,8 @@ PVAL BJNX::CalculateArray(PGLOBAL g, PBVAL bap, int n)
}
// endif Op
}
// endif Op
return
vp
;
return
vp
;
#else
strcpy
(
g
->
Message
,
"Calculate array NIY"
);
return
NULL
;
#endif
}
// end of CalculateArray
}
// end of CalculateArray
/*********************************************************************************/
/* CheckPath: Checks whether the path exists in the document. */
/*********************************************************************************/
my_bool
BJNX
::
CheckPath
(
PGLOBAL
g
)
{
PBVAL
val
=
NULL
;
PBVAL
row
=
Row
;
for
(
int
i
=
0
;
i
<
Nod
&&
row
;
i
++
)
{
val
=
NULL
;
if
(
Nodes
[
i
].
Op
==
OP_NUM
||
Nodes
[
i
].
Op
==
OP_XX
)
{
}
else
switch
(
row
->
Type
)
{
case
TYPE_JOB
:
if
(
Nodes
[
i
].
Key
)
val
=
GetKeyValue
(
row
,
Nodes
[
i
].
Key
);
break
;
case
TYPE_JAR
:
if
(
!
Nodes
[
i
].
Key
)
if
(
Nodes
[
i
].
Op
==
OP_EQ
||
Nodes
[
i
].
Op
==
OP_LE
)
val
=
GetArrayValue
(
row
,
Nodes
[
i
].
Rank
);
break
;
case
TYPE_JVAL
:
val
=
MVP
(
row
->
To_Val
);
break
;
default:
sprintf
(
g
->
Message
,
"Invalid row JSON type %d"
,
row
->
Type
);
}
// endswitch Type
// if (i < Nod - 1)
// if (!(row = (val) ? val->GetJsp() : NULL))
// val = NULL;
row
=
val
;
}
// endfor i
return
(
val
!=
NULL
);
}
// end of CheckPath
/***********************************************************************/
/***********************************************************************/
/* GetRow: Set the complete path of the object to be set. */
/* GetRow: Set the complete path of the object to be set. */
/***********************************************************************/
/***********************************************************************/
...
@@ -758,6 +789,79 @@ my_bool BJNX::WriteValue(PGLOBAL g, PBVAL jvalp)
...
@@ -758,6 +789,79 @@ my_bool BJNX::WriteValue(PGLOBAL g, PBVAL jvalp)
return
false
;
return
false
;
}
// end of WriteValue
}
// end of WriteValue
/*********************************************************************************/
/* CheckPath: Checks whether the path exists in the document. */
/*********************************************************************************/
my_bool
BJNX
::
CheckPath
(
PGLOBAL
g
)
{
PBVAL
val
=
NULL
;
PBVAL
row
=
Row
;
for
(
int
i
=
0
;
i
<
Nod
&&
row
;
i
++
)
{
val
=
NULL
;
if
(
Nodes
[
i
].
Op
==
OP_NUM
||
Nodes
[
i
].
Op
==
OP_XX
)
{
}
else
switch
(
row
->
Type
)
{
case
TYPE_JOB
:
if
(
Nodes
[
i
].
Key
)
val
=
GetKeyValue
(
row
,
Nodes
[
i
].
Key
);
break
;
case
TYPE_JAR
:
if
(
!
Nodes
[
i
].
Key
)
if
(
Nodes
[
i
].
Op
==
OP_EQ
||
Nodes
[
i
].
Op
==
OP_LE
)
val
=
GetArrayValue
(
row
,
Nodes
[
i
].
Rank
);
break
;
case
TYPE_JVAL
:
val
=
row
;
break
;
default:
sprintf
(
g
->
Message
,
"Invalid row JSON type %d"
,
row
->
Type
);
}
// endswitch Type
if
(
i
<
Nod
-
1
)
if
(
!
(
row
=
(
IsJson
(
val
))
?
val
:
NULL
))
val
=
NULL
;
}
// endfor i
return
(
val
!=
NULL
);
}
// end of CheckPath
/*********************************************************************************/
/* Check if a path was specified and set jvp according to it. */
/*********************************************************************************/
my_bool
BJNX
::
CheckPath
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
PBVAL
jsp
,
PBVAL
&
jvp
,
int
n
)
{
for
(
uint
i
=
n
;
i
<
args
->
arg_count
;
i
++
)
if
(
args
->
arg_type
[
i
]
==
STRING_RESULT
&&
args
->
args
[
i
])
{
// A path to a subset of the json tree is given
char
*
path
=
MakePSZ
(
g
,
args
,
i
);
if
(
path
)
{
Row
=
jsp
;
if
(
SetJpath
(
g
,
path
))
return
true
;
if
(
!
(
jvp
=
GetJson
(
g
)))
{
sprintf
(
g
->
Message
,
"No sub-item at '%s'"
,
path
);
return
true
;
}
else
return
false
;
}
else
{
strcpy
(
g
->
Message
,
"Path argument is null"
);
return
true
;
}
// endif path
}
// endif type
jvp
=
jsp
;
return
false
;
}
// end of CheckPath
/*********************************************************************************/
/*********************************************************************************/
/* Locate a value in a JSON tree: */
/* Locate a value in a JSON tree: */
/*********************************************************************************/
/*********************************************************************************/
...
@@ -1141,24 +1245,97 @@ my_bool BJNX::AddPath(void)
...
@@ -1141,24 +1245,97 @@ my_bool BJNX::AddPath(void)
return
false
;
return
false
;
}
// end of AddPath
}
// end of AddPath
/* -----------------------------Utility functions ------------------------------ */
/*********************************************************************************/
/* Make a JSON value from the passed argument. */
/*********************************************************************************/
PBVAL
BJNX
::
MakeValue
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
uint
i
,
PBVAL
*
top
)
{
char
*
sap
=
(
args
->
arg_count
>
i
)
?
args
->
args
[
i
]
:
NULL
;
int
n
,
len
;
int
ci
;
long
long
bigint
;
PBVAL
jvp
=
NewVal
();
if
(
top
)
*
top
=
NULL
;
if
(
sap
)
switch
(
args
->
arg_type
[
i
])
{
case
STRING_RESULT
:
if
((
len
=
args
->
lengths
[
i
]))
{
if
((
n
=
IsArgJson
(
args
,
i
))
<
3
)
sap
=
MakePSZ
(
g
,
args
,
i
);
if
(
n
)
{
if
(
n
==
3
)
{
// if (top)
// *top = ((PBSON)sap)->Top;
// jvp = ((PBSON)sap)->Jsp;
}
else
{
if
(
n
==
2
)
{
if
(
!
(
sap
=
GetJsonFile
(
g
,
sap
)))
{
PUSH_WARNING
(
g
->
Message
);
return
NewVal
();
}
// endif sap
len
=
strlen
(
sap
);
}
// endif n
if
(
!
(
jvp
=
ParseJson
(
g
,
sap
,
strlen
(
sap
))))
PUSH_WARNING
(
g
->
Message
);
else
if
(
top
)
*
top
=
jvp
;
}
// endif's n
}
else
{
ci
=
(
strnicmp
(
args
->
attributes
[
i
],
"ci"
,
2
))
?
0
:
1
;
SetString
(
jvp
,
sap
,
ci
);
}
// endif n
}
// endif len
break
;
case
INT_RESULT
:
bigint
=
*
(
long
long
*
)
sap
;
if
((
bigint
==
0LL
&&
!
strcmp
(
args
->
attributes
[
i
],
"FALSE"
))
||
(
bigint
==
1LL
&&
!
strcmp
(
args
->
attributes
[
i
],
"TRUE"
)))
SetBool
(
jvp
,
(
char
)
bigint
);
else
SetBigint
(
jvp
,
bigint
);
break
;
case
REAL_RESULT
:
SetFloat
(
jvp
,
*
(
double
*
)
sap
);
break
;
case
DECIMAL_RESULT
:
SetFloat
(
jvp
,
atof
(
MakePSZ
(
g
,
args
,
i
)));
break
;
case
TIME_RESULT
:
case
ROW_RESULT
:
default:
break
;
}
// endswitch arg_type
return
jvp
;
}
// end of MakeValue
/*********************************************************************************/
/*********************************************************************************/
/* Make a BVAL value from the passed argument. */
/* Make a BVAL value from the passed argument. */
/*********************************************************************************/
/*********************************************************************************/
static
PBVAL
MakeBinValue
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
uint
i
)
PBVAL
BJNX
::
MakeBinValue
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
uint
i
)
{
{
char
*
sap
=
(
args
->
arg_count
>
i
)
?
args
->
args
[
i
]
:
NULL
;
char
*
sap
=
(
args
->
arg_count
>
i
)
?
args
->
args
[
i
]
:
NULL
;
int
n
,
len
;
int
n
,
len
;
int
ci
;
int
ci
;
longlong
bigint
;
longlong
bigint
;
BDOC
doc
(
g
);
PBVAL
bp
,
bvp
=
NewVal
();
PBVAL
bp
,
bvp
=
doc
.
NewVal
();
if
(
sap
)
{
if
(
sap
)
{
if
(
args
->
arg_type
[
i
]
==
STRING_RESULT
)
{
if
(
args
->
arg_type
[
i
]
==
STRING_RESULT
)
{
if
((
len
=
args
->
lengths
[
i
]))
{
if
((
len
=
args
->
lengths
[
i
]))
{
if
((
n
=
IsJson
(
args
,
i
))
<
3
)
if
((
n
=
Is
Arg
Json
(
args
,
i
))
<
3
)
sap
=
MakePSZ
(
g
,
args
,
i
);
sap
=
MakePSZ
(
g
,
args
,
i
);
if
(
n
)
{
if
(
n
)
{
...
@@ -1171,7 +1348,7 @@ static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i)
...
@@ -1171,7 +1348,7 @@ static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i)
len
=
strlen
(
sap
);
len
=
strlen
(
sap
);
}
// endif 2
}
// endif 2
if
(
!
(
bp
=
doc
.
ParseJson
(
g
,
sap
,
strlen
(
sap
))))
{
if
(
!
(
bp
=
ParseJson
(
g
,
sap
,
strlen
(
sap
))))
{
PUSH_WARNING
(
g
->
Message
);
PUSH_WARNING
(
g
->
Message
);
return
NULL
;
return
NULL
;
}
else
}
else
...
@@ -1181,11 +1358,11 @@ static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i)
...
@@ -1181,11 +1358,11 @@ static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i)
// Check whether this string is a valid json string
// Check whether this string is a valid json string
JsonMemSave
(
g
);
JsonMemSave
(
g
);
if
(
!
(
bp
=
doc
.
ParseJson
(
g
,
sap
,
strlen
(
sap
))))
{
if
(
!
(
bp
=
ParseJson
(
g
,
sap
,
strlen
(
sap
))))
{
// Recover suballocated memory
// Recover suballocated memory
JsonSubSet
(
g
);
JsonSubSet
(
g
);
ci
=
(
strnicmp
(
args
->
attributes
[
i
],
"ci"
,
2
))
?
0
:
1
;
ci
=
(
strnicmp
(
args
->
attributes
[
i
],
"ci"
,
2
))
?
0
:
1
;
doc
.
SetString
(
bvp
,
sap
,
ci
);
SetString
(
bvp
,
sap
,
ci
);
}
else
}
else
bvp
=
bp
;
bvp
=
bp
;
...
@@ -1199,30 +1376,252 @@ static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i)
...
@@ -1199,30 +1376,252 @@ static PBVAL MakeBinValue(PGLOBAL g, UDF_ARGS* args, uint i)
bigint
=
*
(
longlong
*
)
sap
;
bigint
=
*
(
longlong
*
)
sap
;
if
((
bigint
==
0LL
&&
!
strcmp
(
args
->
attributes
[
i
],
"FALSE"
))
||
if
((
bigint
==
0LL
&&
!
strcmp
(
args
->
attributes
[
i
],
"FALSE"
))
||
(
bigint
==
1LL
&&
!
strcmp
(
args
->
attributes
[
i
],
"TRUE"
)))
(
bigint
==
1LL
&&
!
strcmp
(
args
->
attributes
[
i
],
"TRUE"
)))
doc
.
SetBool
(
bvp
,
(
bool
)
bigint
);
SetBool
(
bvp
,
(
bool
)
bigint
);
else
else
doc
.
SetBigint
(
bvp
,
bigint
);
SetBigint
(
bvp
,
bigint
);
break
;
break
;
case
REAL_RESULT
:
case
REAL_RESULT
:
doc
.
SetFloat
(
bvp
,
*
(
double
*
)
sap
);
SetFloat
(
bvp
,
*
(
double
*
)
sap
);
break
;
break
;
case
DECIMAL_RESULT
:
case
DECIMAL_RESULT
:
doc
.
SetFloat
(
bvp
,
atof
(
MakePSZ
(
g
,
args
,
i
)));
SetFloat
(
bvp
,
atof
(
MakePSZ
(
g
,
args
,
i
)));
break
;
break
;
case
TIME_RESULT
:
case
TIME_RESULT
:
case
ROW_RESULT
:
case
ROW_RESULT
:
default:
default:
bvp
->
Type
=
TYPE_UNKNOWN
;
bvp
->
Type
=
TYPE_UNKNOWN
;
break
;
break
;
}
// endswitch arg_type
}
// endswitch arg_type
}
// endif sap
}
// endif sap
return
bvp
;
return
bvp
;
}
// end of MakeBinValue
}
// end of MakeBinValue
/*********************************************************************************/
/* Try making a JSON value of the passed type from the passed argument. */
/*********************************************************************************/
PBVAL
BJNX
::
MakeTypedValue
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
uint
i
,
JTYP
type
,
PBVAL
*
top
)
{
char
*
sap
;
PBVAL
jsp
;
PBVAL
jvp
=
MakeValue
(
g
,
args
,
i
,
top
);
//if (type == TYPE_JSON) {
// if (jvp->GetValType() >= TYPE_JSON)
// return jvp;
//} else if (jvp->GetValType() == type)
// return jvp;
if
(
jvp
->
Type
==
TYPE_STRG
)
{
sap
=
GetString
(
jvp
);
if
((
jsp
=
ParseJson
(
g
,
sap
,
strlen
(
sap
))))
{
if
((
type
==
TYPE_JSON
&&
jsp
->
Type
!=
TYPE_JVAL
)
||
jsp
->
Type
==
type
)
{
if
(
top
)
*
top
=
jvp
;
SetValueVal
(
jvp
,
jsp
);
}
// endif Type
}
// endif jsp
}
// endif Type
return
jvp
;
}
// end of MakeTypedValue
/*********************************************************************************/
/* Parse a json file. */
/*********************************************************************************/
PBVAL
BJNX
::
ParseJsonFile
(
PGLOBAL
g
,
char
*
fn
,
int
&
pty
,
size_t
&
len
)
{
char
*
memory
;
HANDLE
hFile
;
MEMMAP
mm
;
PBVAL
jsp
;
// Create the mapping file object
hFile
=
CreateFileMap
(
g
,
fn
,
&
mm
,
MODE_READ
,
false
);
if
(
hFile
==
INVALID_HANDLE_VALUE
)
{
DWORD
rc
=
GetLastError
();
if
(
!
(
*
g
->
Message
))
sprintf
(
g
->
Message
,
MSG
(
OPEN_MODE_ERROR
),
"map"
,
(
int
)
rc
,
fn
);
return
NULL
;
}
// endif hFile
// Get the file size
len
=
(
size_t
)
mm
.
lenL
;
if
(
mm
.
lenH
)
len
+=
((
size_t
)
mm
.
lenH
*
0x000000001LL
);
memory
=
(
char
*
)
mm
.
memory
;
if
(
!
len
)
{
// Empty or deleted file
CloseFileHandle
(
hFile
);
return
NULL
;
}
// endif len
if
(
!
memory
)
{
CloseFileHandle
(
hFile
);
sprintf
(
g
->
Message
,
MSG
(
MAP_VIEW_ERROR
),
fn
,
GetLastError
());
return
NULL
;
}
// endif Memory
CloseFileHandle
(
hFile
);
// Not used anymore
// Parse the json file and allocate its tree structure
g
->
Message
[
0
]
=
0
;
jsp
=
ParseJson
(
g
,
memory
,
len
);
pty
=
pretty
;
CloseMemMap
(
memory
,
len
);
return
jsp
;
}
// end of ParseJsonFile
/* -----------------------------Utility functions ------------------------------ */
/*********************************************************************************/
/* GetMemPtr: returns the memory pointer used by this argument. */
/*********************************************************************************/
static
PGLOBAL
GetMemPtr
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
uint
i
)
{
return
(
IsArgJson
(
args
,
i
)
==
3
)
?
((
PBSON
)
args
->
args
[
i
])
->
G
:
g
;
}
// end of GetMemPtr
/*********************************************************************************/
/* Returns a pointer to the first integer argument found from the nth argument. */
/*********************************************************************************/
static
int
*
GetIntArgPtr
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
uint
&
n
)
{
int
*
x
=
NULL
;
for
(
uint
i
=
n
;
i
<
args
->
arg_count
;
i
++
)
if
(
args
->
arg_type
[
i
]
==
INT_RESULT
)
{
if
(
args
->
args
[
i
])
{
if
((
x
=
(
int
*
)
PlgDBSubAlloc
(
g
,
NULL
,
sizeof
(
int
))))
*
x
=
(
int
)
*
(
longlong
*
)
args
->
args
[
i
];
else
PUSH_WARNING
(
g
->
Message
);
}
// endif args
n
=
i
+
1
;
break
;
}
// endif arg_type
return
x
;
}
// end of GetIntArgPtr
/*********************************************************************************/
/* Returns not 0 if the argument is a JSON item or file name. */
/*********************************************************************************/
int
IsArgJson
(
UDF_ARGS
*
args
,
uint
i
)
{
int
n
=
0
;
if
(
i
>=
args
->
arg_count
||
args
->
arg_type
[
i
]
!=
STRING_RESULT
)
{
}
else
if
(
!
strnicmp
(
args
->
attributes
[
i
],
"Bson_"
,
5
)
||
!
strnicmp
(
args
->
attributes
[
i
],
"Json_"
,
5
))
{
if
(
!
args
->
args
[
i
]
||
strchr
(
"[{
\t\r\n
"
,
*
args
->
args
[
i
]))
n
=
1
;
// arg should be is a json item
else
n
=
2
;
// A file name may have been returned
}
else
if
(
!
strnicmp
(
args
->
attributes
[
i
],
"Bbin_"
,
5
))
{
if
(
args
->
lengths
[
i
]
==
sizeof
(
BSON
))
n
=
3
;
// arg is a binary json item
else
n
=
2
;
// A file name may have been returned
}
else
if
(
!
strnicmp
(
args
->
attributes
[
i
],
"Bfile_"
,
6
)
||
!
strnicmp
(
args
->
attributes
[
i
],
"Jfile_"
,
6
))
{
n
=
2
;
// arg is a json file name
#if 0
} else if (args->lengths[i]) {
PGLOBAL g = PlugInit(NULL, (size_t)args->lengths[i] * M + 1024);
char *sap = MakePSZ(g, args, i);
if (ParseJson(g, sap, strlen(sap)))
n = 4;
JsonFreeMem(g);
#endif // 0
}
// endif's
return
n
;
}
// end of IsArgJson
/*********************************************************************************/
/* Make the result according to the first argument type. */
/*********************************************************************************/
static
char
*
MakeResult
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
PBVAL
top
,
uint
n
=
2
)
{
char
*
str
=
NULL
;
BDOC
doc
(
g
);
if
(
IsArgJson
(
args
,
0
)
==
2
)
{
// Make the change in the json file
int
pretty
=
2
;
for
(
uint
i
=
n
;
i
<
args
->
arg_count
;
i
++
)
if
(
args
->
arg_type
[
i
]
==
INT_RESULT
)
{
pretty
=
(
int
)
*
(
longlong
*
)
args
->
args
[
i
];
break
;
}
// endif type
if
(
!
doc
.
Serialize
(
g
,
top
,
MakePSZ
(
g
,
args
,
0
),
pretty
))
PUSH_WARNING
(
g
->
Message
);
str
=
NULL
;
}
else
if
(
IsArgJson
(
args
,
0
)
==
3
)
{
#if 0
PBSON bsp = (PBSON)args->args[0];
if (bsp->Filename) {
// Make the change in the json file
if (!Serialize(g, top, bsp->Filename, bsp->Pretty))
PUSH_WARNING(g->Message);
str = bsp->Filename;
} else if (!(str = Serialize(g, top, NULL, 0)))
PUSH_WARNING(g->Message);
SetChanged(bsp);
#endif
}
else
if
(
!
(
str
=
doc
.
Serialize
(
g
,
top
,
NULL
,
0
)))
PUSH_WARNING
(
g
->
Message
);
return
str
;
}
// end of MakeResult
/*********************************************************************************/
/* GetFileLength: returns file size in number of bytes. */
/*********************************************************************************/
static
long
GetFileLength
(
char
*
fn
)
{
int
h
;
long
len
;
h
=
open
(
fn
,
_O_RDONLY
);
if
(
h
!=
-
1
)
{
if
((
len
=
_filelength
(
h
))
<
0
)
len
=
0
;
close
(
h
);
}
else
len
=
0
;
return
len
;
}
// end of GetFileLength
/* ------------------------- Now the new Bin UDF's ----------------------------- */
/* ------------------------- Now the new Bin UDF's ----------------------------- */
/*********************************************************************************/
/*********************************************************************************/
...
@@ -1249,10 +1648,10 @@ char* bsonvalue(UDF_INIT* initid, UDF_ARGS* args, char* result,
...
@@ -1249,10 +1648,10 @@ char* bsonvalue(UDF_INIT* initid, UDF_ARGS* args, char* result,
if
(
!
g
->
Xchk
)
{
if
(
!
g
->
Xchk
)
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
1
,
false
))
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
1
,
false
))
{
B
DOC
doc
(
g
);
B
JNX
bnx
(
g
);
PBVAL
bvp
=
MakeBinValue
(
g
,
args
,
0
);
PBVAL
bvp
=
bnx
.
MakeBinValue
(
g
,
args
,
0
);
if
(
!
(
str
=
doc
.
Serialize
(
g
,
bvp
,
NULL
,
0
)))
if
(
!
(
str
=
bnx
.
Serialize
(
g
,
bvp
,
NULL
,
0
)))
str
=
strcpy
(
result
,
g
->
Message
);
str
=
strcpy
(
result
,
g
->
Message
);
}
else
}
else
...
@@ -1290,13 +1689,13 @@ char* bson_make_array(UDF_INIT* initid, UDF_ARGS* args, char* result,
...
@@ -1290,13 +1689,13 @@ char* bson_make_array(UDF_INIT* initid, UDF_ARGS* args, char* result,
if
(
!
g
->
Xchk
)
{
if
(
!
g
->
Xchk
)
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
args
->
arg_count
,
false
))
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
args
->
arg_count
,
false
))
{
B
DOC
doc
(
g
);
B
JNX
bnx
(
g
);
PBVAL
bvp
=
NULL
,
arp
=
doc
.
NewVal
(
TYPE_JAR
);
PBVAL
bvp
=
NULL
,
arp
=
bnx
.
NewVal
(
TYPE_JAR
);
for
(
uint
i
=
0
;
i
<
args
->
arg_count
;
i
++
)
for
(
uint
i
=
0
;
i
<
args
->
arg_count
;
i
++
)
doc
.
AddArrayValue
(
arp
,
MakeBinValue
(
g
,
args
,
i
));
bnx
.
AddArrayValue
(
arp
,
bnx
.
MakeBinValue
(
g
,
args
,
i
));
if
(
!
(
str
=
doc
.
Serialize
(
g
,
arp
,
NULL
,
0
)))
if
(
!
(
str
=
bnx
.
Serialize
(
g
,
arp
,
NULL
,
0
)))
str
=
strcpy
(
result
,
g
->
Message
);
str
=
strcpy
(
result
,
g
->
Message
);
}
else
}
else
...
@@ -1324,7 +1723,7 @@ my_bool bson_array_add_values_init(UDF_INIT* initid, UDF_ARGS* args, char* messa
...
@@ -1324,7 +1723,7 @@ my_bool bson_array_add_values_init(UDF_INIT* initid, UDF_ARGS* args, char* messa
if
(
args
->
arg_count
<
2
)
{
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"This function must have at least 2 arguments"
);
strcpy
(
message
,
"This function must have at least 2 arguments"
);
return
true
;
return
true
;
//} else if (!IsJson(args, 0, true)) {
//} else if (!Is
Arg
Json(args, 0, true)) {
// strcpy(message, "First argument must be a valid json string or item");
// strcpy(message, "First argument must be a valid json string or item");
// return true;
// return true;
}
else
}
else
...
@@ -1337,7 +1736,7 @@ my_bool bson_array_add_values_init(UDF_INIT* initid, UDF_ARGS* args, char* messa
...
@@ -1337,7 +1736,7 @@ my_bool bson_array_add_values_init(UDF_INIT* initid, UDF_ARGS* args, char* messa
g
->
N
=
(
initid
->
const_item
)
?
1
:
0
;
g
->
N
=
(
initid
->
const_item
)
?
1
:
0
;
// This is to avoid double execution when using prepared statements
// This is to avoid double execution when using prepared statements
if
(
IsJson
(
args
,
0
)
>
1
)
if
(
Is
Arg
Json
(
args
,
0
)
>
1
)
initid
->
const_item
=
0
;
initid
->
const_item
=
0
;
return
false
;
return
false
;
...
@@ -1354,19 +1753,19 @@ char* bson_array_add_values(UDF_INIT* initid, UDF_ARGS* args, char* result,
...
@@ -1354,19 +1753,19 @@ char* bson_array_add_values(UDF_INIT* initid, UDF_ARGS* args, char* result,
if
(
!
g
->
Xchk
)
{
if
(
!
g
->
Xchk
)
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
args
->
arg_count
,
true
))
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
args
->
arg_count
,
true
))
{
uint
i
=
0
;
uint
i
=
0
;
B
DOC
doc
(
g
);
B
JNX
bnx
(
g
);
PBVAL
arp
,
bvp
=
MakeBinValue
(
g
,
args
,
0
);
PBVAL
arp
,
bvp
=
bnx
.
MakeBinValue
(
g
,
args
,
0
);
if
(
bvp
->
Type
==
TYPE_JAR
)
{
if
(
bvp
->
Type
==
TYPE_JAR
)
{
arp
=
bvp
;
arp
=
bvp
;
i
=
1
;
i
=
1
;
}
else
// First argument is not an array
}
else
// First argument is not an array
arp
=
doc
.
NewVal
(
TYPE_JAR
);
arp
=
bnx
.
NewVal
(
TYPE_JAR
);
for
(;
i
<
args
->
arg_count
;
i
++
)
for
(;
i
<
args
->
arg_count
;
i
++
)
doc
.
AddArrayValue
(
arp
,
MakeBinValue
(
g
,
args
,
i
));
bnx
.
AddArrayValue
(
arp
,
bnx
.
MakeBinValue
(
g
,
args
,
i
));
str
=
doc
.
Serialize
(
g
,
arp
,
NULL
,
0
);
str
=
bnx
.
Serialize
(
g
,
arp
,
NULL
,
0
);
}
// endif CheckMemory
}
// endif CheckMemory
if
(
!
str
)
{
if
(
!
str
)
{
...
@@ -1393,318 +1792,2436 @@ void bson_array_add_values_deinit(UDF_INIT* initid) {
...
@@ -1393,318 +1792,2436 @@ void bson_array_add_values_deinit(UDF_INIT* initid) {
}
// end of bson_array_add_values_deinit
}
// end of bson_array_add_values_deinit
/*********************************************************************************/
/*********************************************************************************/
/*
Test BJSON parse and serialize.
*/
/*
Add one value to a Json array.
*/
/*********************************************************************************/
/*********************************************************************************/
my_bool
bson_test_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
my_bool
bson_array_add_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
unsigned
long
reslen
,
memlen
,
more
=
1000
;
{
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
==
0
)
{
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"At least 1 argument required (json)"
);
strcpy
(
message
,
"This function must have at least 2 arguments"
);
return
true
;
}
else
if
(
!
IsJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
return
true
;
//} else if (!IsArgJson(args, 0, true)) {
// strcpy(message, "First argument is not a valid Json item");
// return true;
}
else
}
else
CalcLen
(
args
,
false
,
reslen
,
memlen
);
CalcLen
(
args
,
false
,
reslen
,
memlen
,
true
);
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
if
(
!
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
))
{
}
// end of bson_test_init
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
// This is a constant function
g
->
N
=
(
initid
->
const_item
)
?
1
:
0
;
// This is to avoid double execution when using prepared statements
if
(
IsArgJson
(
args
,
0
)
>
1
)
initid
->
const_item
=
0
;
return
false
;
}
else
return
true
;
}
// end of bson_array_add_init
char
*
bson_array_add
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
Xchk
)
{
// This constant function was recalled
str
=
(
char
*
)
g
->
Xchk
;
goto
fin
;
}
// endif Xchk
if
(
!
CheckMemory
(
g
,
initid
,
args
,
2
,
false
,
false
,
true
))
{
int
*
x
;
uint
n
=
2
;
BJNX
bnx
(
g
,
NULL
,
TYPE_STRING
);
PBVAL
jsp
,
top
;
PBVAL
arp
,
jvp
=
bnx
.
MakeTypedValue
(
g
,
args
,
0
,
TYPE_JAR
,
&
top
);
jsp
=
jvp
;
x
=
GetIntArgPtr
(
g
,
args
,
n
);
if
(
bnx
.
CheckPath
(
g
,
args
,
jsp
,
jvp
,
2
))
PUSH_WARNING
(
g
->
Message
);
else
if
(
jvp
)
{
PGLOBAL
gb
=
GetMemPtr
(
g
,
args
,
0
);
if
(
jvp
->
Type
!=
TYPE_JAR
)
{
if
((
arp
=
bnx
.
NewVal
(
TYPE_JAR
)))
{
bnx
.
AddArrayValue
(
arp
,
jvp
);
if
(
!
top
)
top
=
arp
;
}
// endif arp
}
else
arp
=
jvp
;
if
(
arp
)
{
bnx
.
AddArrayValue
(
arp
,
bnx
.
MakeValue
(
gb
,
args
,
1
),
x
);
str
=
MakeResult
(
g
,
args
,
top
,
n
);
}
else
PUSH_WARNING
(
gb
->
Message
);
}
else
{
PUSH_WARNING
(
"Target is not an array"
);
// if (g->Mrr) *error = 1; (only if no path)
}
// endif jvp
}
// endif CheckMemory
// In case of error or file, return unchanged argument
if
(
!
str
)
str
=
MakePSZ
(
g
,
args
,
0
);
if
(
g
->
N
)
// Keep result of constant function
g
->
Xchk
=
str
;
fin:
if
(
!
str
)
{
*
res_length
=
0
;
*
is_null
=
1
;
*
error
=
1
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_array_add
void
bson_array_add_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_array_add_deinit
/*********************************************************************************/
/* Delete a value from a Json array. */
/*********************************************************************************/
my_bool
bson_array_delete_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"This function must have at least 2 arguments"
);
return
true
;
}
else
CalcLen
(
args
,
false
,
reslen
,
memlen
,
true
);
if
(
!
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
))
{
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
// This is a constant function
g
->
N
=
(
initid
->
const_item
)
?
1
:
0
;
// This is to avoid double execution when using prepared statements
if
(
IsJson
(
args
,
0
)
>
1
)
initid
->
const_item
=
0
;
return
false
;
}
else
return
true
;
}
// end of bson_array_delete_init
char
*
bson_array_delete
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
Xchk
)
{
// This constant function was recalled
str
=
(
char
*
)
g
->
Xchk
;
goto
fin
;
}
// endif Xchk
if
(
!
CheckMemory
(
g
,
initid
,
args
,
1
,
false
,
false
,
true
))
{
int
*
x
;
uint
n
=
1
;
BJNX
bnx
(
g
,
NULL
,
TYPE_STRING
);
PBVAL
arp
,
top
;
PBVAL
jvp
=
bnx
.
MakeTypedValue
(
g
,
args
,
0
,
TYPE_JSON
,
&
top
);
if
(
!
(
x
=
GetIntArgPtr
(
g
,
args
,
n
)))
PUSH_WARNING
(
"Missing or null array index"
);
else
if
(
bnx
.
CheckPath
(
g
,
args
,
jvp
,
arp
,
1
))
PUSH_WARNING
(
g
->
Message
);
else
if
(
arp
&&
arp
->
Type
==
TYPE_JAR
)
{
bnx
.
DeleteValue
(
arp
,
*
x
);
str
=
MakeResult
(
g
,
args
,
top
,
n
);
}
else
{
PUSH_WARNING
(
"First argument target is not an array"
);
// if (g->Mrr) *error = 1;
}
// endif jvp
}
// endif CheckMemory
// In case of error or file, return unchanged argument
if
(
!
str
)
str
=
MakePSZ
(
g
,
args
,
0
);
if
(
g
->
N
)
// Keep result of constant function
g
->
Xchk
=
str
;
fin:
if
(
!
str
)
{
*
is_null
=
1
;
*
error
=
1
;
*
res_length
=
0
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_array_delete
void
bson_array_delete_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_array_delete_deinit
/*********************************************************************************/
/* Make a Json Object containing all the parameters. */
/*********************************************************************************/
my_bool
bson_make_object_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
;
CalcLen
(
args
,
true
,
reslen
,
memlen
);
return
JsonInit
(
initid
,
args
,
message
,
false
,
reslen
,
memlen
);
}
// end of bson_make_object_init
char
*
bson_make_object
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
,
char
*
)
{
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
!
g
->
Xchk
)
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
args
->
arg_count
,
false
,
false
,
true
))
{
BJNX
bnx
(
g
);
PBVAL
objp
;
if
((
objp
=
bnx
.
NewVal
(
TYPE_JOB
)))
{
for
(
uint
i
=
0
;
i
<
args
->
arg_count
;
i
++
)
bnx
.
SetKeyValue
(
objp
,
bnx
.
MakeValue
(
g
,
args
,
i
),
bnx
.
MakeKey
(
args
,
i
));
str
=
bnx
.
Serialize
(
g
,
objp
,
NULL
,
0
);
}
// endif objp
}
// endif CheckMemory
if
(
!
str
)
str
=
strcpy
(
result
,
g
->
Message
);
// Keep result of constant function
g
->
Xchk
=
(
initid
->
const_item
)
?
str
:
NULL
;
}
else
str
=
(
char
*
)
g
->
Xchk
;
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_make_object
void
bson_make_object_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_make_object_deinit
/*********************************************************************************/
/* Make a Json Object containing all not null parameters. */
/*********************************************************************************/
my_bool
bson_object_nonull_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
;
CalcLen
(
args
,
true
,
reslen
,
memlen
);
return
JsonInit
(
initid
,
args
,
message
,
false
,
reslen
,
memlen
);
}
// end of bson_object_nonull_init
char
*
bson_object_nonull
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
,
char
*
)
{
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
!
g
->
Xchk
)
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
args
->
arg_count
,
false
,
true
))
{
BJNX
bnx
(
g
);
PBVAL
jvp
,
objp
;
if
((
objp
=
bnx
.
NewVal
(
TYPE_JOB
)))
{
for
(
uint
i
=
0
;
i
<
args
->
arg_count
;
i
++
)
if
(
!
bnx
.
IsValueNull
(
jvp
=
bnx
.
MakeValue
(
g
,
args
,
i
)))
bnx
.
SetKeyValue
(
objp
,
jvp
,
bnx
.
MakeKey
(
args
,
i
));
str
=
bnx
.
Serialize
(
g
,
objp
,
NULL
,
0
);
}
// endif objp
}
// endif CheckMemory
if
(
!
str
)
str
=
strcpy
(
result
,
g
->
Message
);
// Keep result of constant function
g
->
Xchk
=
(
initid
->
const_item
)
?
str
:
NULL
;
}
else
str
=
(
char
*
)
g
->
Xchk
;
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_object_nonull
void
bson_object_nonull_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_object_nonull_deinit
/*********************************************************************************/
/* Make a Json Object containing all the key/value parameters. */
/*********************************************************************************/
my_bool
bson_object_key_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
%
2
)
{
strcpy
(
message
,
"This function must have an even number of arguments"
);
return
true
;
}
// endif arg_count
CalcLen
(
args
,
true
,
reslen
,
memlen
);
return
JsonInit
(
initid
,
args
,
message
,
false
,
reslen
,
memlen
);
}
// end of bson_object_key_init
char
*
bson_object_key
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
,
char
*
)
{
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
!
g
->
Xchk
)
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
args
->
arg_count
,
false
,
true
))
{
BJNX
bnx
(
g
);
PBVAL
objp
;
if
((
objp
=
bnx
.
NewVal
(
TYPE_JOB
)))
{
for
(
uint
i
=
0
;
i
<
args
->
arg_count
;
i
+=
2
)
bnx
.
SetKeyValue
(
objp
,
bnx
.
MakeValue
(
g
,
args
,
i
+
1
),
MakePSZ
(
g
,
args
,
i
));
str
=
bnx
.
Serialize
(
g
,
objp
,
NULL
,
0
);
}
// endif objp
}
// endif CheckMemory
if
(
!
str
)
str
=
strcpy
(
result
,
g
->
Message
);
// Keep result of constant function
g
->
Xchk
=
(
initid
->
const_item
)
?
str
:
NULL
;
}
else
str
=
(
char
*
)
g
->
Xchk
;
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_object_key
void
bson_object_key_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_object_key_deinit
/*********************************************************************************/
/* Add or replace a value in a Json Object. */
/*********************************************************************************/
my_bool
bson_object_add_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"This function must have at least 2 arguments"
);
return
true
;
}
else
if
(
!
IsArgJson
(
args
,
0
))
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
CalcLen
(
args
,
true
,
reslen
,
memlen
,
true
);
if
(
!
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
))
{
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
// This is a constant function
g
->
N
=
(
initid
->
const_item
)
?
1
:
0
;
// This is to avoid double execution when using prepared statements
if
(
IsJson
(
args
,
0
)
>
1
)
initid
->
const_item
=
0
;
return
false
;
}
else
return
true
;
}
// end of bson_object_add_init
char
*
bson_object_add
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
PSZ
key
;
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
Xchk
)
{
// This constant function was recalled
str
=
(
char
*
)
g
->
Xchk
;
goto
fin
;
}
// endif Xchk
if
(
!
CheckMemory
(
g
,
initid
,
args
,
2
,
false
,
true
,
true
))
{
BJNX
bnx
(
g
,
NULL
,
TYPE_STRG
);
PBVAL
jvp
,
objp
;
PBVAL
jsp
,
top
;
jsp
=
bnx
.
MakeValue
(
g
,
args
,
0
,
&
top
);
if
(
bnx
.
CheckPath
(
g
,
args
,
jsp
,
jvp
,
2
))
PUSH_WARNING
(
g
->
Message
);
else
if
(
jvp
&&
jvp
->
Type
==
TYPE_JOB
)
{
objp
=
jvp
;
jvp
=
bnx
.
MakeValue
(
g
,
args
,
1
);
key
=
bnx
.
MakeKey
(
args
,
1
);
bnx
.
SetKeyValue
(
objp
,
jvp
,
key
);
str
=
MakeResult
(
g
,
args
,
top
);
}
else
{
PUSH_WARNING
(
"First argument target is not an object"
);
// if (g->Mrr) *error = 1; (only if no path)
}
// endif jvp
}
// endif CheckMemory
// In case of error or file, return unchanged argument
if
(
!
str
)
str
=
MakePSZ
(
g
,
args
,
0
);
if
(
g
->
N
)
// Keep result of constant function
g
->
Xchk
=
str
;
fin:
if
(
!
str
)
{
*
is_null
=
1
;
*
error
=
1
;
*
res_length
=
0
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_object_add
void
bson_object_add_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_object_add_deinit
/*********************************************************************************/
/* Delete a value from a Json object. */
/*********************************************************************************/
my_bool
bson_object_delete_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"This function must have 2 or 3 arguments"
);
return
true
;
}
else
if
(
!
IsArgJson
(
args
,
0
))
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
if
(
args
->
arg_type
[
1
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"Second argument must be a key string"
);
return
true
;
}
else
CalcLen
(
args
,
true
,
reslen
,
memlen
,
true
);
if
(
!
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
))
{
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
// This is a constant function
g
->
N
=
(
initid
->
const_item
)
?
1
:
0
;
// This is to avoid double execution when using prepared statements
if
(
IsJson
(
args
,
0
)
>
1
)
initid
->
const_item
=
0
;
return
false
;
}
else
return
true
;
}
// end of bson_object_delete_init
char
*
bson_object_delete
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
Xchk
)
{
// This constant function was recalled
str
=
(
char
*
)
g
->
Xchk
;
goto
fin
;
}
// endif Xchk
if
(
!
CheckMemory
(
g
,
initid
,
args
,
1
,
false
,
true
,
true
))
{
BJNX
bnx
(
g
,
NULL
,
TYPE_STRG
);
PSZ
key
;
PBVAL
jsp
,
objp
,
top
;
PBVAL
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
,
&
top
);
jsp
=
jvp
;
if
(
bnx
.
CheckPath
(
g
,
args
,
jsp
,
jvp
,
2
))
PUSH_WARNING
(
g
->
Message
);
else
if
(
jvp
&&
jvp
->
Type
==
TYPE_JOB
)
{
// key = MakeKey(GetMemPtr(g, args, 0), args, 1);
key
=
bnx
.
MakeKey
(
args
,
1
);
objp
=
jvp
;
bnx
.
DeleteKey
(
objp
,
key
);
str
=
MakeResult
(
g
,
args
,
top
);
}
else
{
PUSH_WARNING
(
"First argument target is not an object"
);
// if (g->Mrr) *error = 1; (only if no path)
}
// endif jvp
}
// endif CheckMemory
// In case of error or file, return unchanged argument
if
(
!
str
)
str
=
MakePSZ
(
g
,
args
,
0
);
if
(
g
->
N
)
// Keep result of constant function
g
->
Xchk
=
str
;
fin:
if
(
!
str
)
{
*
is_null
=
1
;
*
error
=
1
;
*
res_length
=
0
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_object_delete
void
bson_object_delete_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_object_delete_deinit
/*********************************************************************************/
/* Returns an array of the Json object keys. */
/*********************************************************************************/
my_bool
bson_object_list_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
!=
1
)
{
strcpy
(
message
,
"This function must have 1 argument"
);
return
true
;
}
else
if
(
!
IsArgJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"Argument must be a json item"
);
return
true
;
}
else
CalcLen
(
args
,
false
,
reslen
,
memlen
);
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
);
}
// end of bson_object_list_init
char
*
bson_object_list
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
!
g
->
N
)
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
1
,
true
,
true
))
{
BJNX
bnx
(
g
);
char
*
p
;
PBVAL
jsp
,
jarp
;
PBVAL
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
);
if
((
p
=
bnx
.
GetString
(
jvp
)))
{
if
(
!
(
jsp
=
bnx
.
ParseJson
(
g
,
p
,
strlen
(
p
))))
{
PUSH_WARNING
(
g
->
Message
);
return
NULL
;
}
// endif jsp
}
else
jsp
=
jvp
;
if
(
jsp
->
Type
==
TYPE_JOB
)
{
jarp
=
bnx
.
GetKeyList
(
jsp
);
if
(
!
(
str
=
bnx
.
Serialize
(
g
,
jarp
,
NULL
,
0
)))
PUSH_WARNING
(
g
->
Message
);
}
else
{
PUSH_WARNING
(
"First argument is not an object"
);
if
(
g
->
Mrr
)
*
error
=
1
;
}
// endif jvp
}
// endif CheckMemory
if
(
initid
->
const_item
)
{
// Keep result of constant function
g
->
Xchk
=
str
;
g
->
N
=
1
;
// str can be NULL
}
// endif const_item
}
else
str
=
(
char
*
)
g
->
Xchk
;
if
(
!
str
)
{
*
is_null
=
1
;
*
res_length
=
0
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_object_list
void
bson_object_list_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_object_list_deinit
/*********************************************************************************/
/* Returns an array of the Json object values. */
/*********************************************************************************/
my_bool
bson_object_values_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
!=
1
)
{
strcpy
(
message
,
"This function must have 1 argument"
);
return
true
;
}
else
if
(
!
IsJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"Argument must be a json object"
);
return
true
;
}
else
CalcLen
(
args
,
false
,
reslen
,
memlen
);
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
);
}
// end of bson_object_values_init
char
*
bson_object_values
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
!
g
->
N
)
{
if
(
!
CheckMemory
(
g
,
initid
,
args
,
1
,
true
,
true
))
{
BJNX
bnx
(
g
);
char
*
p
;
PBVAL
jsp
,
jarp
;
PBVAL
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
);
if
((
p
=
bnx
.
GetString
(
jvp
)))
{
if
(
!
(
jsp
=
bnx
.
ParseJson
(
g
,
p
,
strlen
(
p
))))
{
PUSH_WARNING
(
g
->
Message
);
return
NULL
;
}
// endif jsp
}
else
jsp
=
jvp
;
if
(
jsp
->
Type
==
TYPE_JOB
)
{
jarp
=
bnx
.
GetObjectValList
(
jsp
);
if
(
!
(
str
=
bnx
.
Serialize
(
g
,
jarp
,
NULL
,
0
)))
PUSH_WARNING
(
g
->
Message
);
}
else
{
PUSH_WARNING
(
"First argument is not an object"
);
if
(
g
->
Mrr
)
*
error
=
1
;
}
// endif jvp
}
// endif CheckMemory
if
(
initid
->
const_item
)
{
// Keep result of constant function
g
->
Xchk
=
str
;
g
->
N
=
1
;
// str can be NULL
}
// endif const_item
}
else
str
=
(
char
*
)
g
->
Xchk
;
if
(
!
str
)
{
*
is_null
=
1
;
*
res_length
=
0
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_object_values
void
bson_object_values_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_object_values_deinit
/*********************************************************************************/
/* Set the value of JsonGrpSize. */
/*********************************************************************************/
my_bool
bsonset_grp_size_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
if
(
args
->
arg_count
!=
1
||
args
->
arg_type
[
0
]
!=
INT_RESULT
)
{
strcpy
(
message
,
"This function must have 1 integer argument"
);
return
true
;
}
else
return
false
;
}
// end of bsonset_grp_size_init
long
long
bsonset_grp_size
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
,
char
*
)
{
long
long
n
=
*
(
long
long
*
)
args
->
args
[
0
];
JsonGrpSize
=
(
uint
)
n
;
return
(
long
long
)
GetJsonGroupSize
();
}
// end of bsonset_grp_size
/*********************************************************************************/
/* Get the value of JsonGrpSize. */
/*********************************************************************************/
my_bool
bsonget_grp_size_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
if
(
args
->
arg_count
!=
0
)
{
strcpy
(
message
,
"This function must have no arguments"
);
return
true
;
}
else
return
false
;
}
// end of bsonget_grp_size_init
long
long
bsonget_grp_size
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
,
char
*
)
{
return
(
long
long
)
GetJsonGroupSize
();
}
// end of bsonget_grp_size
/*********************************************************************************/
/* Make a Json array from values coming from rows. */
/*********************************************************************************/
my_bool
bson_array_grp_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
n
=
GetJsonGroupSize
();
if
(
args
->
arg_count
!=
1
)
{
strcpy
(
message
,
"This function can only accept 1 argument"
);
return
true
;
}
else
if
(
IsArgJson
(
args
,
0
)
==
3
)
{
strcpy
(
message
,
"This function does not support Jbin arguments"
);
return
true
;
}
else
CalcLen
(
args
,
false
,
reslen
,
memlen
);
reslen
*=
n
;
memlen
+=
((
memlen
-
MEMFIX
)
*
(
n
-
1
));
if
(
JsonInit
(
initid
,
args
,
message
,
false
,
reslen
,
memlen
))
return
true
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PBJNX
bxp
=
new
(
g
)
BJNX
(
g
);
JsonMemSave
(
g
);
return
false
;
}
// end of bson_array_grp_init
void
bson_array_grp_clear
(
UDF_INIT
*
initid
,
char
*
,
char
*
)
{
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PBJNX
bxp
=
(
PBJNX
)((
char
*
)
g
->
Sarea
+
sizeof
(
POOLHEADER
));
JsonSubSet
(
g
);
g
->
Activityp
=
(
PACTIVITY
)
bxp
->
NewVal
(
TYPE_JAR
);
g
->
N
=
GetJsonGroupSize
();
}
// end of bson_array_grp_clear
void
bson_array_grp_add
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
,
char
*
)
{
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PBJNX
bxp
=
(
PBJNX
)((
char
*
)
g
->
Sarea
+
sizeof
(
POOLHEADER
));
PBVAL
arp
=
(
PBVAL
)
g
->
Activityp
;
if
(
arp
&&
g
->
N
--
>
0
)
bxp
->
AddArrayValue
(
arp
,
bxp
->
MakeValue
(
g
,
args
,
0
));
}
// end of bson_array_grp_add
char
*
bson_array_grp
(
UDF_INIT
*
initid
,
UDF_ARGS
*
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
,
char
*
)
{
char
*
str
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PBJNX
bxp
=
(
PBJNX
)((
char
*
)
g
->
Sarea
+
sizeof
(
POOLHEADER
));
PBVAL
arp
=
(
PBVAL
)
g
->
Activityp
;
if
(
g
->
N
<
0
)
PUSH_WARNING
(
"Result truncated to json_grp_size values"
);
if
(
!
arp
||
!
(
str
=
bxp
->
Serialize
(
g
,
arp
,
NULL
,
0
)))
str
=
strcpy
(
result
,
g
->
Message
);
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_array_grp
void
bson_array_grp_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_array_grp_deinit
/*********************************************************************************/
/* Make a Json object from values coming from rows. */
/*********************************************************************************/
my_bool
bson_object_grp_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
n
=
GetJsonGroupSize
();
if
(
args
->
arg_count
!=
2
)
{
strcpy
(
message
,
"This function requires 2 arguments (key, value)"
);
return
true
;
}
else
if
(
IsJson
(
args
,
0
)
==
3
)
{
strcpy
(
message
,
"This function does not support Jbin arguments"
);
return
true
;
}
else
CalcLen
(
args
,
true
,
reslen
,
memlen
);
reslen
*=
n
;
memlen
+=
((
memlen
-
MEMFIX
)
*
(
n
-
1
));
if
(
JsonInit
(
initid
,
args
,
message
,
false
,
reslen
,
memlen
))
return
true
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PBJNX
bxp
=
new
(
g
)
BJNX
(
g
);
JsonMemSave
(
g
);
return
false
;
}
// end of bson_object_grp_init
void
bson_object_grp_clear
(
UDF_INIT
*
initid
,
char
*
,
char
*
)
{
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PBJNX
bxp
=
(
PBJNX
)((
char
*
)
g
->
Sarea
+
sizeof
(
POOLHEADER
));
JsonSubSet
(
g
);
g
->
Activityp
=
(
PACTIVITY
)
bxp
->
NewVal
(
TYPE_JOB
);
g
->
N
=
GetJsonGroupSize
();
}
// end of bson_object_grp_clear
void
bson_object_grp_add
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
,
char
*
)
{
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PBJNX
bxp
=
(
PBJNX
)((
char
*
)
g
->
Sarea
+
sizeof
(
POOLHEADER
));
PBVAL
bop
=
(
PBVAL
)
g
->
Activityp
;
if
(
g
->
N
--
>
0
)
bxp
->
SetKeyValue
(
bop
,
bxp
->
MakeValue
(
g
,
args
,
0
),
MakePSZ
(
g
,
args
,
1
));
}
// end of bson_object_grp_add
char
*
bson_object_grp
(
UDF_INIT
*
initid
,
UDF_ARGS
*
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
,
char
*
)
{
char
*
str
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PBJNX
bxp
=
(
PBJNX
)((
char
*
)
g
->
Sarea
+
sizeof
(
POOLHEADER
));
PBVAL
bop
=
(
PBVAL
)
g
->
Activityp
;
if
(
g
->
N
<
0
)
PUSH_WARNING
(
"Result truncated to json_grp_size values"
);
if
(
!
bop
||
!
(
str
=
bxp
->
Serialize
(
g
,
bop
,
NULL
,
0
)))
str
=
strcpy
(
result
,
g
->
Message
);
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_object_grp
void
bson_object_grp_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_object_grp_deinit
/*********************************************************************************/
/* Test BJSON parse and serialize. */
/*********************************************************************************/
my_bool
bson_test_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
=
1000
;
if
(
args
->
arg_count
==
0
)
{
strcpy
(
message
,
"At least 1 argument required (json)"
);
return
true
;
}
else
if
(
!
IsArgJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
CalcLen
(
args
,
false
,
reslen
,
memlen
);
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
}
// end of bson_test_init
char
*
bson_test
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
char
*
bson_test
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
str
=
NULL
,
*
sap
=
NULL
,
*
fn
=
NULL
;
char
*
str
=
NULL
,
*
sap
=
NULL
,
*
fn
=
NULL
;
int
pretty
=
1
;
int
pretty
=
1
;
PBVAL
bvp
;
PBVAL
bvp
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
N
)
{
str
=
(
char
*
)
g
->
Activityp
;
goto
err
;
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
try
{
BJNX
bnx
(
g
);
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
!
g
->
Xchk
))
{
PUSH_WARNING
(
"CheckMemory error"
);
*
error
=
1
;
goto
err
;
}
else
if
(
!
(
bvp
=
bnx
.
MakeBinValue
(
g
,
args
,
0
)))
{
PUSH_WARNING
(
g
->
Message
);
goto
err
;
}
// endif bvp
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
bvp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
else
bvp
=
(
PBVAL
)
g
->
Xchk
;
for
(
uint
i
=
1
;
i
<
args
->
arg_count
;
i
++
)
if
(
args
->
arg_type
[
i
]
==
STRING_RESULT
)
fn
=
args
->
args
[
i
];
else
if
(
args
->
arg_type
[
i
]
==
INT_RESULT
)
pretty
=
(
int
)
*
(
longlong
*
)
args
->
args
[
i
];
// Serialize the parse tree
str
=
bnx
.
Serialize
(
g
,
bvp
,
fn
,
pretty
);
if
(
initid
->
const_item
)
// Keep result of constant function
g
->
Activityp
=
(
PACTIVITY
)
str
;
}
catch
(
int
n
)
{
xtrc
(
1
,
"json_test_bson: error %d: %s
\n
"
,
n
,
g
->
Message
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
str
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
str
=
NULL
;
}
// end catch
err:
if
(
!
str
)
{
*
res_length
=
0
;
*
is_null
=
1
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_test
void
bson_test_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_test_deinit
/*********************************************************************************/
/* Locate a value in a Json tree. */
/*********************************************************************************/
my_bool
bsonlocate_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
=
1000
;
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"At least 2 arguments required"
);
return
true
;
}
else
if
(
!
IsArgJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
if
(
args
->
arg_count
>
2
&&
args
->
arg_type
[
2
]
!=
INT_RESULT
)
{
strcpy
(
message
,
"Third argument is not an integer (rank)"
);
return
true
;
}
// endifs args
CalcLen
(
args
,
false
,
reslen
,
memlen
);
// TODO: calculate this
if
(
IsArgJson
(
args
,
0
)
==
3
)
more
=
0
;
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
}
// end of bsonlocate_init
char
*
bsonlocate
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
path
=
NULL
;
int
k
;
PBVAL
bvp
,
bvp2
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
N
)
{
if
(
g
->
Activityp
)
{
path
=
(
char
*
)
g
->
Activityp
;
*
res_length
=
strlen
(
path
);
return
path
;
}
else
{
*
res_length
=
0
;
*
is_null
=
1
;
return
NULL
;
}
// endif Activityp
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
try
{
BJNX
bnx
(
g
);
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
!
g
->
Xchk
))
{
PUSH_WARNING
(
"CheckMemory error"
);
*
error
=
1
;
goto
err
;
}
else
bvp
=
bnx
.
MakeBinValue
(
g
,
args
,
0
);
if
(
!
bvp
)
{
PUSH_WARNING
(
"First argument is not a valid JSON item"
);
goto
err
;
}
// endif bvp
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
bvp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
else
bvp
=
(
PBVAL
)
g
->
Xchk
;
// The item to locate
if
(
!
(
bvp2
=
bnx
.
MakeBinValue
(
g
,
args
,
1
)))
{
PUSH_WARNING
(
"Invalid second argument"
);
goto
err
;
}
// endif bvp
k
=
(
args
->
arg_count
>
2
)
?
(
int
)
*
(
long
long
*
)
args
->
args
[
2
]
:
1
;
// bnxp = new(g) BJNX(g, bvp, TYPE_STRING);
path
=
bnx
.
Locate
(
g
,
bvp
,
bvp2
,
k
);
if
(
initid
->
const_item
)
// Keep result of constant function
g
->
Activityp
=
(
PACTIVITY
)
path
;
}
catch
(
int
n
)
{
xtrc
(
1
,
"Exception %d: %s
\n
"
,
n
,
g
->
Message
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
path
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
path
=
NULL
;
}
// end catch
err:
if
(
!
path
)
{
*
res_length
=
0
;
*
is_null
=
1
;
}
else
*
res_length
=
strlen
(
path
);
return
path
;
}
// end of bsonlocate
void
bsonlocate_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bsonlocate_deinit
/*********************************************************************************/
/* Locate all occurences of a value in a Json tree. */
/*********************************************************************************/
my_bool
bson_locate_all_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
=
1000
;
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"At least 2 arguments required"
);
return
true
;
}
else
if
(
!
IsArgJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
if
(
args
->
arg_count
>
2
&&
args
->
arg_type
[
2
]
!=
INT_RESULT
)
{
strcpy
(
message
,
"Third argument is not an integer (Depth)"
);
return
true
;
}
// endifs
CalcLen
(
args
,
false
,
reslen
,
memlen
);
// TODO: calculate this
if
(
IsArgJson
(
args
,
0
)
==
3
)
more
=
0
;
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
}
// end of bson_locate_all_init
char
*
bson_locate_all
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
path
=
NULL
;
int
mx
=
10
;
PBVAL
bvp
,
bvp2
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
N
)
{
if
(
g
->
Activityp
)
{
path
=
(
char
*
)
g
->
Activityp
;
*
res_length
=
strlen
(
path
);
return
path
;
}
else
{
*
error
=
1
;
*
res_length
=
0
;
*
is_null
=
1
;
return
NULL
;
}
// endif Activityp
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
try
{
BJNX
bnx
(
g
);
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
true
))
{
PUSH_WARNING
(
"CheckMemory error"
);
*
error
=
1
;
goto
err
;
}
else
bvp
=
bnx
.
MakeBinValue
(
g
,
args
,
0
);
if
(
!
bvp
)
{
PUSH_WARNING
(
"First argument is not a valid JSON item"
);
goto
err
;
}
// endif bvp
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
bvp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
else
bvp
=
(
PBVAL
)
g
->
Xchk
;
// The item to locate
if
(
!
(
bvp2
=
bnx
.
MakeBinValue
(
g
,
args
,
1
)))
{
PUSH_WARNING
(
"Invalid second argument"
);
goto
err
;
}
// endif bvp
if
(
args
->
arg_count
>
2
)
mx
=
(
int
)
*
(
long
long
*
)
args
->
args
[
2
];
// bnxp = new(g) BJNX(g, bvp, TYPE_STRING);
path
=
bnx
.
LocateAll
(
g
,
bvp
,
bvp2
,
mx
);
if
(
initid
->
const_item
)
// Keep result of constant function
g
->
Activityp
=
(
PACTIVITY
)
path
;
}
catch
(
int
n
)
{
xtrc
(
1
,
"Exception %d: %s
\n
"
,
n
,
g
->
Message
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
path
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
path
=
NULL
;
}
// end catch
err:
if
(
!
path
)
{
*
res_length
=
0
;
*
is_null
=
1
;
}
else
*
res_length
=
strlen
(
path
);
return
path
;
}
// end of bson_locate_all
void
bson_locate_all_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_locate_all_deinit
/*********************************************************************************/
/* Check whether the document contains a value or item. */
/*********************************************************************************/
my_bool
bson_contains_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
=
1024
;
int
n
=
IsArgJson
(
args
,
0
);
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"At least 2 arguments required"
);
return
true
;
}
else
if
(
!
n
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
if
(
args
->
arg_count
>
2
&&
args
->
arg_type
[
2
]
!=
INT_RESULT
)
{
strcpy
(
message
,
"Third argument is not an integer (index)"
);
return
true
;
}
else
if
(
args
->
arg_count
>
3
)
{
if
(
args
->
arg_type
[
3
]
==
INT_RESULT
&&
args
->
args
[
3
])
more
+=
(
unsigned
long
)
*
(
long
long
*
)
args
->
args
[
3
];
else
strcpy
(
message
,
"Fourth argument is not an integer (memory)"
);
}
// endif's
CalcLen
(
args
,
false
,
reslen
,
memlen
);
//memlen += more;
// TODO: calculate this
more
+=
(
IsJson
(
args
,
0
)
!=
3
?
1000
:
0
);
return
JsonInit
(
initid
,
args
,
message
,
false
,
reslen
,
memlen
,
more
);
}
// end of bson contains_init
long
long
bson_contains
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
,
char
*
error
)
{
char
isn
,
res
[
256
];
unsigned
long
reslen
;
isn
=
0
;
bsonlocate
(
initid
,
args
,
res
,
&
reslen
,
&
isn
,
error
);
return
(
isn
)
?
0LL
:
1LL
;
}
// end of bson_contains
void
bson_contains_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_contains_deinit
/*********************************************************************************/
/* Check whether the document contains a path. */
/*********************************************************************************/
my_bool
bsoncontains_path_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
=
1024
;
int
n
=
IsArgJson
(
args
,
0
);
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"At least 2 arguments required"
);
return
true
;
}
else
if
(
!
n
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
if
(
args
->
arg_type
[
1
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"Second argument is not a string (path)"
);
return
true
;
}
else
if
(
args
->
arg_count
>
2
)
{
if
(
args
->
arg_type
[
2
]
==
INT_RESULT
&&
args
->
args
[
2
])
more
+=
(
unsigned
long
)
*
(
long
long
*
)
args
->
args
[
2
];
else
strcpy
(
message
,
"Third argument is not an integer (memory)"
);
}
// endif's
CalcLen
(
args
,
false
,
reslen
,
memlen
);
//memlen += more;
// TODO: calculate this
more
+=
(
IsJson
(
args
,
0
)
!=
3
?
1000
:
0
);
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
}
// end of bsoncontains_path_init
long
long
bsoncontains_path
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
,
char
*
error
)
{
char
*
p
,
*
path
;
long
long
n
;
PBVAL
jsp
;
PBVAL
jvp
;
PBJNX
bxp
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
N
)
{
if
(
!
g
->
Activityp
)
{
return
0LL
;
}
else
return
*
(
long
long
*
)
g
->
Activityp
;
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
true
))
{
PUSH_WARNING
(
"CheckMemory error"
);
goto
err
;
}
else
{
BJNX
bnx
(
g
);
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
);
if
((
p
=
bnx
.
GetString
(
jvp
)))
{
if
(
!
(
jsp
=
bnx
.
ParseJson
(
g
,
p
,
strlen
(
p
))))
{
PUSH_WARNING
(
g
->
Message
);
goto
err
;
}
// endif jsp
}
else
jsp
=
jvp
;
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
jsp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
// endelse CheckMemory
}
else
jsp
=
(
PBVAL
)
g
->
Xchk
;
bxp
=
new
(
g
)
BJNX
(
g
,
jsp
,
TYPE_BIGINT
);
path
=
MakePSZ
(
g
,
args
,
1
);
if
(
bxp
->
SetJpath
(
g
,
path
))
{
PUSH_WARNING
(
g
->
Message
);
goto
err
;
}
// endif SetJpath
n
=
(
bxp
->
CheckPath
(
g
))
?
1LL
:
0LL
;
if
(
initid
->
const_item
)
{
// Keep result of constant function
long
long
*
np
=
(
long
long
*
)
PlgDBSubAlloc
(
g
,
NULL
,
sizeof
(
long
long
));
if
(
np
)
{
*
np
=
n
;
g
->
Activityp
=
(
PACTIVITY
)
np
;
}
else
PUSH_WARNING
(
g
->
Message
);
}
// endif const_item
return
n
;
err:
if
(
g
->
Mrr
)
*
error
=
1
;
return
0LL
;
}
// end of bsoncontains_path
void
bsoncontains_path_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bsoncontains_path_deinit
/*********************************************************************************/
/* Merge two arrays or objects. */
/*********************************************************************************/
my_bool
bson_item_merge_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"This function must have at least 2 arguments"
);
return
true
;
}
else
for
(
int
i
=
0
;
i
<
2
;
i
++
)
if
(
!
IsArgJson
(
args
,
i
)
&&
args
->
arg_type
[
i
]
!=
STRING_RESULT
)
{
sprintf
(
message
,
"Argument %d must be a json item"
,
i
);
return
true
;
}
// endif type
CalcLen
(
args
,
false
,
reslen
,
memlen
,
true
);
if
(
!
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
))
{
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
// This is a constant function
g
->
N
=
(
initid
->
const_item
)
?
1
:
0
;
// This is to avoid double execution when using prepared statements
if
(
IsArgJson
(
args
,
0
)
>
1
)
initid
->
const_item
=
0
;
return
false
;
}
else
return
true
;
}
// end of bson_item_merge_init
char
*
bson_item_merge
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
Xchk
)
{
// This constant function was recalled
str
=
(
char
*
)
g
->
Xchk
;
goto
fin
;
}
// endif Xchk
if
(
!
CheckMemory
(
g
,
initid
,
args
,
2
,
false
,
false
,
true
))
{
JTYP
type
;
BJNX
bnx
(
g
);
PBVAL
jvp
,
top
=
NULL
;
PBVAL
jsp
[
2
]
=
{
NULL
,
NULL
};
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
jvp
=
bnx
.
MakeBinValue
(
g
,
args
,
i
);
if
(
i
)
{
if
(
jvp
->
Type
!=
type
)
{
PUSH_WARNING
(
"Argument types mismatch"
);
goto
fin
;
}
// endif type
}
else
{
type
=
(
JTYP
)
jvp
->
Type
;
if
(
type
!=
TYPE_JAR
&&
type
!=
TYPE_JOB
)
{
PUSH_WARNING
(
"First argument is not an array or object"
);
goto
fin
;
}
else
top
=
jvp
;
}
// endif i
jsp
[
i
]
=
jvp
;
}
// endfor i
if
(
type
==
TYPE_JAR
)
bnx
.
MergeArray
(
jsp
[
0
],
jsp
[
1
]);
else
bnx
.
MergeObject
(
jsp
[
0
],
jsp
[
1
]);
str
=
MakeResult
(
g
,
args
,
top
);
}
// endif CheckMemory
// In case of error or file, return unchanged first argument
if
(
!
str
)
str
=
MakePSZ
(
g
,
args
,
0
);
if
(
g
->
N
)
// Keep result of constant function
g
->
Xchk
=
str
;
fin:
if
(
!
str
)
{
*
res_length
=
0
;
*
error
=
1
;
*
is_null
=
1
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_item_merge
void
bson_item_merge_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_item_merge_deinit
/*********************************************************************************/
/* Get a Json item from a Json document. */
/*********************************************************************************/
my_bool
bson_get_item_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
;
int
n
=
IsArgJson
(
args
,
0
);
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"This function must have at least 2 arguments"
);
return
true
;
}
else
if
(
!
n
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
if
(
args
->
arg_type
[
1
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"Second argument is not a string (jpath)"
);
return
true
;
}
else
CalcLen
(
args
,
false
,
reslen
,
memlen
);
if
(
n
==
2
&&
args
->
args
[
0
])
{
char
fn
[
_MAX_PATH
];
long
fl
;
memcpy
(
fn
,
args
->
args
[
0
],
args
->
lengths
[
0
]);
fn
[
args
->
lengths
[
0
]]
=
0
;
fl
=
GetFileLength
(
fn
);
more
=
fl
*
3
;
}
else
if
(
n
!=
3
)
{
more
=
args
->
lengths
[
0
]
*
3
;
}
else
more
=
0
;
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
}
// end of bson_get_item_init
char
*
bson_get_item
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
)
{
char
*
p
,
*
path
,
*
str
=
NULL
;
PBVAL
jsp
,
jvp
;
PBJNX
bxp
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
N
)
{
str
=
(
char
*
)
g
->
Activityp
;
goto
fin
;
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
true
,
true
))
{
PUSH_WARNING
(
"CheckMemory error"
);
goto
fin
;
}
else
{
BJNX
bnx
(
g
);
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
);
if
((
p
=
bnx
.
GetString
(
jvp
)))
{
if
(
!
(
jsp
=
bnx
.
ParseJson
(
g
,
p
,
strlen
(
p
))))
{
PUSH_WARNING
(
g
->
Message
);
goto
fin
;
}
// endif jsp
}
else
jsp
=
jvp
;
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
jsp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
// endelse CheckMemory
}
else
jsp
=
(
PBVAL
)
g
->
Xchk
;
path
=
MakePSZ
(
g
,
args
,
1
);
bxp
=
new
(
g
)
BJNX
(
g
,
jsp
,
TYPE_STRING
,
initid
->
max_length
);
if
(
bxp
->
SetJpath
(
g
,
path
,
true
))
{
PUSH_WARNING
(
g
->
Message
);
goto
fin
;
}
else
bxp
->
ReadValue
(
g
);
if
(
!
bxp
->
GetValue
()
->
IsNull
())
str
=
bxp
->
GetValue
()
->
GetCharValue
();
if
(
initid
->
const_item
)
// Keep result of constant function
g
->
Activityp
=
(
PACTIVITY
)
str
;
fin:
if
(
!
str
)
{
*
is_null
=
1
;
*
res_length
=
0
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_get_item
void
bson_get_item_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_get_item_deinit
/*********************************************************************************/
/* Get a string value from a Json item. */
/*********************************************************************************/
my_bool
bsonget_string_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
=
1024
;
int
n
=
IsArgJson
(
args
,
0
);
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"At least 2 arguments required"
);
return
true
;
}
else
if
(
!
n
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
if
(
args
->
arg_type
[
1
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"Second argument is not a string (jpath)"
);
return
true
;
}
else
if
(
args
->
arg_count
>
2
)
{
if
(
args
->
arg_type
[
2
]
==
INT_RESULT
&&
args
->
args
[
2
])
more
+=
(
unsigned
long
)
*
(
long
long
*
)
args
->
args
[
2
];
else
strcpy
(
message
,
"Third argument is not an integer (memory)"
);
}
// endif's
CalcLen
(
args
,
false
,
reslen
,
memlen
);
//memlen += more;
if
(
n
==
2
&&
args
->
args
[
0
])
{
char
fn
[
_MAX_PATH
];
long
fl
;
memcpy
(
fn
,
args
->
args
[
0
],
args
->
lengths
[
0
]);
fn
[
args
->
lengths
[
0
]]
=
0
;
fl
=
GetFileLength
(
fn
);
more
+=
fl
*
3
;
}
else
if
(
n
!=
3
)
more
+=
args
->
lengths
[
0
]
*
3
;
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
}
// end of bsonget_string_init
char
*
bsonget_string
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
)
{
char
*
p
,
*
path
,
*
str
=
NULL
;
PBVAL
jsp
,
jvp
;
PBJNX
bxp
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
N
)
{
str
=
(
char
*
)
g
->
Activityp
;
goto
err
;
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
try
{
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
true
))
{
PUSH_WARNING
(
"CheckMemory error"
);
goto
err
;
}
else
{
BJNX
bnx
(
g
);
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
);
if
((
p
=
bnx
.
GetString
(
jvp
)))
{
if
(
!
(
jsp
=
bnx
.
ParseJson
(
g
,
p
,
strlen
(
p
))))
{
PUSH_WARNING
(
g
->
Message
);
goto
err
;
}
// endif jsp
}
else
jsp
=
jvp
;
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
jsp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
// endelse CheckMemory
}
else
jsp
=
(
PBVAL
)
g
->
Xchk
;
path
=
MakePSZ
(
g
,
args
,
1
);
bxp
=
new
(
g
)
BJNX
(
g
,
jsp
,
TYPE_STRING
,
initid
->
max_length
);
if
(
bxp
->
SetJpath
(
g
,
path
))
{
PUSH_WARNING
(
g
->
Message
);
goto
err
;
}
else
bxp
->
ReadValue
(
g
);
if
(
!
bxp
->
GetValue
()
->
IsNull
())
str
=
bxp
->
GetValue
()
->
GetCharValue
();
if
(
initid
->
const_item
)
// Keep result of constant function
g
->
Activityp
=
(
PACTIVITY
)
str
;
}
catch
(
int
n
)
{
if
(
trace
(
1
))
htrc
(
"Exception %d: %s
\n
"
,
n
,
g
->
Message
);
PUSH_WARNING
(
g
->
Message
);
str
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
PUSH_WARNING
(
g
->
Message
);
str
=
NULL
;
}
// end catch
err:
if
(
!
str
)
{
*
is_null
=
1
;
*
res_length
=
0
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bsonget_string
void
bsonget_string_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bsonget_string_deinit
/*********************************************************************************/
/* Get an integer value from a Json item. */
/*********************************************************************************/
my_bool
bsonget_int_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
;
if
(
args
->
arg_count
!=
2
)
{
strcpy
(
message
,
"This function must have 2 arguments"
);
return
true
;
}
else
if
(
!
IsArgJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
if
(
args
->
arg_type
[
1
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"Second argument is not a (jpath) string"
);
return
true
;
}
else
CalcLen
(
args
,
false
,
reslen
,
memlen
);
// TODO: calculate this
more
=
(
IsJson
(
args
,
0
)
!=
3
)
?
1000
:
0
;
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
}
// end of bsonget_int_init
long
long
bsonget_int
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
is_null
,
char
*
error
)
{
char
*
p
,
*
path
;
long
long
n
;
PBVAL
jsp
,
jvp
;
PBJNX
bxp
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
N
)
{
if
(
!
g
->
Activityp
)
{
*
is_null
=
1
;
return
0LL
;
}
else
return
*
(
long
long
*
)
g
->
Activityp
;
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
true
))
{
PUSH_WARNING
(
"CheckMemory error"
);
if
(
g
->
Mrr
)
*
error
=
1
;
*
is_null
=
1
;
return
0LL
;
}
else
{
BJNX
bnx
(
g
);
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
);
if
((
p
=
bnx
.
GetString
(
jvp
)))
{
if
(
!
(
jsp
=
bnx
.
ParseJson
(
g
,
p
,
strlen
(
p
))))
{
PUSH_WARNING
(
g
->
Message
);
if
(
g
->
Mrr
)
*
error
=
1
;
*
is_null
=
1
;
return
0
;
}
// endif jsp
}
else
jsp
=
jvp
;
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
jsp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
// endelse CheckMemory
}
else
jsp
=
(
PBVAL
)
g
->
Xchk
;
path
=
MakePSZ
(
g
,
args
,
1
);
bxp
=
new
(
g
)
BJNX
(
g
,
jsp
,
TYPE_BIGINT
);
if
(
bxp
->
SetJpath
(
g
,
path
))
{
PUSH_WARNING
(
g
->
Message
);
*
is_null
=
1
;
return
0
;
}
else
bxp
->
ReadValue
(
g
);
if
(
bxp
->
GetValue
()
->
IsNull
())
{
*
is_null
=
1
;
return
0
;
}
// endif IsNull
n
=
bxp
->
GetValue
()
->
GetBigintValue
();
if
(
initid
->
const_item
)
{
// Keep result of constant function
long
long
*
np
=
(
long
long
*
)
PlgDBSubAlloc
(
g
,
NULL
,
sizeof
(
long
long
));
if
(
np
)
{
*
np
=
n
;
g
->
Activityp
=
(
PACTIVITY
)
np
;
}
else
PUSH_WARNING
(
g
->
Message
);
}
// endif const_item
return
n
;
}
// end of bsonget_int
void
bsonget_int_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bsonget_int_deinit
/*********************************************************************************/
/* Get a double value from a Json item. */
/*********************************************************************************/
my_bool
bsonget_real_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
;
if
(
args
->
arg_count
<
2
)
{
strcpy
(
message
,
"At least 2 arguments required"
);
return
true
;
}
else
if
(
!
IsArgJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
if
(
args
->
arg_type
[
1
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"Second argument is not a (jpath) string"
);
return
true
;
}
else
if
(
args
->
arg_count
>
2
)
{
if
(
args
->
arg_type
[
2
]
!=
INT_RESULT
)
{
strcpy
(
message
,
"Third argument is not an integer (decimals)"
);
return
true
;
}
else
initid
->
decimals
=
(
uint
)
*
(
longlong
*
)
args
->
args
[
2
];
}
else
initid
->
decimals
=
15
;
CalcLen
(
args
,
false
,
reslen
,
memlen
);
// TODO: calculate this
more
=
(
IsJson
(
args
,
0
)
!=
3
)
?
1000
:
0
;
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
}
// end of bsonget_real_init
double
bsonget_real
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
is_null
,
char
*
error
)
{
char
*
p
,
*
path
;
double
d
;
PBVAL
jsp
,
jvp
;
PBJNX
bxp
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
N
)
{
if
(
!
g
->
Activityp
)
{
*
is_null
=
1
;
return
0.0
;
}
else
return
*
(
double
*
)
g
->
Activityp
;
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
true
))
{
PUSH_WARNING
(
"CheckMemory error"
);
if
(
g
->
Mrr
)
*
error
=
1
;
*
is_null
=
1
;
return
0.0
;
}
else
{
BJNX
bnx
(
g
);
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
);
if
((
p
=
bnx
.
GetString
(
jvp
)))
{
if
(
!
(
jsp
=
bnx
.
ParseJson
(
g
,
p
,
strlen
(
p
))))
{
PUSH_WARNING
(
g
->
Message
);
*
is_null
=
1
;
return
0.0
;
}
// endif jsp
}
else
jsp
=
jvp
;
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
jsp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
// endelse CheckMemory
}
else
jsp
=
(
PBVAL
)
g
->
Xchk
;
path
=
MakePSZ
(
g
,
args
,
1
);
bxp
=
new
(
g
)
BJNX
(
g
,
jsp
,
TYPE_DOUBLE
);
if
(
bxp
->
SetJpath
(
g
,
path
))
{
PUSH_WARNING
(
g
->
Message
);
*
is_null
=
1
;
return
0.0
;
}
else
bxp
->
ReadValue
(
g
);
if
(
bxp
->
GetValue
()
->
IsNull
())
{
*
is_null
=
1
;
return
0.0
;
}
// endif IsNull
d
=
bxp
->
GetValue
()
->
GetFloatValue
();
if
(
initid
->
const_item
)
{
// Keep result of constant function
double
*
dp
;
if
((
dp
=
(
double
*
)
PlgDBSubAlloc
(
g
,
NULL
,
sizeof
(
double
))))
{
*
dp
=
d
;
g
->
Activityp
=
(
PACTIVITY
)
dp
;
}
else
{
PUSH_WARNING
(
g
->
Message
);
*
is_null
=
1
;
return
0.0
;
}
// endif dp
}
// endif const_item
return
d
;
}
// end of jsonget_real
void
bsonget_real_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bsonget_real_deinit
/*********************************************************************************/
/* This function is used by the json_set/insert/update_item functions. */
/*********************************************************************************/
static
char
*
bson_handle_item
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
p
,
*
path
,
*
str
=
NULL
;
int
w
;
my_bool
b
=
true
;
PBJNX
bxp
;
PBVAL
jsp
,
jvp
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
//PGLOBAL gb = GetMemPtr(g, args, 0);
PGLOBAL
gb
=
g
;
if
(
g
->
Alchecked
)
{
str
=
(
char
*
)
g
->
Activityp
;
goto
fin
;
}
else
if
(
g
->
N
)
g
->
Alchecked
=
1
;
if
(
!
strcmp
(
result
,
"$set"
))
w
=
0
;
else
if
(
!
strcmp
(
result
,
"$insert"
))
w
=
1
;
else
if
(
!
strcmp
(
result
,
"$update"
))
w
=
2
;
else
{
PUSH_WARNING
(
"Logical error, please contact CONNECT developer"
);
goto
fin
;
}
// endelse
try
{
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
true
,
false
,
true
))
{
PUSH_WARNING
(
"CheckMemory error"
);
throw
1
;
}
else
{
BJNX
bnx
(
g
);
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
);
if
((
p
=
bnx
.
GetString
(
jvp
)))
{
if
(
!
(
jsp
=
bnx
.
ParseJson
(
g
,
p
,
strlen
(
p
))))
{
throw
2
;
}
// endif jsp
}
else
jsp
=
jvp
;
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
jsp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
// endelse CheckMemory
}
else
jsp
=
(
PBVAL
)
g
->
Xchk
;
bxp
=
new
(
g
)
BJNX
(
g
,
jsp
,
TYPE_STRING
,
initid
->
max_length
,
0
,
true
);
for
(
uint
i
=
1
;
i
+
1
<
args
->
arg_count
;
i
+=
2
)
{
jvp
=
bxp
->
MakeValue
(
gb
,
args
,
i
);
path
=
MakePSZ
(
g
,
args
,
i
+
1
);
if
(
bxp
->
SetJpath
(
g
,
path
,
false
))
{
PUSH_WARNING
(
g
->
Message
);
continue
;
}
// endif SetJpath
if
(
w
)
{
bxp
->
ReadValue
(
g
);
b
=
bxp
->
GetValue
()
->
IsNull
();
b
=
(
w
==
1
)
?
b
:
!
b
;
}
// endif w
if
(
b
&&
bxp
->
WriteValue
(
gb
,
jvp
))
PUSH_WARNING
(
g
->
Message
);
}
// endfor i
// In case of error or file, return unchanged argument
if
(
!
(
str
=
MakeResult
(
g
,
args
,
jsp
,
INT_MAX32
)))
str
=
MakePSZ
(
g
,
args
,
0
);
if
(
g
->
N
)
// Keep result of constant function
g
->
Activityp
=
(
PACTIVITY
)
str
;
}
catch
(
int
n
)
{
if
(
trace
(
1
))
htrc
(
"Exception %d: %s
\n
"
,
n
,
g
->
Message
);
PUSH_WARNING
(
g
->
Message
);
str
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
PUSH_WARNING
(
g
->
Message
);
str
=
NULL
;
}
// end catch
fin:
if
(
!
str
)
{
*
is_null
=
1
;
*
res_length
=
0
;
}
else
*
res_length
=
strlen
(
str
);
return
str
;
}
// end of bson_handle_item
/*********************************************************************************/
/* Set Json items of a Json document according to path. */
/*********************************************************************************/
my_bool
bson_set_item_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
=
0
;
int
n
=
IsArgJson
(
args
,
0
);
if
(
!
(
args
->
arg_count
%
2
))
{
strcpy
(
message
,
"This function must have an odd number of arguments"
);
return
true
;
}
else
if
(
!
n
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
}
else
CalcLen
(
args
,
false
,
reslen
,
memlen
);
if
(
n
==
2
&&
args
->
args
[
0
])
{
char
fn
[
_MAX_PATH
];
long
fl
;
memcpy
(
fn
,
args
->
args
[
0
],
args
->
lengths
[
0
]);
fn
[
args
->
lengths
[
0
]]
=
0
;
fl
=
GetFileLength
(
fn
);
more
+=
fl
*
3
;
}
else
if
(
n
!=
3
)
more
+=
args
->
lengths
[
0
]
*
3
;
if
(
!
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
))
{
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
// This is a constant function
g
->
N
=
(
initid
->
const_item
)
?
1
:
0
;
// This is to avoid double execution when using prepared statements
if
(
IsJson
(
args
,
0
)
>
1
)
initid
->
const_item
=
0
;
g
->
Alchecked
=
0
;
return
false
;
}
else
return
true
;
}
// end of bson_set_item_init
char
*
bson_set_item
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
p
)
{
strcpy
(
result
,
"$set"
);
return
bson_handle_item
(
initid
,
args
,
result
,
res_length
,
is_null
,
p
);
}
// end of bson_set_item
void
bson_set_item_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_set_item_deinit
/*********************************************************************************/
/* Insert Json items of a Json document according to path. */
/*********************************************************************************/
my_bool
bson_insert_item_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
return
bson_set_item_init
(
initid
,
args
,
message
);
}
// end of bson_insert_item_init
char
*
bson_insert_item
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
p
)
{
strcpy
(
result
,
"$insert"
);
return
bson_handle_item
(
initid
,
args
,
result
,
res_length
,
is_null
,
p
);
}
// end of bson_insert_item
void
bson_insert_item_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_insert_item_deinit
/*********************************************************************************/
/* Update Json items of a Json document according to path. */
/*********************************************************************************/
my_bool
bson_update_item_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
return
bson_set_item_init
(
initid
,
args
,
message
);
}
// end of bson_update_item_init
char
*
bson_update_item
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
p
)
{
strcpy
(
result
,
"$update"
);
return
bson_handle_item
(
initid
,
args
,
result
,
res_length
,
is_null
,
p
);
}
// end of bson_update_item
void
bson_update_item_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_update_item_deinit
/*********************************************************************************/
/* Returns a json file as a json string. */
/*********************************************************************************/
my_bool
bson_file_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
fl
,
more
=
1024
;
if
(
args
->
arg_count
<
1
||
args
->
arg_count
>
4
)
{
strcpy
(
message
,
"This function only accepts 1 to 4 arguments"
);
return
true
;
}
else
if
(
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a string (file name)"
);
return
true
;
}
// endif's args[0]
for
(
unsigned
int
i
=
1
;
i
<
args
->
arg_count
;
i
++
)
{
if
(
!
(
args
->
arg_type
[
i
]
==
INT_RESULT
||
args
->
arg_type
[
i
]
==
STRING_RESULT
))
{
sprintf
(
message
,
"Argument %d is not an integer or a string (pretty or path)"
,
i
);
return
true
;
}
// endif arg_type
// Take care of eventual memory argument
if
(
args
->
arg_type
[
i
]
==
INT_RESULT
&&
args
->
args
[
i
])
more
+=
(
ulong
)
*
(
longlong
*
)
args
->
args
[
i
];
}
// endfor i
initid
->
maybe_null
=
1
;
CalcLen
(
args
,
false
,
reslen
,
memlen
);
if
(
args
->
args
[
0
])
fl
=
GetFileLength
(
args
->
args
[
0
]);
else
fl
=
100
;
// What can be done here?
reslen
+=
fl
;
if
(
initid
->
const_item
)
more
+=
fl
;
if
(
args
->
arg_count
>
1
)
more
+=
fl
*
M
;
memlen
+=
more
;
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
);
}
// end of bson_file_init
char
*
bson_file
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
fn
,
*
str
=
NULL
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
BDOC
doc
(
g
);
if
(
g
->
N
)
{
if
(
g
->
N
)
{
str
=
(
char
*
)
g
->
Activityp
;
str
=
(
char
*
)
g
->
Xchk
;
goto
err
;
goto
fin
;
}
else
if
(
initid
->
const_item
)
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
g
->
N
=
1
;
try
{
PlugSubSet
(
g
->
Sarea
,
g
->
Sarea_Size
);
if
(
!
g
->
Xchk
)
{
fn
=
MakePSZ
(
g
,
args
,
0
);
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
!
g
->
Xchk
))
{
PUSH_WARNING
(
"CheckMemory error"
);
*
error
=
1
;
goto
err
;
}
else
if
(
!
(
bvp
=
MakeBinValue
(
g
,
args
,
0
)))
{
PUSH_WARNING
(
g
->
Message
);
goto
err
;
}
// endif bvp
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
bvp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
else
if
(
args
->
arg_count
>
1
)
{
bvp
=
(
PBVAL
)
g
->
Xchk
;
int
pretty
=
3
,
pty
=
3
;
size_t
len
;
PBVAL
jsp
,
jvp
=
NULL
;
BJNX
bnx
(
g
);
for
(
unsigned
int
i
=
1
;
i
<
args
->
arg_count
;
i
++
)
if
(
args
->
arg_type
[
i
]
==
INT_RESULT
&&
*
(
longlong
*
)
args
->
args
[
i
]
<
4
)
{
pretty
=
(
int
)
*
(
longlong
*
)
args
->
args
[
i
];
break
;
}
// endif type
for
(
uint
i
=
1
;
i
<
args
->
arg_count
;
i
++
)
// Parse the json file and allocate its tree structure
if
(
args
->
arg_type
[
i
]
==
STRING_RESULT
)
if
(
!
(
jsp
=
bnx
.
ParseJsonFile
(
g
,
fn
,
pty
,
len
)))
{
fn
=
args
->
args
[
i
];
PUSH_WARNING
(
g
->
Message
);
else
if
(
args
->
arg_type
[
i
]
==
INT_RESULT
)
goto
fin
;
pretty
=
(
int
)
*
(
longlong
*
)
args
->
args
[
i
];
}
// endif jsp
if
(
pty
==
3
)
PUSH_WARNING
(
"File pretty format cannot be determined"
);
else
if
(
pretty
!=
3
&&
pty
!=
pretty
)
PUSH_WARNING
(
"File pretty format doesn't match the specified pretty value"
);
else
if
(
pretty
==
3
)
pretty
=
pty
;
// Check whether a path was specified
if
(
bnx
.
CheckPath
(
g
,
args
,
jsp
,
jvp
,
1
))
{
PUSH_WARNING
(
g
->
Message
);
goto
fin
;
}
else
if
(
jvp
)
jsp
=
jvp
;
// Serialize the parse tree
if
(
!
(
str
=
bnx
.
Serialize
(
g
,
jsp
,
NULL
,
0
)))
str
=
doc
.
Serialize
(
g
,
bvp
,
fn
,
pretty
);
PUSH_WARNING
(
g
->
Message
);
if
(
initid
->
const_item
)
}
else
// Keep result of constant function
if
(
!
(
str
=
GetJsonFile
(
g
,
fn
)))
g
->
Activityp
=
(
PACTIVITY
)
str
;
PUSH_WARNING
(
g
->
Message
)
;
}
catch
(
int
n
)
{
if
(
initid
->
const_item
)
xtrc
(
1
,
"json_test_bson: error %d: %s
\n
"
,
n
,
g
->
Message
);
// Keep result of constant function
PUSH_WARNING
(
g
->
Message
);
g
->
Xchk
=
str
;
*
error
=
1
;
str
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
str
=
NULL
;
}
// end catch
err
:
fin
:
if
(
!
str
)
{
if
(
!
str
)
{
*
res_length
=
0
;
*
res_length
=
0
;
*
is_null
=
1
;
*
is_null
=
1
;
}
else
}
else
*
res_length
=
strlen
(
str
);
*
res_length
=
strlen
(
str
);
return
str
;
return
str
;
}
// end of bson_
test
}
// end of bson_
file
void
bson_test_deinit
(
UDF_INIT
*
initid
)
{
void
bson_file_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of bson_
test
_deinit
}
// end of bson_
file
_deinit
/*********************************************************************************/
/*********************************************************************************/
/*
Locate a value in a Json tree.
*/
/*
Make a json file from a json item.
*/
/*********************************************************************************/
/*********************************************************************************/
my_bool
bsonlocate_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
my_bool
bfile_make_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
unsigned
long
reslen
,
memlen
,
more
=
1000
;
{
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
<
2
)
{
if
(
args
->
arg_count
<
1
||
args
->
arg_count
>
3
)
{
strcpy
(
message
,
"
At least 2 arguments required
"
);
strcpy
(
message
,
"
Wrong number of arguments
"
);
return
true
;
return
true
;
}
else
if
(
!
IsJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
}
else
if
(
!
Is
Arg
Json
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
return
true
;
}
else
if
(
args
->
arg_count
>
2
&&
args
->
arg_type
[
2
]
!=
INT_RESULT
)
{
}
// endif
strcpy
(
message
,
"Third argument is not an integer (rank)"
);
return
true
;
}
// endifs args
CalcLen
(
args
,
false
,
reslen
,
memlen
);
CalcLen
(
args
,
false
,
reslen
,
memlen
);
memlen
=
memlen
+
5000
;
// To take care of not pretty files
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
);
}
// end of bfile_make_init
// TODO: calculate this
char
*
bfile_make
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
if
(
IsJson
(
args
,
0
)
==
3
)
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
)
more
=
0
;
{
char
*
p
,
*
str
=
NULL
,
*
fn
=
NULL
;
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
int
n
,
pretty
=
2
;
}
// end of bsonlocate_init
PBVAL
jsp
,
jvp
;
char
*
bsonlocate
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
path
=
NULL
;
int
k
;
PBVAL
bvp
,
bvp2
;
PBJNX
bnxp
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
BJNX
bnx
(
g
);
if
(
g
->
N
)
{
if
(
g
->
N
)
{
if
(
g
->
Activityp
)
{
str
=
(
char
*
)
g
->
Activityp
;
path
=
(
char
*
)
g
->
Activityp
;
goto
fin
;
*
res_length
=
strlen
(
path
);
return
path
;
}
else
{
*
res_length
=
0
;
*
is_null
=
1
;
return
NULL
;
}
// endif Activityp
}
else
if
(
initid
->
const_item
)
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
g
->
N
=
1
;
try
{
// if ((n = IsArgJson(args, 0)) == 3) {
if
(
!
g
->
Xchk
)
{
// Get default file name and pretty
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
!
g
->
Xchk
))
{
// PBSON bsp = (PBSON)args->args[0];
PUSH_WARNING
(
"CheckMemory error"
);
*
error
=
1
;
goto
err
;
}
else
bvp
=
MakeBinValue
(
g
,
args
,
0
);
if
(
!
bvp
)
{
// fn = bsp->Filename;
PUSH_WARNING
(
"First argument is not a valid JSON item"
);
// pretty = bsp->Pretty;
goto
err
;
// } else
}
// endif bvp
if
((
n
=
IsArgJson
(
args
,
0
))
==
2
)
fn
=
args
->
args
[
0
];
if
(
g
->
Mrr
)
{
// First argument is a constant
if
(
!
g
->
Xchk
)
{
g
->
Xchk
=
bvp
;
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
true
))
{
JsonMemSave
(
g
);
PUSH_WARNING
(
"CheckMemory error"
);
}
// endif Mrr
goto
fin
;
}
else
jvp
=
bnx
.
MakeValue
(
g
,
args
,
0
);
if
((
p
=
bnx
.
GetString
(
jvp
)))
{
if
(
!
strchr
(
"[{
\t\r\n
"
,
*
p
))
{
// Is this a file name?
if
(
!
(
p
=
GetJsonFile
(
g
,
p
)))
{
PUSH_WARNING
(
g
->
Message
);
goto
fin
;
}
else
fn
=
bnx
.
GetString
(
jvp
);
}
// endif p
if
(
!
(
jsp
=
bnx
.
ParseJson
(
g
,
p
,
strlen
(
p
))))
{
PUSH_WARNING
(
g
->
Message
);
goto
fin
;
}
// endif jsp
}
else
bnx
.
SetValueVal
(
jvp
,
jsp
);
bvp
=
(
PBVAL
)
g
->
Xchk
;
}
// endif p
// The item to locate
if
(
g
->
Mrr
)
{
// First argument is a constant
if
(
!
(
bvp2
=
MakeBinValue
(
g
,
args
,
1
)))
{
g
->
Xchk
=
jvp
;
PUSH_WARNING
(
"Invalid second argument"
);
JsonMemSave
(
g
);
goto
err
;
}
// endif Mrr
}
// endif bvp
k
=
(
args
->
arg_count
>
2
)
?
(
int
)
*
(
long
long
*
)
args
->
args
[
2
]
:
1
;
}
else
jvp
=
(
PBVAL
)
g
->
Xchk
;
bnxp
=
new
(
g
)
BJNX
(
g
,
bvp
,
TYPE_STRING
);
for
(
uint
i
=
1
;
i
<
args
->
arg_count
;
i
++
)
path
=
bnxp
->
Locate
(
g
,
bvp
,
bvp2
,
k
);
switch
(
args
->
arg_type
[
i
])
{
case
STRING_RESULT
:
fn
=
MakePSZ
(
g
,
args
,
i
);
break
;
case
INT_RESULT
:
pretty
=
(
int
)
*
(
longlong
*
)
args
->
args
[
i
];
break
;
default:
PUSH_WARNING
(
"Unexpected argument type in bfile_make"
);
}
// endswitch arg_type
if
(
initid
->
const_item
)
if
(
fn
)
{
// Keep result of constant function
if
(
!
bnx
.
Serialize
(
g
,
jvp
,
fn
,
pretty
))
g
->
Activityp
=
(
PACTIVITY
)
path
;
PUSH_WARNING
(
g
->
Message
);
}
else
PUSH_WARNING
(
"Missing file name"
);
}
catch
(
int
n
)
{
str
=
fn
;
xtrc
(
1
,
"Exception %d: %s
\n
"
,
n
,
g
->
Message
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
path
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
path
=
NULL
;
}
// end catch
err:
if
(
initid
->
const_item
)
if
(
!
path
)
{
// Keep result of constant function
g
->
Activityp
=
(
PACTIVITY
)
str
;
fin:
if
(
!
str
)
{
*
res_length
=
0
;
*
res_length
=
0
;
*
is_null
=
1
;
*
is_null
=
1
;
}
else
}
else
*
res_length
=
strlen
(
path
);
*
res_length
=
strlen
(
str
);
return
path
;
return
str
;
}
// end of b
sonlocat
e
}
// end of b
file_mak
e
void
bsonlocate_deinit
(
UDF_INIT
*
initid
)
{
void
bfile_make_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of b
sonlocat
e_deinit
}
// end of b
file_mak
e_deinit
/*********************************************************************************/
/*********************************************************************************/
/*
Locate all occurences of a value in a Json tree.
*/
/*
Convert a prettiest Json file to Pretty=0.
*/
/*********************************************************************************/
/*********************************************************************************/
my_bool
b
son_locate_all
_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
my_bool
b
file_convert
_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
unsigned
long
reslen
,
memlen
,
more
=
1000
;
unsigned
long
reslen
,
memlen
;
if
(
args
->
arg_count
<
2
)
{
if
(
args
->
arg_count
!=
3
)
{
strcpy
(
message
,
"At least 2 arguments required"
);
strcpy
(
message
,
"This function must have 3 arguments"
);
return
true
;
}
else
if
(
!
IsJson
(
args
,
0
)
&&
args
->
arg_type
[
0
]
!=
STRING_RESULT
)
{
strcpy
(
message
,
"First argument must be a json item"
);
return
true
;
return
true
;
}
else
if
(
args
->
arg_
count
>
2
&&
args
->
arg_
type
[
2
]
!=
INT_RESULT
)
{
}
else
if
(
args
->
arg_type
[
2
]
!=
INT_RESULT
)
{
strcpy
(
message
,
"Third
argument is not an integer (Depth
)"
);
strcpy
(
message
,
"Third
Argument must be an integer (LRECL
)"
);
return
true
;
return
true
;
}
// endifs
}
else
for
(
int
i
=
0
;
i
<
2
;
i
++
)
if
(
args
->
arg_type
[
i
]
!=
STRING_RESULT
)
{
sprintf
(
message
,
"Arguments %d must be a string (file name)"
,
i
+
1
);
return
true
;
}
// endif args
CalcLen
(
args
,
false
,
reslen
,
memlen
);
CalcLen
(
args
,
false
,
reslen
,
memlen
);
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
);
}
// end of bfile_convert_init
// TODO: calculate this
char
*
bfile_convert
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
if
(
IsJson
(
args
,
0
)
==
3
)
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
more
=
0
;
char
*
str
,
*
fn
,
*
ofn
;
int
lrecl
=
(
int
)
*
(
longlong
*
)
args
->
args
[
2
];
return
JsonInit
(
initid
,
args
,
message
,
true
,
reslen
,
memlen
,
more
);
}
// end of bson_locate_all_init
char
*
bson_locate_all
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
path
=
NULL
;
int
mx
=
10
;
PBVAL
bvp
,
bvp2
;
PBJNX
bnxp
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
if
(
g
->
N
)
{
PlugSubSet
(
g
->
Sarea
,
g
->
Sarea_Size
);
if
(
g
->
Activityp
)
{
fn
=
MakePSZ
(
g
,
args
,
0
);
path
=
(
char
*
)
g
->
Activityp
;
ofn
=
MakePSZ
(
g
,
args
,
1
);
*
res_length
=
strlen
(
path
);
return
path
;
}
else
{
*
error
=
1
;
*
res_length
=
0
;
*
is_null
=
1
;
return
NULL
;
}
// endif Activityp
}
else
if
(
initid
->
const_item
)
g
->
N
=
1
;
try
{
if
(
!
g
->
Xchk
)
{
if
(
CheckMemory
(
g
,
initid
,
args
,
1
,
true
))
{
PUSH_WARNING
(
"CheckMemory error"
);
*
error
=
1
;
goto
err
;
}
else
bvp
=
MakeBinValue
(
g
,
args
,
0
);
if
(
!
bvp
)
{
PUSH_WARNING
(
"First argument is not a valid JSON item"
);
goto
err
;
}
// endif bvp
if
(
g
->
Mrr
)
{
// First argument is a constant
g
->
Xchk
=
bvp
;
JsonMemSave
(
g
);
}
// endif Mrr
}
else
bvp
=
(
PBVAL
)
g
->
Xchk
;
// The item to locate
if
(
!
(
bvp2
=
MakeBinValue
(
g
,
args
,
1
)))
{
PUSH_WARNING
(
"Invalid second argument"
);
goto
err
;
}
// endif bvp
if
(
args
->
arg_count
>
2
)
mx
=
(
int
)
*
(
long
long
*
)
args
->
args
[
2
];
bnxp
=
new
(
g
)
BJNX
(
g
,
bvp
,
TYPE_STRING
);
if
(
!
g
->
Xchk
)
{
path
=
bnxp
->
LocateAll
(
g
,
bvp
,
bvp2
,
mx
);
JUP
*
jup
=
new
(
g
)
JUP
(
g
);
if
(
initid
->
const_item
)
str
=
jup
->
UnprettyJsonFile
(
g
,
fn
,
ofn
,
lrecl
);
// Keep result of constant function
g
->
Xchk
=
str
;
g
->
Activityp
=
(
PACTIVITY
)
path
;
}
else
str
=
(
char
*
)
g
->
Xchk
;
}
catch
(
int
n
)
{
if
(
!
str
)
{
xtrc
(
1
,
"Exception %d: %s
\n
"
,
n
,
g
->
Message
);
PUSH_WARNING
(
g
->
Message
?
g
->
Message
:
"Unexpected error"
);
PUSH_WARNING
(
g
->
Message
);
*
is_null
=
1
;
*
error
=
1
;
path
=
NULL
;
}
catch
(
const
char
*
msg
)
{
strcpy
(
g
->
Message
,
msg
);
PUSH_WARNING
(
g
->
Message
);
*
error
=
1
;
*
error
=
1
;
path
=
NULL
;
}
// end catch
err:
if
(
!
path
)
{
*
res_length
=
0
;
*
res_length
=
0
;
*
is_null
=
1
;
}
else
{
}
else
strcpy
(
result
,
str
);
*
res_length
=
strlen
(
path
);
*
res_length
=
strlen
(
str
);
}
// endif str
return
path
;
return
str
;
}
// end of b
son_locate_all
}
// end of b
file_convert
void
b
son_locate_all
_deinit
(
UDF_INIT
*
initid
)
{
void
b
file_convert
_deinit
(
UDF_INIT
*
initid
)
{
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
JsonFreeMem
((
PGLOBAL
)
initid
->
ptr
);
}
// end of b
son_locate_all
_deinit
}
// end of b
file_convert
_deinit
/*********************************************************************************/
/*********************************************************************************/
/* Convert a pretty=0 Json file to binary BJSON. */
/* Convert a pretty=0 Json file to binary BJSON. */
...
...
storage/connect/bsonudf.h
View file @
cba46c99
...
@@ -9,7 +9,77 @@
...
@@ -9,7 +9,77 @@
#include "jsonudf.h"
#include "jsonudf.h"
#include "bson.h"
#include "bson.h"
#if 0
#define UDF_EXEC_ARGS \
UDF_INIT*, UDF_ARGS*, char*, unsigned long*, char*, char*
// BSON size should be equal on Linux and Windows
#define BMX 255
typedef struct BSON* PBSON;
/***********************************************************************/
/* Structure used to return binary json to Json UDF functions. */
/***********************************************************************/
struct BSON {
char Msg[BMX + 1];
char *Filename;
PGLOBAL G;
int Pretty;
ulong Reslen;
my_bool Changed;
PJSON Top;
PJSON Jsp;
PBSON Bsp;
}; // end of struct BSON
PBSON JbinAlloc(PGLOBAL g, UDF_ARGS* args, ulong len, PJSON jsp);
/*********************************************************************************/
/* The JSON tree node. Can be an Object or an Array. */
/*********************************************************************************/
typedef struct _jnode {
PSZ Key; // The key used for object
OPVAL Op; // Operator used for this node
PVAL CncVal; // To cont value used for OP_CNC
PVAL Valp; // The internal array VALUE
int Rank; // The rank in array
int Rx; // Read row number
int Nx; // Next to read row number
} JNODE, *PJNODE;
/*********************************************************************************/
/* The JSON utility functions. */
/*********************************************************************************/
bool IsNum(PSZ s);
char *NextChr(PSZ s, char sep);
char *GetJsonNull(void);
uint GetJsonGrpSize(void);
my_bool JsonSubSet(PGLOBAL g, my_bool b = false);
my_bool CalcLen(UDF_ARGS* args, my_bool obj, unsigned long& reslen,
unsigned long& memlen, my_bool mod = false);
my_bool JsonInit(UDF_INIT* initid, UDF_ARGS* args, char* message, my_bool mbn,
unsigned long reslen, unsigned long memlen,
unsigned long more = 0);
my_bool CheckMemory(PGLOBAL g, UDF_INIT* initid, UDF_ARGS* args, uint n,
my_bool m, my_bool obj = false, my_bool mod = false);
PSZ MakePSZ(PGLOBAL g, UDF_ARGS* args, int i);
int IsArgJson(UDF_ARGS* args, uint i);
char *GetJsonFile(PGLOBAL g, char* fn);
/*********************************************************************************/
/* Structure JPN. Used to make the locate path. */
/*********************************************************************************/
typedef struct _jpn {
int Type;
PCSZ Key;
int N;
} JPN, *PJPN;
#endif // 0
/* --------------------------- New Testing BJSON Stuff --------------------------*/
/* --------------------------- New Testing BJSON Stuff --------------------------*/
extern
uint
JsonGrpSize
;
uint
GetJsonGroupSize
(
void
);
typedef
class
BJNX
*
PBJNX
;
typedef
class
BJNX
*
PBJNX
;
...
@@ -19,11 +89,13 @@ typedef class BJNX* PBJNX;
...
@@ -19,11 +89,13 @@ typedef class BJNX* PBJNX;
class
BJNX
:
public
BDOC
{
class
BJNX
:
public
BDOC
{
public:
public:
// Constructors
// Constructors
BJNX
(
PGLOBAL
g
);
BJNX
(
PGLOBAL
g
,
PBVAL
row
,
int
type
,
int
len
=
64
,
int
prec
=
0
,
my_bool
wr
=
false
);
BJNX
(
PGLOBAL
g
,
PBVAL
row
,
int
type
,
int
len
=
64
,
int
prec
=
0
,
my_bool
wr
=
false
);
// Implementation
// Implementation
int
GetPrecision
(
void
)
{
return
Prec
;
}
int
GetPrecision
(
void
)
{
return
Prec
;
}
PVAL
GetValue
(
void
)
{
return
Value
;
}
PVAL
GetValue
(
void
)
{
return
Value
;
}
void
SetRow
(
PBVAL
vp
)
{
Row
=
vp
;
}
// Methods
// Methods
my_bool
SetJpath
(
PGLOBAL
g
,
char
*
path
,
my_bool
jb
=
false
);
my_bool
SetJpath
(
PGLOBAL
g
,
char
*
path
,
my_bool
jb
=
false
);
...
@@ -32,9 +104,16 @@ class BJNX : public BDOC {
...
@@ -32,9 +104,16 @@ class BJNX : public BDOC {
PBVAL
GetRowValue
(
PGLOBAL
g
,
PBVAL
row
,
int
i
,
my_bool
b
=
true
);
PBVAL
GetRowValue
(
PGLOBAL
g
,
PBVAL
row
,
int
i
,
my_bool
b
=
true
);
PBVAL
GetJson
(
PGLOBAL
g
);
PBVAL
GetJson
(
PGLOBAL
g
);
my_bool
CheckPath
(
PGLOBAL
g
);
my_bool
CheckPath
(
PGLOBAL
g
);
my_bool
CheckPath
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
PBVAL
jsp
,
PBVAL
&
jvp
,
int
n
);
my_bool
WriteValue
(
PGLOBAL
g
,
PBVAL
jvalp
);
my_bool
WriteValue
(
PGLOBAL
g
,
PBVAL
jvalp
);
char
*
Locate
(
PGLOBAL
g
,
PBVAL
jsp
,
PBVAL
jvp
,
int
k
=
1
);
char
*
Locate
(
PGLOBAL
g
,
PBVAL
jsp
,
PBVAL
jvp
,
int
k
=
1
);
char
*
LocateAll
(
PGLOBAL
g
,
PBVAL
jsp
,
PBVAL
jvp
,
int
mx
=
10
);
char
*
LocateAll
(
PGLOBAL
g
,
PBVAL
jsp
,
PBVAL
jvp
,
int
mx
=
10
);
PSZ
MakeKey
(
UDF_ARGS
*
args
,
int
i
);
PBVAL
MakeBinValue
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
uint
i
);
PBVAL
MakeValue
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
uint
i
,
PBVAL
*
top
=
NULL
);
PBVAL
MakeTypedValue
(
PGLOBAL
g
,
UDF_ARGS
*
args
,
uint
i
,
JTYP
type
,
PBVAL
*
top
=
NULL
);
PBVAL
ParseJsonFile
(
PGLOBAL
g
,
char
*
fn
,
int
&
pty
,
size_t
&
len
);
protected:
protected:
my_bool
SetArrayOptions
(
PGLOBAL
g
,
char
*
p
,
int
i
,
PSZ
nm
);
my_bool
SetArrayOptions
(
PGLOBAL
g
,
char
*
p
,
int
i
,
PSZ
nm
);
...
@@ -99,6 +178,14 @@ extern "C" {
...
@@ -99,6 +178,14 @@ extern "C" {
DllExport
char
*
bson_array_add_values
(
UDF_EXEC_ARGS
);
DllExport
char
*
bson_array_add_values
(
UDF_EXEC_ARGS
);
DllExport
void
bson_array_add_values_deinit
(
UDF_INIT
*
);
DllExport
void
bson_array_add_values_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_array_add_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_array_add
(
UDF_EXEC_ARGS
);
DllExport
void
bson_array_add_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_array_delete_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_array_delete
(
UDF_EXEC_ARGS
);
DllExport
void
bson_array_delete_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bsonlocate_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
my_bool
bsonlocate_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bsonlocate
(
UDF_EXEC_ARGS
);
DllExport
char
*
bsonlocate
(
UDF_EXEC_ARGS
);
DllExport
void
bsonlocate_deinit
(
UDF_INIT
*
);
DllExport
void
bsonlocate_deinit
(
UDF_INIT
*
);
...
@@ -107,6 +194,104 @@ extern "C" {
...
@@ -107,6 +194,104 @@ extern "C" {
DllExport
char
*
bson_locate_all
(
UDF_EXEC_ARGS
);
DllExport
char
*
bson_locate_all
(
UDF_EXEC_ARGS
);
DllExport
void
bson_locate_all_deinit
(
UDF_INIT
*
);
DllExport
void
bson_locate_all_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_contains_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
long
long
bson_contains
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
,
char
*
);
DllExport
void
bson_contains_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bsoncontains_path_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
long
long
bsoncontains_path
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
,
char
*
);
DllExport
void
bsoncontains_path_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_make_object_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_make_object
(
UDF_EXEC_ARGS
);
DllExport
void
bson_make_object_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_object_nonull_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_object_nonull
(
UDF_EXEC_ARGS
);
DllExport
void
bson_object_nonull_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_object_key_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_object_key
(
UDF_EXEC_ARGS
);
DllExport
void
bson_object_key_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_object_add_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_object_add
(
UDF_EXEC_ARGS
);
DllExport
void
bson_object_add_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_object_delete_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_object_delete
(
UDF_EXEC_ARGS
);
DllExport
void
bson_object_delete_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_object_list_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_object_list
(
UDF_EXEC_ARGS
);
DllExport
void
bson_object_list_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_object_values_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_object_values
(
UDF_EXEC_ARGS
);
DllExport
void
bson_object_values_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_item_merge_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_item_merge
(
UDF_EXEC_ARGS
);
DllExport
void
bson_item_merge_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_get_item_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_get_item
(
UDF_EXEC_ARGS
);
DllExport
void
bson_get_item_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bsonget_string_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bsonget_string
(
UDF_EXEC_ARGS
);
DllExport
void
bsonget_string_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bsonget_int_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
long
long
bsonget_int
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
,
char
*
);
DllExport
void
bsonget_int_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bsonget_real_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
double
bsonget_real
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
,
char
*
);
DllExport
void
bsonget_real_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bsonset_grp_size_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
long
long
bsonset_grp_size
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
,
char
*
);
DllExport
my_bool
bsonget_grp_size_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
long
long
bsonget_grp_size
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
,
char
*
);
DllExport
my_bool
bson_array_grp_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
void
bson_array_grp_clear
(
UDF_INIT
*
,
char
*
,
char
*
);
DllExport
void
bson_array_grp_add
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
,
char
*
);
DllExport
char
*
bson_array_grp
(
UDF_EXEC_ARGS
);
DllExport
void
bson_array_grp_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_object_grp_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
void
bson_object_grp_clear
(
UDF_INIT
*
,
char
*
,
char
*
);
DllExport
void
bson_object_grp_add
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
,
char
*
);
DllExport
char
*
bson_object_grp
(
UDF_EXEC_ARGS
);
DllExport
void
bson_object_grp_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_set_item_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_set_item
(
UDF_EXEC_ARGS
);
DllExport
void
bson_set_item_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_insert_item_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_insert_item
(
UDF_EXEC_ARGS
);
DllExport
void
bson_insert_item_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_update_item_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_update_item
(
UDF_EXEC_ARGS
);
DllExport
void
bson_update_item_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bson_file_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bson_file
(
UDF_EXEC_ARGS
);
DllExport
void
bson_file_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bfile_make_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bfile_make
(
UDF_EXEC_ARGS
);
DllExport
void
bfile_make_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bfile_convert_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bfile_convert
(
UDF_EXEC_ARGS
);
DllExport
void
bfile_convert_deinit
(
UDF_INIT
*
);
DllExport
my_bool
bfile_bjson_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
my_bool
bfile_bjson_init
(
UDF_INIT
*
,
UDF_ARGS
*
,
char
*
);
DllExport
char
*
bfile_bjson
(
UDF_EXEC_ARGS
);
DllExport
char
*
bfile_bjson
(
UDF_EXEC_ARGS
);
DllExport
void
bfile_bjson_deinit
(
UDF_INIT
*
);
DllExport
void
bfile_bjson_deinit
(
UDF_INIT
*
);
...
...
storage/connect/filamtxt.cpp
View file @
cba46c99
...
@@ -812,7 +812,7 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
...
@@ -812,7 +812,7 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
p
=
To_Buf
+
strlen
(
To_Buf
)
-
1
;
p
=
To_Buf
+
strlen
(
To_Buf
)
-
1
;
if
(
trace
(
2
))
if
(
trace
(
2
))
htrc
(
" Read: To_Buf=%p p=%c
\n
"
,
To_Buf
,
To_Buf
,
p
);
htrc
(
" Read: To_Buf=%p p=%c
\n
"
,
To_Buf
,
p
);
#if defined(__WIN__)
#if defined(__WIN__)
if
(
Bin
)
{
if
(
Bin
)
{
...
...
storage/connect/jsonudf.cpp
View file @
cba46c99
...
@@ -35,7 +35,7 @@ static PJSON JsonNew(PGLOBAL g, JTYP type);
...
@@ -35,7 +35,7 @@ static PJSON JsonNew(PGLOBAL g, JTYP type);
static
PJVAL
JvalNew
(
PGLOBAL
g
,
JTYP
type
,
void
*
vp
=
NULL
);
static
PJVAL
JvalNew
(
PGLOBAL
g
,
JTYP
type
,
void
*
vp
=
NULL
);
static
PJSNX
JsnxNew
(
PGLOBAL
g
,
PJSON
jsp
,
int
type
,
int
len
=
64
);
static
PJSNX
JsnxNew
(
PGLOBAL
g
,
PJSON
jsp
,
int
type
,
int
len
=
64
);
static
uint
JsonGrpSize
=
10
;
uint
JsonGrpSize
=
10
;
/*********************************************************************************/
/*********************************************************************************/
/* SubAlloc a new JSNX class with protection against memory exhaustion. */
/* SubAlloc a new JSNX class with protection against memory exhaustion. */
...
@@ -1166,7 +1166,7 @@ static void SetChanged(PBSON bsp)
...
@@ -1166,7 +1166,7 @@ static void SetChanged(PBSON bsp)
/*********************************************************************************/
/*********************************************************************************/
/* Replaces GetJsonGrpSize not usable when CONNECT is not installed. */
/* Replaces GetJsonGrpSize not usable when CONNECT is not installed. */
/*********************************************************************************/
/*********************************************************************************/
static
uint
GetJsonGroupSize
(
void
)
uint
GetJsonGroupSize
(
void
)
{
{
return
(
JsonGrpSize
)
?
JsonGrpSize
:
GetJsonGrpSize
();
return
(
JsonGrpSize
)
?
JsonGrpSize
:
GetJsonGrpSize
();
}
// end of GetJsonGroupSize
}
// end of GetJsonGroupSize
...
@@ -5837,11 +5837,11 @@ my_bool jfile_convert_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
...
@@ -5837,11 +5837,11 @@ my_bool jfile_convert_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
}
// endif args
}
// endif args
CalcLen
(
args
,
false
,
reslen
,
memlen
);
CalcLen
(
args
,
false
,
reslen
,
memlen
);
return
JsonInit
(
initid
,
args
,
message
,
fals
e
,
reslen
,
memlen
);
return
JsonInit
(
initid
,
args
,
message
,
tru
e
,
reslen
,
memlen
);
}
// end of jfile_convert_init
}
// end of jfile_convert_init
char
*
jfile_convert
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
char
*
jfile_convert
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
res_length
,
char
*
,
char
*
error
)
{
unsigned
long
*
res_length
,
char
*
is_null
,
char
*
error
)
{
char
*
str
,
*
fn
,
*
ofn
;
char
*
str
,
*
fn
,
*
ofn
;
int
lrecl
=
(
int
)
*
(
longlong
*
)
args
->
args
[
2
];
int
lrecl
=
(
int
)
*
(
longlong
*
)
args
->
args
[
2
];
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
PGLOBAL
g
=
(
PGLOBAL
)
initid
->
ptr
;
...
@@ -5853,20 +5853,21 @@ char *jfile_convert(UDF_INIT* initid, UDF_ARGS* args, char* result,
...
@@ -5853,20 +5853,21 @@ char *jfile_convert(UDF_INIT* initid, UDF_ARGS* args, char* result,
if
(
!
g
->
Xchk
)
{
if
(
!
g
->
Xchk
)
{
JUP
*
jup
=
new
(
g
)
JUP
(
g
);
JUP
*
jup
=
new
(
g
)
JUP
(
g
);
str
=
strcpy
(
result
,
jup
->
UnprettyJsonFile
(
g
,
fn
,
ofn
,
lrecl
)
);
str
=
jup
->
UnprettyJsonFile
(
g
,
fn
,
ofn
,
lrecl
);
g
->
Xchk
=
str
;
g
->
Xchk
=
str
;
}
else
}
else
str
=
(
char
*
)
g
->
Xchk
;
str
=
(
char
*
)
g
->
Xchk
;
if
(
!
str
)
{
if
(
!
str
)
{
if
(
g
->
Message
)
PUSH_WARNING
(
g
->
Message
?
g
->
Message
:
"Unexpected error"
);
str
=
strcpy
(
result
,
g
->
Message
);
*
is_null
=
1
;
else
*
error
=
1
;
str
=
strcpy
(
result
,
"Unexpected error"
);
*
res_length
=
0
;
}
else
{
}
// endif str
strcpy
(
result
,
str
);
*
res_length
=
strlen
(
str
);
}
// endif str
*
res_length
=
strlen
(
str
);
return
str
;
return
str
;
}
// end of jfile_convert
}
// end of jfile_convert
...
...
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