Skip to content

Commit

Permalink
v.info: add json output for columns (OSGeo#4590)
Browse files Browse the repository at this point in the history
  • Loading branch information
NishantBansal2003 authored Nov 5, 2024
1 parent 206cabc commit 039183d
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 18 deletions.
3 changes: 2 additions & 1 deletion vector/v.info/local_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ void parse_args(int, char **, char **, char **, int *, int *, int *,
void format_double(double, char *);
void print_region(struct Map_info *, enum OutputFormat, JSON_Object *);
void print_topo(struct Map_info *, enum OutputFormat, JSON_Object *);
void print_columns(struct Map_info *, const char *, const char *);
void print_columns(struct Map_info *, const char *, const char *,
enum OutputFormat);
void print_info(struct Map_info *);
void print_shell(struct Map_info *, const char *, enum OutputFormat,
JSON_Object *);
12 changes: 6 additions & 6 deletions vector/v.info/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ int main(int argc, char *argv[])
parse_args(argc, argv, &input_opt, &field_opt, &hist_flag, &col_flag,
&shell_flag, &format);

if (format == JSON) {
root_value = json_value_init_object();
root_object = json_value_get_object(root_value);
}

/* try to open head-only on level 2 */
if (Vect_open_old_head2(&Map, input_opt, "", field_opt) < 2) {
/* force level 1, open fully
Expand All @@ -85,13 +80,18 @@ int main(int argc, char *argv[])
}
}
else if (col_flag) {
print_columns(&Map, input_opt, field_opt);
print_columns(&Map, input_opt, field_opt, format);
}
Vect_close(&Map);

return (EXIT_SUCCESS);
}

if (format == JSON) {
root_value = json_value_init_object();
root_object = json_value_get_object(root_value);
}

if ((shell_flag & SHELL_BASIC) || format == JSON) {
print_shell(&Map, field_opt, format, root_object);
}
Expand Down
88 changes: 77 additions & 11 deletions vector/v.info/print.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ void print_topo(struct Map_info *Map, enum OutputFormat format,
}

void print_columns(struct Map_info *Map, const char *input_opt,
const char *field_opt)
const char *field_opt, enum OutputFormat format)
{
int num_dblinks, col, ncols;

Expand All @@ -189,6 +189,7 @@ void print_columns(struct Map_info *Map, const char *input_opt,
num_dblinks = Vect_get_num_dblinks(Map);

if (num_dblinks <= 0) {
Vect_close(Map);
G_fatal_error(
_("Database connection for map <%s> is not defined in DB file"),
input_opt);
Expand All @@ -198,32 +199,97 @@ void print_columns(struct Map_info *Map, const char *input_opt,
"layer <%s>:"),
field_opt);

if ((fi = Vect_get_field2(Map, field_opt)) == NULL)
if ((fi = Vect_get_field2(Map, field_opt)) == NULL) {
Vect_close(Map);
G_fatal_error(
_("Database connection not defined for layer <%s> of <%s>"),
field_opt, input_opt);
}
driver = db_start_driver(fi->driver);
if (driver == NULL)
if (driver == NULL) {
Vect_close(Map);
G_fatal_error(_("Unable to open driver <%s>"), fi->driver);
}
db_init_handle(&handle);
db_set_handle(&handle, fi->database, NULL);
if (db_open_database(driver, &handle) != DB_OK)
if (db_open_database(driver, &handle) != DB_OK) {
db_shutdown_driver(driver);
Vect_close(Map);
G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
fi->database, fi->driver);
}
db_init_string(&table_name);
db_set_string(&table_name, fi->table);
if (db_describe_table(driver, &table_name, &table) != DB_OK)
if (db_describe_table(driver, &table_name, &table) != DB_OK) {
db_close_database_shutdown_driver(driver);
Vect_close(Map);
G_fatal_error(_("Unable to describe table <%s>"), fi->table);
}

JSON_Value *root_value = NULL, *columns_value = NULL, *column_value = NULL;
JSON_Object *root_object = NULL, *column_object = NULL;
JSON_Array *columns_array = NULL;

if (format == JSON) {
root_value = json_value_init_object();
root_object = json_object(root_value);
columns_value = json_value_init_array();
columns_array = json_array(columns_value);
json_object_set_value(root_object, "columns", columns_value);
}

ncols = db_get_table_number_of_columns(table);
for (col = 0; col < ncols; col++)
fprintf(stdout, "%s|%s\n",
db_sqltype_name(
db_get_column_sqltype(db_get_table_column(table, col))),
for (col = 0; col < ncols; col++) {
switch (format) {
case SHELL:
break;

case JSON:
column_value = json_value_init_object();
column_object = json_object(column_value);

json_object_set_string(
column_object, "name",
db_get_column_name(db_get_table_column(table, col)));

db_close_database(driver);
db_shutdown_driver(driver);
int sql_type =
db_get_column_sqltype(db_get_table_column(table, col));
json_object_set_string(column_object, "sql_type",
db_sqltype_name(sql_type));

int c_type = db_sqltype_to_Ctype(sql_type);
json_object_set_boolean(
column_object, "is_number",
(c_type == DB_C_TYPE_INT || c_type == DB_C_TYPE_DOUBLE));

json_array_append_value(columns_array, column_value);
break;

case PLAIN:
fprintf(stdout, "%s|%s\n",
db_sqltype_name(
db_get_column_sqltype(db_get_table_column(table, col))),
db_get_column_name(db_get_table_column(table, col)));
break;
}
}

if (format == JSON) {
char *serialized_string = NULL;
serialized_string = json_serialize_to_string_pretty(root_value);
if (serialized_string == NULL) {
json_value_free(root_value);
db_close_database_shutdown_driver(driver);
Vect_close(Map);
G_fatal_error(_("Failed to initialize pretty JSON string."));
}
puts(serialized_string);
json_free_serialized_string(serialized_string);
json_value_free(root_value);
}

Vect_destroy_field_info(fi);
db_close_database_shutdown_driver(driver);
}

void print_shell(struct Map_info *Map, const char *field_opt,
Expand Down
21 changes: 21 additions & 0 deletions vector/v.info/testsuite/test_vinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,27 @@ def test_json(self):
result.pop(field)
self.assertDictEqual(expected, result)

def test_json_column(self):
module = SimpleModule(
"v.info", map=self.test_vinfo_with_db_3d, format="json", flags="c"
)
self.runModule(module)

expected_json = {
"columns": [
{"is_number": True, "name": "cat", "sql_type": "INTEGER"},
{
"is_number": True,
"name": "elevation",
"sql_type": "DOUBLE PRECISION",
},
]
}

result = json.loads(module.outputs.stdout)

self.assertDictEqual(expected_json, result)

def test_database_table(self):
"""Test the database table column and type of the two vector maps with attribute data"""
self.assertModuleKeyValue(
Expand Down

0 comments on commit 039183d

Please sign in to comment.