Skip to content

Commit

Permalink
db.describe: add json support
Browse files Browse the repository at this point in the history
  • Loading branch information
kritibirda26 committed Jul 10, 2024
1 parent 87b6ac0 commit 28829d5
Show file tree
Hide file tree
Showing 6 changed files with 528 additions and 51 deletions.
2 changes: 1 addition & 1 deletion db/db.describe/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

MODULE_TOPDIR = ../..

LIBES = $(DBMILIB) $(GISLIB)
LIBES = $(DBMILIB) $(GISLIB) $(PARSONLIB)
DEPENDENCIES = $(DBMIDEP) $(GISDEP)

PGM = db.describe
Expand Down
109 changes: 109 additions & 0 deletions db/db.describe/db.describe.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,115 @@ <h3>DBF example</h3>
[...]
</pre></div>

<h3>JSON Output</h3>
<div class="code"><pre>
db.describe mysoils
</pre></div>

<div class="code"><pre>
{
"table": "mysoils",
"description": "",
"insert": null,
"delete": null,
"ncols": 7,
"nrows": 1428,
"columns": [
{
"position": 1,
"column": "cat",
"description": "",
"type": "INTEGER",
"length": 20,
"scale": 0,
"precision": 0,
"default": null,
"nullok": true,
"select": null,
"update": null
},
{
"position": 2,
"column": "OBJECTID",
"description": "",
"type": "INTEGER",
"length": 20,
"scale": 0,
"precision": 0,
"default": null,
"nullok": true,
"select": null,
"update": null
},
{
"position": 3,
"column": "AREA",
"description": "",
"type": "DOUBLE PRECISION",
"length": 20,
"scale": 0,
"precision": 0,
"default": null,
"nullok": true,
"select": null,
"update": null
},
{
"position": 4,
"column": "PERIMETER",
"description": "",
"type": "DOUBLE PRECISION",
"length": 20,
"scale": 0,
"precision": 0,
"default": null,
"nullok": true,
"select": null,
"update": null
},
{
"position": 5,
"column": "GSLNC250_",
"description": "",
"type": "INTEGER",
"length": 20,
"scale": 0,
"precision": 0,
"default": null,
"nullok": true,
"select": null,
"update": null
},
{
"position": 6,
"column": "GSLNC250_I",
"description": "",
"type": "INTEGER",
"length": 20,
"scale": 0,
"precision": 0,
"default": null,
"nullok": true,
"select": null,
"update": null
},
{
"position": 7,
"column": "GSL_NAME",
"description": "",
"type": "CHARACTER",
"length": 6,
"scale": 0,
"precision": 0,
"default": null,
"nullok": true,
"select": null,
"update": null
}
]
}
</pre></div>

<h2>SEE ALSO</h2>

<em>
Expand Down
11 changes: 8 additions & 3 deletions db/db.describe/local_proto.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
#ifndef __LOCAL_PROTO_H__
#define __LOCAL_PROTO_H__

int print_priv(char *, int);
int print_column_definition(dbColumn *);
int print_table_definition(dbDriver *, dbTable *);
#include <grass/parson.h>

enum OutputFormat { PLAIN, JSON };

int print_priv(char *, int, enum OutputFormat, JSON_Object *);
int print_column_definition(dbColumn *, int, enum OutputFormat, JSON_Array *);
int print_table_definition(dbDriver *, dbTable *, enum OutputFormat,
JSON_Object *, JSON_Array *);

#endif /* __LOCAL_PROTO_H__ */
87 changes: 79 additions & 8 deletions db/db.describe/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
#include <grass/gis.h>
#include <grass/dbmi.h>
#include <grass/glocale.h>
#include <grass/parson.h>
#include "local_proto.h"

struct {
char *driver, *database, *table;
int printcolnames;
enum OutputFormat format;
} parms;

/* function prototypes */
Expand All @@ -40,7 +42,25 @@ int main(int argc, char **argv)
char buf[1024];
dbString stmt;

JSON_Object *root_object, *col_object;
JSON_Value *root_value, *cols_value, *col_value;
JSON_Array *cols_array;

