gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master 730ece3 3/3: Query: new option to sort downloa


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 730ece3 3/3: Query: new option to sort downloaded data by certain column
Date: Wed, 20 Jan 2021 19:37:42 -0500 (EST)

branch: master
commit 730ece32514385a55a5225d939d1f97327520fae
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Query: new option to sort downloaded data by certain column
    
    Until now, the order of the retrieved datasets was determined by the server
    that provided the data. But this was annoying when a certain order is
    needed (an extra call to 'asttable' would be necessary). However, ADQL does
    have features to support sorting on the server.
    
    With this commit, the ADQL feature of 'ORDER BY' has been implemented as
    the '--sort' option on the command-line.
---
 bin/query/args.h  | 13 +++++++++++
 bin/query/main.h  |  1 +
 bin/query/tap.c   | 69 +++++++++++++++++++++++++++++++++++++++++++------------
 bin/query/ui.c    |  8 +++----
 bin/query/ui.h    |  1 +
 doc/gnuastro.texi |  6 +++++
 6 files changed, 79 insertions(+), 19 deletions(-)

diff --git a/bin/query/args.h b/bin/query/args.h
index e2c5f76..58df1f9 100644
--- a/bin/query/args.h
+++ b/bin/query/args.h
@@ -241,6 +241,19 @@ struct argp_option program_options[] =
       GAL_OPTIONS_NOT_MANDATORY,
       GAL_OPTIONS_NOT_SET,
     },
