|
20 | 20 | #define STR_EXPAND(x) #x |
21 | 21 | #define STR(x) STR_EXPAND(x) |
22 | 22 |
|
23 | | -void |
24 | | -version_get_info(VersionInfo *vinfo) |
25 | | -{ |
26 | | - memset(vinfo, 0, sizeof(VersionInfo)); |
27 | | - vinfo->version[0] = strtol(TIMESCALEDB_MAJOR_VERSION, NULL, 10); |
28 | | - vinfo->version[1] = strtol(TIMESCALEDB_MINOR_VERSION, NULL, 10); |
29 | | - vinfo->version[2] = strtol(TIMESCALEDB_PATCH_VERSION, NULL, 10); |
30 | | - |
31 | | - if (strlen(TIMESCALEDB_MOD_VERSION) > 0) |
32 | | - { |
33 | | - StrNCpy(vinfo->version_mod, TIMESCALEDB_MOD_VERSION, sizeof(vinfo->version_mod)); |
34 | | - vinfo->has_version_mod = true; |
35 | | - } |
36 | | -} |
37 | | - |
38 | | -/* |
39 | | - * Compare two versions. |
40 | | - * |
41 | | - * It returns an integer less than, equal to, or greater than zero if version |
42 | | - * v1 is found, respectively, to be less than, to match, or be greater than |
43 | | - * version v2. |
44 | | - */ |
45 | | -int |
46 | | -version_cmp(VersionInfo *v1, VersionInfo *v2) |
47 | | -{ |
48 | | - int i; |
49 | | - |
50 | | - for (i = 0; i < 3; i++) |
51 | | - { |
52 | | - if (v1->version[i] > v2->version[i]) |
53 | | - return 1; |
54 | | - |
55 | | - if (v1->version[i] < v2->version[i]) |
56 | | - return -1; |
57 | | - } |
58 | | - |
59 | | - /* |
60 | | - * Note that the version mod signifies a pre-release version, so having a |
61 | | - * version mod is "less" than not having one with otherwise identical |
62 | | - * versions |
63 | | - */ |
64 | | - if (v1->has_version_mod && !v2->has_version_mod) |
65 | | - return -1; |
66 | | - |
67 | | - if (!v1->has_version_mod && v2->has_version_mod) |
68 | | - return 1; |
69 | | - |
70 | | - /* Compare the version mod lexicographically */ |
71 | | - if (v1->has_version_mod && v2->has_version_mod) |
72 | | - return strncmp(v1->version_mod, v2->version_mod, sizeof(v1->version_mod)); |
73 | | - |
74 | | - return 0; |
75 | | -} |
76 | | - |
77 | | -bool |
78 | | -version_parse(const char *version, VersionInfo *result) |
79 | | -{ |
80 | | - size_t version_len = strlen(version); |
81 | | - int fields_parsed = 0; |
82 | | - int i = 0; |
83 | | - int parse_length[4] = {0}; |
84 | | - |
85 | | - memset(result, 0, sizeof(VersionInfo)); |
86 | | - |
87 | | - /* |
88 | | - * a version is a string of the form |
89 | | - * |
90 | | - * <number>[.<number>[.<number>[-<string>]]] |
91 | | - * |
92 | | - * this corresponds to the format-string |
93 | | - * |
94 | | - * "%lu.%lu.%lu-%<VERSION_INFO_LEN>s" |
95 | | - * |
96 | | - * after parsing each field in the version-string, we output the number of |
97 | | - * bytes currently parsed using %n, a version-string is valid if all of |
98 | | - * the bytes of the string were parsable using the above grammar. |
99 | | - */ |
100 | | - fields_parsed = sscanf(version, "%lu%n.%lu%n.%lu%n-%" STR(VERSION_INFO_LEN) "s%n", |
101 | | - &result->version[0], &parse_length[0], |
102 | | - &result->version[1], &parse_length[1], |
103 | | - &result->version[2], &parse_length[2], |
104 | | - result->version_mod, &parse_length[3]); |
105 | | - |
106 | | - /* |
107 | | - * sscanf is allowed to return EOF if no parses succeed, so make sure |
108 | | - * fields_parsed is between 1 and 4; |
109 | | - */ |
110 | | - if (fields_parsed <= 0 || fields_parsed > 4) |
111 | | - return false; |
112 | | - |
113 | | - result->has_version_mod = fields_parsed > 3; |
114 | | - |
115 | | - result->version_mod[VERSION_INFO_LEN - 1] = '\0'; |
116 | | - |
117 | | - for (i = 0; i < VERSION_INFO_LEN; i++) |
118 | | - if (!isprint(result->version_mod[i])) |
119 | | - result->version_mod[i] = '\0'; |
120 | | - |
121 | | - return ((size_t) parse_length[fields_parsed - 1]) == version_len; |
122 | | -} |
123 | | - |
124 | | -TS_FUNCTION_INFO_V1(ts_version_get_info); |
125 | | - |
126 | | -Datum |
127 | | -ts_version_get_info(PG_FUNCTION_ARGS) |
128 | | -{ |
129 | | - VersionInfo info; |
130 | | - TupleDesc tupdesc; |
131 | | - Datum values[4]; |
132 | | - bool nulls[4] = {false}; |
133 | | - HeapTuple tuple; |
134 | | - |
135 | | - version_get_info(&info); |
136 | | - |
137 | | - if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) |
138 | | - ereport(ERROR, |
139 | | - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
140 | | - errmsg("function returning record called in context " |
141 | | - "that cannot accept type record"))); |
142 | | - |
143 | | - values[0] = Int32GetDatum((int32) info.version[0]); |
144 | | - values[1] = Int32GetDatum((int32) info.version[1]); |
145 | | - values[2] = Int32GetDatum((int32) info.version[2]); |
146 | | - |
147 | | - if (info.has_version_mod) |
148 | | - values[3] = CStringGetTextDatum(info.version_mod); |
149 | | - else |
150 | | - nulls[3] = true; |
151 | | - |
152 | | - tuple = heap_form_tuple(tupdesc, values, nulls); |
153 | | - |
154 | | - return HeapTupleGetDatum(tuple); |
155 | | -} |
156 | | - |
157 | 23 | const char *git_commit = STR(EXT_GIT_COMMIT); |
158 | 24 |
|
159 | 25 | TS_FUNCTION_INFO_V1(ts_get_git_commit); |
|
0 commit comments