Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Add the artifact_to_json(rid|symbolic-name) UDF. Emit check-ins with no P- or F-card as having an empty array for those cards, in the hope of simplifying host-language traversal over the results (no need to check for existence of the cards before traversal). |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | artifact-to-json |
| Files: | files | file ages | folders |
| SHA3-256: |
4416f09b420cae1486a4c02e72b954fa |
| User & Date: | stephan 2025-03-24 17:06:29.746 |
Context
|
2025-03-24
| ||
| 17:23 | Preliminarily remove the "rid" property from artifact_to_json() output, as that value is only valid within a given repository instance. check-in: 024c0ff07f user: stephan tags: artifact-to-json | |
| 17:06 | Add the artifact_to_json(rid|symbolic-name) UDF. Emit check-ins with no P- or F-card as having an empty array for those cards, in the hope of simplifying host-language traversal over the results (no need to check for existence of the cards before traversal). check-in: 4416f09b42 user: stephan tags: artifact-to-json | |
| 14:18 | Re-do previous checkin - i had been editing the generated bld/manifest_.c because of PEBKAC caused by following a compilation error into that file. check-in: 069995d7ea user: stephan tags: artifact-to-json | |
Changes
Changes to src/db.c.
| ︙ | ︙ | |||
1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 |
sqlite3_create_function(db, "url_nouser", 1, SQLITE_UTF8, 0,
url_nouser_func,0,0);
sqlite3_create_function(db, "chat_msg_from_event", 4,
SQLITE_UTF8 | SQLITE_INNOCUOUS, 0,
chat_msg_from_event, 0, 0);
sqlite3_create_function(db, "inode", 1, SQLITE_UTF8, 0,
file_inode_sql_func,0,0);
}
#if USE_SEE
/*
** This is a pointer to the saved database encryption key string.
*/
| > > | 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 |
sqlite3_create_function(db, "url_nouser", 1, SQLITE_UTF8, 0,
url_nouser_func,0,0);
sqlite3_create_function(db, "chat_msg_from_event", 4,
SQLITE_UTF8 | SQLITE_INNOCUOUS, 0,
chat_msg_from_event, 0, 0);
sqlite3_create_function(db, "inode", 1, SQLITE_UTF8, 0,
file_inode_sql_func,0,0);
sqlite3_create_function(db, "artifact_to_json", 1, SQLITE_UTF8, 0,
artifact_to_json_sql_func,0,0);
}
#if USE_SEE
/*
** This is a pointer to the saved database encryption key string.
*/
|
| ︙ | ︙ |
Changes to src/manifest.c.
| ︙ | ︙ | |||
2929 2930 2931 2932 2933 2934 2935 |
case CFTYPE_EVENT: return "event";
case CFTYPE_FORUM: return "forumpost";
}
return NULL;
}
/*
| | > > > | 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 |
case CFTYPE_EVENT: return "event";
case CFTYPE_FORUM: return "forumpost";
}
return NULL;
}
/*
** Creates a JSON representation of p, appending it to b.
**
** b is not cleared before rendering, so the caller needs to do that
** if it's important for their use case.
**
** Pedantic note: this routine traverses p->aFile directly, rather than
** using manifest_file_next(), so that delta manifests are rendered as-is
** instead of having their derived files. If that policy is ever changed,
** p will need to be non-const.
*/
void artifact_to_json(Manifest const *p, Blob *b){
|
| ︙ | ︙ | |||
2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 |
blob_append_char(b, '{');
KVP_STR(0, name, pF->zName);
KVP_STR(1, uuid, pF->zUuid);
KVP_STR(1, perm, pF->zPerm);
KVP_STR(1, oldName, pF->zPrior);
blob_append_char(b, '}');
}
blob_append_char(b, ']');
}
CARD_STR2(G, p->zThreadRoot);
CARD_STR2(H, p->zThreadTitle);
CARD_STR2(I, p->zInReplyTo);
if( p->nField ){
CARD_LETTER(J);
| > > > | 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 |
blob_append_char(b, '{');
KVP_STR(0, name, pF->zName);
KVP_STR(1, uuid, pF->zUuid);
KVP_STR(1, perm, pF->zPerm);
KVP_STR(1, oldName, pF->zPrior);
blob_append_char(b, '}');
}
/* Special case: model checkins with no F-card as having an empty
** array, rather than no F-cards, to hypothetically simplify
** handling in JSON queries. */
blob_append_char(b, ']');
}
CARD_STR2(G, p->zThreadRoot);
CARD_STR2(H, p->zThreadTitle);
CARD_STR2(I, p->zInReplyTo);
if( p->nField ){
CARD_LETTER(J);
|
| ︙ | ︙ | |||
3018 3019 3020 3021 3022 3023 3024 |
for( int i = 0; i < p->nCChild; ++i ){
if( i>0 ) blob_append_char(b, ',');
blob_appendf(b, "%!j", p->azCChild[i]);
}
blob_append_char(b, ']');
}
CARD_STR2(N, p->zMimetype);
| | > | | | | > > > > | 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 |
for( int i = 0; i < p->nCChild; ++i ){
if( i>0 ) blob_append_char(b, ',');
blob_appendf(b, "%!j", p->azCChild[i]);
}
blob_append_char(b, ']');
}
CARD_STR2(N, p->zMimetype);
ISA( CFTYPE_MANIFEST ){
CARD_LETTER(P);
blob_append_char(b, '[');
if( p->nParent ){
for( i = 0; i < p->nParent; ++i ){
if( i>0 ) blob_append_char(b, ',');
blob_appendf(b, "%!j", p->azParent[i]);
}
}
/* Special case: model checkins with no P-card as having
** an empty array, rather than no P-card, to hypothetically
** simplify handling in JSON queries. */
blob_append_char(b, ']');
}
if( p->nCherrypick ){
CARD_LETTER(Q);
blob_append_char(b, '[');
for( i = 0; i < p->nCherrypick; ++i ){
if( i>0 ) blob_append_char(b, ',');
|
| ︙ | ︙ | |||
3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 |
#undef CARD_LETTER
#undef CARD_STR
#undef CARD_STR2
#undef ISA
#undef KVP_STR
#undef STR_OR_NULL
}
/*
** Convenience wrapper around artifact_to_json() which accepts any
** artifact name which is legal for symbolic_name_to_rid(). On success
** it returns the rid of the artifact. Returns 0 if no such artifact
** exists and a negative value if the name is ambiguous.
**
** pOut is not cleared before rendering, so the caller needs to do
** that if it's important for their use case.
*/
int artifact_to_json_by_name(const char *zName, Blob *pOut){
| > > > > > > > > > > > > > > > > > > > | | > > > > | > > > > > > > > | > | < > > > > > > > > > > | > > > | > > > > > > > > > | > > > > > | 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 |
#undef CARD_LETTER
#undef CARD_STR
#undef CARD_STR2
#undef ISA
#undef KVP_STR
#undef STR_OR_NULL
}
/*
** Convenience wrapper around artifact_to_json() which expects rid to
** be the blob.rid of any artifact type. If it can load a Manifest
** with that rid, it returns rid, else it returns 0.
*/
int artifact_to_json_by_rid(int rid, Blob *pOut){
Manifest * const p = manifest_get(rid, CFTYPE_ANY, 0);
if( p ){
artifact_to_json(p, pOut);
manifest_destroy(p);
}else{
rid = 0;
}
return rid;
}
/*
** Convenience wrapper around artifact_to_json() which accepts any
** artifact name which is legal for symbolic_name_to_rid(). On success
** it returns the rid of the artifact. Returns 0 if no such artifact
** exists and a negative value if the name is ambiguous.
**
** pOut is not cleared before rendering, so the caller needs to do
** that if it's important for their use case.
*/
int artifact_to_json_by_name(const char *zName, Blob *pOut){
const int rid = symbolic_name_to_rid(zName, 0);
return rid>0
? artifact_to_json_by_rid(rid, pOut)
: rid;
}
/*
** SQLite UDF for artifact_to_json(). Its single argument should be
** either an INTEGER (blob.rid value) or a TEXT symbolic artifact
** name, as per symbolic_name_to_rid(). If an artifact is found then
** the result of the UDF is that JSON as a string, else it evaluates
** to NULL.
*/
void artifact_to_json_sql_func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int rid = 0;
Blob b = empty_blob;
if(1 != argc){
goto error_usage;
}
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_INTEGER:
rid = artifact_to_json_by_rid(sqlite3_value_int(argv[0]), &b);
break;
case SQLITE_TEXT:{
const char * z = (const char *)sqlite3_value_text(argv[0]);
if( z ){
rid = artifact_to_json_by_name(z, &b);
}
break;
}
default:
goto error_usage;
}
if( rid>0 ){
sqlite3_result_text(context, blob_str(&b), blob_size(&b),
SQLITE_TRANSIENT);
blob_reset(&b);
}else{
/* We should arguably error out if rid<0 (ambiguous name) */
sqlite3_result_null(context);
}
return;
error_usage:
sqlite3_result_error(context, "Expecting one argument: blob.rid or "
"artifact symbolic name", -1);
}
/*
** COMMAND: test-artifact-to-json
**
** Usage: %fossil test-artifact-to-json ?-pretty? symbolic-name [...names]
**
** Tests the artifact_to_json() and artifact_to_json_by_name() APIs.
|
| ︙ | ︙ |