+    {
+      "sort",
+      UI_KEY_SORT,
+      "STR[,STR]",
+      0,
+      "Sort based on values of given columns.",
+      UI_GROUP_GENQUERY,
+      &p->sort,
+      GAL_TYPE_STRLL,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
 
 
 
diff --git a/bin/query/main.h b/bin/query/main.h
index fffd53e..97f0aa4 100644
--- a/bin/query/main.h
+++ b/bin/query/main.h
@@ -56,6 +56,7 @@ struct queryparams
   gal_data_t           *radius;  /* Radius around center.              */
   gal_data_t            *range;  /* Range of magnitudes to query.      */
   gal_list_str_t      *noblank;  /* Return rows that aren't blank.     */
+  gal_list_str_t         *sort;  /* Sort output by given column(s).    */
   gal_data_t            *width;  /* Width of box around center.        */
   char                  *query;  /* Raw query string.                  */
   gal_list_str_t      *columns;  /* Columns to extract from database.  */
diff --git a/bin/query/tap.c b/bin/query/tap.c
index 61fc57f..064e25a 100644
--- a/bin/query/tap.c
+++ b/bin/query/tap.c
@@ -231,14 +231,14 @@ tap_query_construct_noblank(struct queryparams *p, char 
**outstr)
         {
           if( asprintf(&noblankstr, "%s AND %s IS NOT NULL",
                        prevstr, tmp->v) < 0 )
-            error(EXIT_FAILURE, 0, "%s: asprintf allocation ('rangestr')",
-                  __func__);
+            error(EXIT_FAILURE, 0,
+                  "%s: asprintf allocation ('noblankstr', 1)", __func__);
           free(prevstr);
         }
       else
         if( asprintf(&noblankstr, "%s IS NOT NULL", tmp->v) < 0 )
-          error(EXIT_FAILURE, 0, "%s: asprintf allocation ('rangestr')",
-                __func__);
+          error(EXIT_FAILURE, 0,
+                "%s: asprintf allocation ('noblankstr', 2)", __func__);
 
       /* Put the 'rangestr' in previous-range string for the next
          round.*/
@@ -268,15 +268,15 @@ tap_query_construct_range(struct queryparams *p, char 
**outstr)
         {
           if( asprintf(&rangestr, "%s AND %s>=%g AND %s<=%g", prevstr,
                        tmp->name, darray[0], tmp->name, darray[1]) < 0 )
-            error(EXIT_FAILURE, 0, "%s: asprintf allocation ('rangestr')",
-                  __func__);
+            error(EXIT_FAILURE, 0,
+                  "%s: asprintf allocation ('rangestr', 1)", __func__);
           free(prevstr);
         }
       else
         if( asprintf(&rangestr, "%s>=%g AND %s<=%g",
                      tmp->name, darray[0], tmp->name, darray[1]) < 0 )
-          error(EXIT_FAILURE, 0, "%s: asprintf allocation ('rangestr')",
-                __func__);
+          error(EXIT_FAILURE, 0,
+                "%s: asprintf allocation ('rangestr', 2)", __func__);
 
       /* Put the 'rangestr' in previous-range string for the next
          round.*/
@@ -291,12 +291,47 @@ tap_query_construct_range(struct queryparams *p, char 
**outstr)
 
 
 
+static char *
+tap_query_construct_sort(struct queryparams *p)
+{
+  gal_list_str_t *tmp;
+  char *sortstr=NULL, *prevstr=NULL;
+
+  for(tmp=p->sort; tmp!=NULL; tmp=tmp->next)
+    {
+      /* Write 'rangestr'. */
+      if(prevstr)
+        {
+          if( asprintf(&sortstr, "%s,%s", prevstr, tmp->v) < 0 )
+            error(EXIT_FAILURE, 0,
+                  "%s: asprintf allocation ('sortstr', 1)", __func__);
+          free(prevstr);
+        }
+      else
+        if( asprintf(&sortstr, "ORDER BY %s", tmp->v) < 0 )
+          error(EXIT_FAILURE, 0,
+                "%s: asprintf allocation ('sortstr', 2)", __func__);
+
+      /* Put the 'rangestr' in previous-range string for the next
+         round.*/
+      prevstr=sortstr;
+    }
+
+  /* Set the final output pointer. */
+  return sortstr;
+}
+
+
+
+
+
 /* Construct the query for data download. */
 static char *
 tap_query_construct_data(struct queryparams *p)
 {
-  char *datasetstr, *valuelimitstr=NULL;
+  char *sortstr=NULL;
   char *headstr=NULL, allcols[]="*";
+  char *datasetstr, *valuelimitstr=NULL;
   char *querystr, *columns, *spatialstr=NULL;
 
   /* If the dataset has special characters (like a slash) it needs to
@@ -313,25 +348,29 @@ tap_query_construct_data(struct queryparams *p)
       error(EXIT_FAILURE, 0, "%s: asprintf allocation ('head')",
             __func__);
 
-  /* If the user has asked for a spatial constraint. */
-  if(p->overlapwith || p->center)
-    spatialstr=tap_query_construct_spatial(p);
-
   /* Build the 'noblank' and 'range' criteria. No blank goes first because
      it is easier to check (for the server), thus the more time-consuming
      range check can be done on fewer rows. */
   if(p->noblank) tap_query_construct_noblank(p, &valuelimitstr);
   if(p->range) tap_query_construct_range(p, &valuelimitstr);
 
+  /* If the user has asked for a spatial constraint. */
+  if(p->overlapwith || p->center)
+    spatialstr=tap_query_construct_spatial(p);
+
+  /* If the user has asked to sort the columns. */
+  if(p->sort) sortstr=tap_query_construct_sort(p);
+
   /* Write the automatically generated query string.  */
-  if( asprintf(&querystr,  "'SELECT %s %s FROM %s %s %s %s %s'",
+  if( asprintf(&querystr,  "'SELECT %s %s FROM %s %s %s %s %s %s'",
                headstr ? headstr : "",
                columns,
                datasetstr,
                ( valuelimitstr || spatialstr ? "WHERE" : ""),
                valuelimitstr ? valuelimitstr : "",
                ( valuelimitstr && spatialstr ? "AND"   : "" ),
-               spatialstr ? spatialstr : "")<0 )
+               spatialstr ? spatialstr : "",
+               sortstr ? sortstr : "")<0 )
     error(EXIT_FAILURE, 0, "%s: asprintf allocation ('querystr')",
           __func__);
 
diff --git a/bin/query/ui.c b/bin/query/ui.c
index bef6e7d..ed37313 100644
--- a/bin/query/ui.c
+++ b/bin/query/ui.c
@@ -313,10 +313,10 @@ ui_read_check_only_options(struct queryparams *p)
       p->dec_name=p->ccol->next->v;
     }
 
-  /* If '--noblank' is given (possibly multiple times, each with multiple
-     column names) break it up into individual names. */
-  if(p->noblank)
-    gal_options_merge_list_of_csv(&p->noblank);
+  /* If '--noblank' or '--sort' are given (possibly multiple times, each
+     with multiple column names) break it up into individual names. */
+  if(p->sort)    gal_options_merge_list_of_csv(&p->sort);
+  if(p->noblank) gal_options_merge_list_of_csv(&p->noblank);
 
   /* Make sure that '--query' and '--center' are not called together. */
   if(p->query && (p->center || p->overlapwith) )
diff --git a/bin/query/ui.h b/bin/query/ui.h
index e38c134..4f960f2 100644
--- a/bin/query/ui.h
+++ b/bin/query/ui.h
@@ -66,6 +66,7 @@ enum option_keys_enum
   /* Only with long version (start with a value 1000, the rest will be set
      automatically). */
   UI_KEY_CCOL            = 1000,
+  UI_KEY_SORT,
 };
 
 
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index c50e195..8b50b8a 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -10744,6 +10744,12 @@ Then you can edit it to be non-inclusive on your 
desired side.
 Only ask for rows that don't have a blank value in the @code{STR} column.
 This option can be called many times, and each call can have multiple column 
names (separated by a comma or @key{,}).
 For example if you want the retrieved rows to not have a blank value in 
columns @code{A}, @code{B}, @code{C} and @code{D}, you can use 
@command{--noblank=A -bB,C,D}.
+
+@item --sort=STR[,STR]
+Ask for the server to sort the downloaded data based on the given columns.
+For example let's assume your desired catalog has column @code{Z} for redshift 
and column @code{MAG_R} for magnitude in the R band.
+When you call @option{--sort=Z,MAG_R}, it will primarily sort the columns 
based on the redshift, but if two objects have the same redshift, they will be 
sorted by magnitude.
+You can add as many columns as you like for higher-level sorting.
 @end table
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]