Fossil SCM
Added --after/--before support to /json/timeline/ci and wiki.
Commit
e01d49b252d9d2a1cbd36df7380e4a9cb41f24e9
Parent
12545465e98da07…
1 file changed
+62
-8
+62
-8
| --- src/json.c | ||
| +++ src/json.c | ||
| @@ -1893,14 +1893,15 @@ | ||
| 1893 | 1893 | |
| 1894 | 1894 | /* |
| 1895 | 1895 | ** Create a temporary table suitable for storing timeline data. |
| 1896 | 1896 | */ |
| 1897 | 1897 | static void json_timeline_temp_table(void){ |
| 1898 | - /* Field order MUST match that from json_timeline_query_XXX()!!! */ | |
| 1898 | + /* Field order MUST match that from json_timeline_query()!!! */ | |
| 1899 | 1899 | static const char zSql[] = |
| 1900 | 1900 | @ CREATE TEMP TABLE IF NOT EXISTS json_timeline( |
| 1901 | - @ rid INTEGER PRIMARY KEY, | |
| 1901 | + @ sortId INTEGER PRIMARY KEY, | |
| 1902 | + @ rid INTEGER, | |
| 1902 | 1903 | @ uuid TEXT, |
| 1903 | 1904 | @ mtime INTEGER, |
| 1904 | 1905 | @ timestampString TEXT, |
| 1905 | 1906 | @ comment TEXT, |
| 1906 | 1907 | @ user TEXT, |
| @@ -1921,10 +1922,11 @@ | ||
| 1921 | 1922 | */ |
| 1922 | 1923 | const char const * json_timeline_query(void){ |
| 1923 | 1924 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 1924 | 1925 | static const char zBaseSql[] = |
| 1925 | 1926 | @ SELECT |
| 1927 | + @ NULL, | |
| 1926 | 1928 | @ blob.rid, |
| 1927 | 1929 | @ uuid, |
| 1928 | 1930 | @ strftime('%%s',event.mtime), |
| 1929 | 1931 | @ datetime(event.mtime,'utc'), |
| 1930 | 1932 | @ coalesce(ecomment, comment), |
| @@ -1940,10 +1942,61 @@ | ||
| 1940 | 1942 | @ FROM event JOIN blob |
| 1941 | 1943 | @ WHERE blob.rid=event.objid |
| 1942 | 1944 | ; |
| 1943 | 1945 | return zBaseSql; |
| 1944 | 1946 | } |
| 1947 | + | |
| 1948 | +/* | |
| 1949 | +** Helper for the timeline family of functions. Possibly appends 1 | |
| 1950 | +** AND clause and an ORDER BY clause to pSql, depending on the state | |
| 1951 | +** of the "after" ("a") or "before" ("b") environment parameters. | |
| 1952 | +** This function gives "after" precedence over "before", and only | |
| 1953 | +** applies one of them. | |
| 1954 | +** | |
| 1955 | +** Returns -1 if it adds a "before" clause, 1 if it adds | |
| 1956 | +** an "after" clause, and 0 if it does not change pSql. | |
| 1957 | +*/ | |
| 1958 | +static char json_timeline_add_time_clause(Blob *pSql){ | |
| 1959 | + char const * zAfter = NULL; | |
| 1960 | + char const * zBefore = NULL; | |
| 1961 | + if( g.isHTTP ){ | |
| 1962 | + /** | |
| 1963 | + FIXME: we are only honoring STRING values here, not int (for | |
| 1964 | + passing Unix Epoch times). | |
| 1965 | + */ | |
| 1966 | + zAfter = json_getenv_cstr("after"); | |
| 1967 | + if(!zAfter || !*zAfter){ | |
| 1968 | + zAfter = json_getenv_cstr("a"); | |
| 1969 | + } | |
| 1970 | + if(!zAfter){ | |
| 1971 | + zBefore = json_getenv_cstr("before"); | |
| 1972 | + if(!zBefore||!*zBefore){ | |
| 1973 | + zBefore = json_getenv_cstr("b"); | |
| 1974 | + } | |
| 1975 | + } | |
| 1976 | + }else{ | |
| 1977 | + zAfter = find_option("after","a",1); | |
| 1978 | + zBefore = zAfter ? NULL : find_option("before","b",1); | |
| 1979 | + } | |
| 1980 | + if(zAfter&&*zAfter){ | |
| 1981 | + while( fossil_isspace(*zAfter) ) ++zAfter; | |
| 1982 | + blob_appendf(pSql, | |
| 1983 | + " AND event.mtime>=(SELECT julianday(%Q,'utc')) " | |
| 1984 | + " ORDER BY event.mtime ASC ", | |
| 1985 | + zAfter); | |
| 1986 | + return 1; | |
| 1987 | + }else if(zBefore && *zBefore){ | |
| 1988 | + while( fossil_isspace(*zBefore) ) ++zBefore; | |
| 1989 | + blob_appendf(pSql, | |
| 1990 | + " AND event.mtime<=(SELECT julianday(%Q,'utc')) " | |
| 1991 | + " ORDER BY event.mtime DESC ", | |
| 1992 | + zBefore); | |
| 1993 | + return -1; | |
| 1994 | + }else{ | |
| 1995 | + return 0; | |
| 1996 | + } | |
| 1997 | +} | |
| 1945 | 1998 | |
| 1946 | 1999 | /* |
| 1947 | 2000 | ** Tries to figure out a timeline query length limit base on |
| 1948 | 2001 | ** environment parameters. If it can it returns that value, |
| 1949 | 2002 | ** else it returns some statically defined default value. |
| @@ -1990,12 +2043,12 @@ | ||
| 1990 | 2043 | payV = cson_value_new_object(); |
| 1991 | 2044 | pay = cson_value_get_object(payV); |
| 1992 | 2045 | json_timeline_temp_table(); |
| 1993 | 2046 | blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1); |
| 1994 | 2047 | blob_append(&sql, json_timeline_query(), -1 ); |
| 1995 | - blob_append(&sql, "AND event.type IN('ci') ", -1); | |
| 1996 | - blob_append(&sql, "ORDER BY mtime DESC ", -1); | |
| 2048 | + blob_append(&sql, " AND event.type IN('ci') ", -1); | |
| 2049 | + json_timeline_add_time_clause(&sql); | |
| 1997 | 2050 | #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \ |
| 1998 | 2051 | g.json.resultCode = (cson_rc.AllocError==check) \ |
| 1999 | 2052 | ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \ |
| 2000 | 2053 | goto error;\ |
| 2001 | 2054 | } |
| @@ -2011,11 +2064,12 @@ | ||
| 2011 | 2064 | tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))); |
| 2012 | 2065 | SET("timelineSql"); |
| 2013 | 2066 | #endif |
| 2014 | 2067 | |
| 2015 | 2068 | blob_reset(&sql); |
| 2016 | - blob_append(&sql, "SELECT rid AS rid," | |
| 2069 | + blob_append(&sql, "SELECT " | |
| 2070 | + " rid AS rid," | |
| 2017 | 2071 | " uuid AS uuid," |
| 2018 | 2072 | " mtime AS timestamp," |
| 2019 | 2073 | " timestampString AS timestampString," |
| 2020 | 2074 | " comment AS comment, " |
| 2021 | 2075 | " user AS user," |
| @@ -2025,11 +2079,11 @@ | ||
| 2025 | 2079 | " tags AS tags," /*FIXME: split this into |
| 2026 | 2080 | a JSON array*/ |
| 2027 | 2081 | " tagId AS tagId," |
| 2028 | 2082 | " brief AS briefText" |
| 2029 | 2083 | " FROM json_timeline" |
| 2030 | - " ORDER BY mtime DESC", | |
| 2084 | + " ORDER BY sortId", | |
| 2031 | 2085 | -1); |
| 2032 | 2086 | db_prepare(&q,blob_buffer(&sql)); |
| 2033 | 2087 | listV = cson_value_new_array(); |
| 2034 | 2088 | list = cson_value_get_array(listV); |
| 2035 | 2089 | tmp = listV; |
| @@ -2107,11 +2161,11 @@ | ||
| 2107 | 2161 | pay = cson_value_get_object(payV); |
| 2108 | 2162 | json_timeline_temp_table(); |
| 2109 | 2163 | blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1); |
| 2110 | 2164 | blob_append(&sql, json_timeline_query(), -1 ); |
| 2111 | 2165 | blob_append(&sql, "AND event.type IN('w') ", -1); |
| 2112 | - blob_append(&sql, "ORDER BY mtime DESC ", -1); | |
| 2166 | + json_timeline_add_time_clause(&sql); | |
| 2113 | 2167 | #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \ |
| 2114 | 2168 | g.json.resultCode = (cson_rc.AllocError==check) \ |
| 2115 | 2169 | ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \ |
| 2116 | 2170 | goto error;\ |
| 2117 | 2171 | } |
| @@ -2141,11 +2195,11 @@ | ||
| 2141 | 2195 | " tags AS tags," /*FIXME: split this into |
| 2142 | 2196 | a JSON array*/ |
| 2143 | 2197 | " tagId AS tagId," |
| 2144 | 2198 | #endif |
| 2145 | 2199 | " FROM json_timeline" |
| 2146 | - " ORDER BY mtime DESC", | |
| 2200 | + " ORDER BY sortId", | |
| 2147 | 2201 | -1); |
| 2148 | 2202 | db_prepare(&q,blob_buffer(&sql)); |
| 2149 | 2203 | listV = cson_value_new_array(); |
| 2150 | 2204 | list = cson_value_get_array(listV); |
| 2151 | 2205 | tmp = listV; |
| 2152 | 2206 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -1893,14 +1893,15 @@ | |
| 1893 | |
| 1894 | /* |
| 1895 | ** Create a temporary table suitable for storing timeline data. |
| 1896 | */ |
| 1897 | static void json_timeline_temp_table(void){ |
| 1898 | /* Field order MUST match that from json_timeline_query_XXX()!!! */ |
| 1899 | static const char zSql[] = |
| 1900 | @ CREATE TEMP TABLE IF NOT EXISTS json_timeline( |
| 1901 | @ rid INTEGER PRIMARY KEY, |
| 1902 | @ uuid TEXT, |
| 1903 | @ mtime INTEGER, |
| 1904 | @ timestampString TEXT, |
| 1905 | @ comment TEXT, |
| 1906 | @ user TEXT, |
| @@ -1921,10 +1922,11 @@ | |
| 1921 | */ |
| 1922 | const char const * json_timeline_query(void){ |
| 1923 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 1924 | static const char zBaseSql[] = |
| 1925 | @ SELECT |
| 1926 | @ blob.rid, |
| 1927 | @ uuid, |
| 1928 | @ strftime('%%s',event.mtime), |
| 1929 | @ datetime(event.mtime,'utc'), |
| 1930 | @ coalesce(ecomment, comment), |
| @@ -1940,10 +1942,61 @@ | |
| 1940 | @ FROM event JOIN blob |
| 1941 | @ WHERE blob.rid=event.objid |
| 1942 | ; |
| 1943 | return zBaseSql; |
| 1944 | } |
| 1945 | |
| 1946 | /* |
| 1947 | ** Tries to figure out a timeline query length limit base on |
| 1948 | ** environment parameters. If it can it returns that value, |
| 1949 | ** else it returns some statically defined default value. |
| @@ -1990,12 +2043,12 @@ | |
| 1990 | payV = cson_value_new_object(); |
| 1991 | pay = cson_value_get_object(payV); |
| 1992 | json_timeline_temp_table(); |
| 1993 | blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1); |
| 1994 | blob_append(&sql, json_timeline_query(), -1 ); |
| 1995 | blob_append(&sql, "AND event.type IN('ci') ", -1); |
| 1996 | blob_append(&sql, "ORDER BY mtime DESC ", -1); |
| 1997 | #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \ |
| 1998 | g.json.resultCode = (cson_rc.AllocError==check) \ |
| 1999 | ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \ |
| 2000 | goto error;\ |
| 2001 | } |
| @@ -2011,11 +2064,12 @@ | |
| 2011 | tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))); |
| 2012 | SET("timelineSql"); |
| 2013 | #endif |
| 2014 | |
| 2015 | blob_reset(&sql); |
| 2016 | blob_append(&sql, "SELECT rid AS rid," |
| 2017 | " uuid AS uuid," |
| 2018 | " mtime AS timestamp," |
| 2019 | " timestampString AS timestampString," |
| 2020 | " comment AS comment, " |
| 2021 | " user AS user," |
| @@ -2025,11 +2079,11 @@ | |
| 2025 | " tags AS tags," /*FIXME: split this into |
| 2026 | a JSON array*/ |
| 2027 | " tagId AS tagId," |
| 2028 | " brief AS briefText" |
| 2029 | " FROM json_timeline" |
| 2030 | " ORDER BY mtime DESC", |
| 2031 | -1); |
| 2032 | db_prepare(&q,blob_buffer(&sql)); |
| 2033 | listV = cson_value_new_array(); |
| 2034 | list = cson_value_get_array(listV); |
| 2035 | tmp = listV; |
| @@ -2107,11 +2161,11 @@ | |
| 2107 | pay = cson_value_get_object(payV); |
| 2108 | json_timeline_temp_table(); |
| 2109 | blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1); |
| 2110 | blob_append(&sql, json_timeline_query(), -1 ); |
| 2111 | blob_append(&sql, "AND event.type IN('w') ", -1); |
| 2112 | blob_append(&sql, "ORDER BY mtime DESC ", -1); |
| 2113 | #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \ |
| 2114 | g.json.resultCode = (cson_rc.AllocError==check) \ |
| 2115 | ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \ |
| 2116 | goto error;\ |
| 2117 | } |
| @@ -2141,11 +2195,11 @@ | |
| 2141 | " tags AS tags," /*FIXME: split this into |
| 2142 | a JSON array*/ |
| 2143 | " tagId AS tagId," |
| 2144 | #endif |
| 2145 | " FROM json_timeline" |
| 2146 | " ORDER BY mtime DESC", |
| 2147 | -1); |
| 2148 | db_prepare(&q,blob_buffer(&sql)); |
| 2149 | listV = cson_value_new_array(); |
| 2150 | list = cson_value_get_array(listV); |
| 2151 | tmp = listV; |
| 2152 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -1893,14 +1893,15 @@ | |
| 1893 | |
| 1894 | /* |
| 1895 | ** Create a temporary table suitable for storing timeline data. |
| 1896 | */ |
| 1897 | static void json_timeline_temp_table(void){ |
| 1898 | /* Field order MUST match that from json_timeline_query()!!! */ |
| 1899 | static const char zSql[] = |
| 1900 | @ CREATE TEMP TABLE IF NOT EXISTS json_timeline( |
| 1901 | @ sortId INTEGER PRIMARY KEY, |
| 1902 | @ rid INTEGER, |
| 1903 | @ uuid TEXT, |
| 1904 | @ mtime INTEGER, |
| 1905 | @ timestampString TEXT, |
| 1906 | @ comment TEXT, |
| 1907 | @ user TEXT, |
| @@ -1921,10 +1922,11 @@ | |
| 1922 | */ |
| 1923 | const char const * json_timeline_query(void){ |
| 1924 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 1925 | static const char zBaseSql[] = |
| 1926 | @ SELECT |
| 1927 | @ NULL, |
| 1928 | @ blob.rid, |
| 1929 | @ uuid, |
| 1930 | @ strftime('%%s',event.mtime), |
| 1931 | @ datetime(event.mtime,'utc'), |
| 1932 | @ coalesce(ecomment, comment), |
| @@ -1940,10 +1942,61 @@ | |
| 1942 | @ FROM event JOIN blob |
| 1943 | @ WHERE blob.rid=event.objid |
| 1944 | ; |
| 1945 | return zBaseSql; |
| 1946 | } |
| 1947 | |
| 1948 | /* |
| 1949 | ** Helper for the timeline family of functions. Possibly appends 1 |
| 1950 | ** AND clause and an ORDER BY clause to pSql, depending on the state |
| 1951 | ** of the "after" ("a") or "before" ("b") environment parameters. |
| 1952 | ** This function gives "after" precedence over "before", and only |
| 1953 | ** applies one of them. |
| 1954 | ** |
| 1955 | ** Returns -1 if it adds a "before" clause, 1 if it adds |
| 1956 | ** an "after" clause, and 0 if it does not change pSql. |
| 1957 | */ |
| 1958 | static char json_timeline_add_time_clause(Blob *pSql){ |
| 1959 | char const * zAfter = NULL; |
| 1960 | char const * zBefore = NULL; |
| 1961 | if( g.isHTTP ){ |
| 1962 | /** |
| 1963 | FIXME: we are only honoring STRING values here, not int (for |
| 1964 | passing Unix Epoch times). |
| 1965 | */ |
| 1966 | zAfter = json_getenv_cstr("after"); |
| 1967 | if(!zAfter || !*zAfter){ |
| 1968 | zAfter = json_getenv_cstr("a"); |
| 1969 | } |
| 1970 | if(!zAfter){ |
| 1971 | zBefore = json_getenv_cstr("before"); |
| 1972 | if(!zBefore||!*zBefore){ |
| 1973 | zBefore = json_getenv_cstr("b"); |
| 1974 | } |
| 1975 | } |
| 1976 | }else{ |
| 1977 | zAfter = find_option("after","a",1); |
| 1978 | zBefore = zAfter ? NULL : find_option("before","b",1); |
| 1979 | } |
| 1980 | if(zAfter&&*zAfter){ |
| 1981 | while( fossil_isspace(*zAfter) ) ++zAfter; |
| 1982 | blob_appendf(pSql, |
| 1983 | " AND event.mtime>=(SELECT julianday(%Q,'utc')) " |
| 1984 | " ORDER BY event.mtime ASC ", |
| 1985 | zAfter); |
| 1986 | return 1; |
| 1987 | }else if(zBefore && *zBefore){ |
| 1988 | while( fossil_isspace(*zBefore) ) ++zBefore; |
| 1989 | blob_appendf(pSql, |
| 1990 | " AND event.mtime<=(SELECT julianday(%Q,'utc')) " |
| 1991 | " ORDER BY event.mtime DESC ", |
| 1992 | zBefore); |
| 1993 | return -1; |
| 1994 | }else{ |
| 1995 | return 0; |
| 1996 | } |
| 1997 | } |
| 1998 | |
| 1999 | /* |
| 2000 | ** Tries to figure out a timeline query length limit base on |
| 2001 | ** environment parameters. If it can it returns that value, |
| 2002 | ** else it returns some statically defined default value. |
| @@ -1990,12 +2043,12 @@ | |
| 2043 | payV = cson_value_new_object(); |
| 2044 | pay = cson_value_get_object(payV); |
| 2045 | json_timeline_temp_table(); |
| 2046 | blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1); |
| 2047 | blob_append(&sql, json_timeline_query(), -1 ); |
| 2048 | blob_append(&sql, " AND event.type IN('ci') ", -1); |
| 2049 | json_timeline_add_time_clause(&sql); |
| 2050 | #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \ |
| 2051 | g.json.resultCode = (cson_rc.AllocError==check) \ |
| 2052 | ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \ |
| 2053 | goto error;\ |
| 2054 | } |
| @@ -2011,11 +2064,12 @@ | |
| 2064 | tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))); |
| 2065 | SET("timelineSql"); |
| 2066 | #endif |
| 2067 | |
| 2068 | blob_reset(&sql); |
| 2069 | blob_append(&sql, "SELECT " |
| 2070 | " rid AS rid," |
| 2071 | " uuid AS uuid," |
| 2072 | " mtime AS timestamp," |
| 2073 | " timestampString AS timestampString," |
| 2074 | " comment AS comment, " |
| 2075 | " user AS user," |
| @@ -2025,11 +2079,11 @@ | |
| 2079 | " tags AS tags," /*FIXME: split this into |
| 2080 | a JSON array*/ |
| 2081 | " tagId AS tagId," |
| 2082 | " brief AS briefText" |
| 2083 | " FROM json_timeline" |
| 2084 | " ORDER BY sortId", |
| 2085 | -1); |
| 2086 | db_prepare(&q,blob_buffer(&sql)); |
| 2087 | listV = cson_value_new_array(); |
| 2088 | list = cson_value_get_array(listV); |
| 2089 | tmp = listV; |
| @@ -2107,11 +2161,11 @@ | |
| 2161 | pay = cson_value_get_object(payV); |
| 2162 | json_timeline_temp_table(); |
| 2163 | blob_append(&sql, "INSERT OR IGNORE INTO json_timeline ", -1); |
| 2164 | blob_append(&sql, json_timeline_query(), -1 ); |
| 2165 | blob_append(&sql, "AND event.type IN('w') ", -1); |
| 2166 | json_timeline_add_time_clause(&sql); |
| 2167 | #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \ |
| 2168 | g.json.resultCode = (cson_rc.AllocError==check) \ |
| 2169 | ? FSL_JSON_E_ALLOC : FSL_JSON_E_UNKNOWN; \ |
| 2170 | goto error;\ |
| 2171 | } |
| @@ -2141,11 +2195,11 @@ | |
| 2195 | " tags AS tags," /*FIXME: split this into |
| 2196 | a JSON array*/ |
| 2197 | " tagId AS tagId," |
| 2198 | #endif |
| 2199 | " FROM json_timeline" |
| 2200 | " ORDER BY sortId", |
| 2201 | -1); |
| 2202 | db_prepare(&q,blob_buffer(&sql)); |
| 2203 | listV = cson_value_new_array(); |
| 2204 | list = cson_value_get_array(listV); |
| 2205 | tmp = listV; |
| 2206 |