parse_command_line(argc, argv);

if (parms.format == JSON) {
root_value = json_value_init_object();
if (root_value == NULL) {
G_fatal_error(_("Failed to initialize JSON array. Out of memory?"));
}
root_object = json_object(root_value);
cols_value = json_value_init_array();
if (cols_value == NULL) {
G_fatal_error(_("Failed to initialize JSON array. Out of memory?"));
}
cols_array = json_array(cols_value);
}

if (!db_table_exists(parms.driver, parms.database, parms.table)) {
G_warning(_("Table <%s> not found in database <%s> using driver <%s>"),
parms.table, parms.database, parms.driver);
Expand All @@ -63,25 +83,66 @@ int main(int argc, char **argv)
db_get_string(&table_name));

if (!parms.printcolnames)
print_table_definition(driver, table);
print_table_definition(driver, table, parms.format, root_object,
cols_array);
else {
ncols = db_get_table_number_of_columns(table);

db_init_string(&stmt);
sprintf(buf, "select * from %s", db_get_table_name(table));
db_set_string(&stmt, buf);
nrows = db_get_table_number_of_rows(driver, &stmt);
fprintf(stdout, "ncols: %d\n", ncols);
fprintf(stdout, "nrows: %d\n", nrows);

switch (parms.format) {
case PLAIN:
fprintf(stdout, "ncols: %d\n", ncols);
fprintf(stdout, "nrows: %d\n", nrows);
break;
case JSON:
json_object_set_number(root_object, "ncols", ncols);
json_object_set_number(root_object, "nrows", nrows);
break;
}

for (col = 0; col < ncols; col++) {
column = db_get_table_column(table, col);
fprintf(stdout, "Column %d: %s:%s:%d\n", (col + 1),
db_get_column_name(column),
db_sqltype_name(db_get_column_sqltype(column)),
db_get_column_length(column));

switch (parms.format) {
case PLAIN:
fprintf(stdout, "Column %d: %s:%s:%d\n", (col + 1),
db_get_column_name(column),
db_sqltype_name(db_get_column_sqltype(column)),
db_get_column_length(column));
break;
case JSON:
col_value = json_value_init_object();
col_object = json_object(col_value);
json_object_set_number(col_object, "position", col + 1);
json_object_set_string(col_object, "name",
db_get_column_name(column));
json_object_set_string(
col_object, "type",
db_sqltype_name(db_get_column_sqltype(column)));
json_object_set_number(col_object, "length",
db_get_column_length(column));
json_array_append_value(cols_array, col_value);
break;
}
}
}

if (parms.format == JSON) {
json_object_set_value(root_object, "columns", cols_value);
char *serialized_string = NULL;
serialized_string = json_serialize_to_string_pretty(root_value);
if (serialized_string == NULL) {
G_fatal_error(_("Failed to initialize pretty JSON string."));
}
puts(serialized_string);
json_free_serialized_string(serialized_string);
json_value_free(root_value);
}

db_close_database(driver);
db_shutdown_driver(driver);

Expand All @@ -90,7 +151,7 @@ int main(int argc, char **argv)

static void parse_command_line(int argc, char **argv)
{
struct Option *driver, *database, *table;
struct Option *driver, *database, *table, *format_opt;
struct Flag *cols;
struct GModule *module;
const char *drv, *db;
Expand All @@ -115,6 +176,9 @@ static void parse_command_line(int argc, char **argv)
if ((db = db_get_default_database_name()))
database->answer = (char *)db;

format_opt = G_define_standard_option(G_OPT_F_FORMAT);
format_opt->guisection = _("Print");

/* Set description */
module = G_define_module();
G_add_keyword(_("database"));
Expand All @@ -128,4 +192,11 @@ static void parse_command_line(int argc, char **argv)
parms.database = database->answer;
parms.table = table->answer;
parms.printcolnames = cols->answer;

if (strcmp(format_opt->answer, "json") == 0) {
parms.format = JSON;
}
else {
parms.format = PLAIN;
}
}
Loading

0 comments on commit 28829d5

Please sign in to comment.