1 /* 2 3 -Procedure ekpsel_c ( EK, parse SELECT clause ) 4 5 -Abstract 6 7 Parse the SELECT clause of an EK query, returning full particulars 8 concerning each selected item. 9 10 -Disclaimer 11 12 THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE 13 CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. 14 GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE 15 ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE 16 PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" 17 TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY 18 WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A 19 PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC 20 SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE 21 SOFTWARE AND RELATED MATERIALS, HOWEVER USED. 22 23 IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA 24 BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT 25 LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, 26 INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, 27 REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE 28 REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. 29 30 RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF 31 THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY 32 CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE 33 ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. 34 35 -Required_Reading 36 37 None. 38 39 -Keywords 40 41 PRIVATE 42 43 */ 44 45 #include "SpiceUsr.h" 46 #include "SpiceZfc.h" 47 #include "SpiceZst.h" 48 #include "SpiceZmc.h" 49 50 ekpsel_c(ConstSpiceChar * query,SpiceInt msglen,SpiceInt tablen,SpiceInt collen,SpiceInt * n,SpiceInt * xbegs,SpiceInt * xends,SpiceEKDataType * xtypes,SpiceEKExprClass * xclass,void * tabs,void * cols,SpiceBoolean * error,SpiceChar * errmsg)51 void ekpsel_c ( ConstSpiceChar * query, 52 SpiceInt msglen, 53 SpiceInt tablen, 54 SpiceInt collen, 55 SpiceInt * n, 56 SpiceInt * xbegs, 57 SpiceInt * xends, 58 SpiceEKDataType * xtypes, 59 SpiceEKExprClass * xclass, 60 void * tabs, 61 void * cols, 62 SpiceBoolean * error, 63 SpiceChar * errmsg ) 64 /* 65 66 -Brief_I/O 67 68 Variable I/O Description 69 -------- --- -------------------------------------------------- 70 query I EK query. 71 msglen I Available space in the output error message string. 72 tablen I Length of strings in `tabs' output array. 73 collen I Length of strings in `cols' output array. 74 n O Number of items in SELECT clause of query. 75 xbegs O Begin positions of expressions in SELECT clause. 76 xends O End positions of expressions in SELECT clause. 77 xtypes O Data types of expressions. 78 xclass O Classes of expressions. 79 tabs O Names of tables qualifying SELECT columns. 80 cols O Names of columns in SELECT clause of query. 81 error O Error flag. 82 errmsg O Parse error message. 83 84 -Detailed_Input 85 86 query is a character string containing an EK query. 87 EK queries have the general form 88 89 SELECT <select expr>, <select expr>, ... 90 FROM <table spec>, <table spec>, ... 91 [WHERE <constraint list>] 92 [ORDER BY <order-by column list>] 93 94 Here the symbol <select expr> indicates any 95 expression representing an entity that can be 96 selected. Commonly, the selected items are 97 columns, with or without qualifying table names, 98 having the form 99 100 <column name> 101 <table name>.<column name> 102 <table alias>.<column name> 103 104 but more general expressions may also be selected. 105 Examples are functions, such as 106 107 COUNT(*) 108 COUNT( <table name>.<column name> ) 109 MAX ( <table name>.<column name> ) 110 111 or expressions involving constants, such as 112 113 2 * <column name> 114 115 116 msglen The allowed length for the output message string. 117 This length must large enough to hold the output 118 string plus the terminator. If the output string is 119 expected to have x characters, msglen needs to be 120 x + 1. 121 122 tablen The length of the strings in the output table array. 123 This length must large enough to hold the output 124 strings plus the terminator. If the output strings 125 are expected to have x characters, tablen needs to be 126 x + 1. The parameter SPICE_EK_TSTRLN defines a string 127 length sufficient to hold any table name. This 128 parameter is defined by SpiceUsr.h. 129 130 collen The length of the strings in the output column array. 131 This length must large enough to hold the output 132 strings plus the terminator. If the output strings 133 are expected to have x characters, collen needs to be 134 x + 1. The parameter SPICE_EK_CSTRLN defines a string 135 length sufficient to hold any table name. This 136 parameter is defined by SpiceUsr.h. 137 138 -Detailed_Output 139 140 n is the number of items specified in the 141 SELECT clause of the input query. 142 143 xbegs, 144 xends are, respectively, arrays of begin and end 145 positions of expressions designating items in the 146 SELECT clause of the input query. The ith 147 expression is located in the substring 148 149 query[ xbegs[i] ]...query[ xends[i] ] 150 151 152 xtypes is an array of values of type SpiceEKDataType giving 153 types of the expressions in the SELECT clause. 154 Values and meanings of xtypes are: 155 156 SPICE_CHR Character type 157 SPICE_DP Double precision type 158 SPICE_INT Integer type 159 SPICE_TIME Time type 160 161 The ith element of xtypes refers to the ith 162 selected item. 163 164 The data type of an expression indicates which 165 fetch routine to use to obtain values of the 166 selected expression. The mapping of data types 167 to fetch routines is shown below: 168 169 SPICE_CHR ekgc_c 170 SPICE_DP ekgd_c 171 SPICE_INT ekgi_c 172 SPICE_TIME ekgd_c 173 174 Note that time values are stored as d.p. numbers. 175 176 177 xclass is an array of values of type SpiceEKExprClass giving 178 the classes of the expressions occurring in the SELECT 179 clause of the input query. Values and meanings of 180 xclass are: 181 182 SPICE_EK_EXP_COL Selected item was a column. 183 The column may qualified by a 184 table name. 185 186 SPICE_EK_EXP_FUNC Selected item was a simple 187 function invocation of the 188 form 189 190 F ( <column> ) 191 192 or else was 193 194 COUNT(*) 195 196 SPICE_EK_EXP_EXPR Selected item was a more 197 general expression than those 198 shown above. 199 200 The Ith element of xclass refers to the Ith 201 selected item. 202 203 When a selected item is a column, the values of 204 the arguments tabs and cols (discussed below) are 205 defined. 206 207 208 tabs is an array of names of tables corresponding to 209 the columns in the SELECT clause. The ith element 210 of tabs corresponds to the table containing the 211 ith SELECT column. Table names returned in tabs 212 are the actual names of tables in loaded EKs, not 213 aliases supplied in the input query. Table names 214 are supplied even if the corresponding column was 215 unqualified in the input query, as long as the 216 column name was unambiguous. 217 218 The contents of tabs[i] are defined if and only if 219 the returned value of xclass[i] is SPICE_EK_EXP_COL. 220 221 The caller should declare `tabs' as an array of strings 222 of length 223 224 SPICE_EK_TSTRLN 225 226 for example 227 228 SpiceChar tabs[SPICE_EK_MAXQSEL][SPICE_EK_TSTRLN]; 229 230 231 232 cols is an array containing the columns of the SELECT 233 clause. The contents of cols[i] are defined if and 234 only if the returned value of xclass[i] is 235 SPICE_EK_EXP_COL. 236 237 The caller should declare `cols' as an array of strings 238 of length 239 240 SPICE_EK_CSTRLN 241 242 for example 243 244 SpiceChar tabs[SPICE_EK_MAXQSEL][SPICE_EK_CSTRLN]; 245 246 247 error is a logical flag indicating whether the input 248 query parsed correctly. The other outputs of this 249 routine, except for errmsg, are undefined if a 250 parse error occurred. error is returned SPICETRUE if 251 a parse error occurred, SPICEFALSE otherwise. 252 253 errmsg is a character string describing the cause of a 254 parse error, if such an error occurred. Otherwise, 255 errmsg is returned empty. 256 257 -Parameters 258 259 None. 260 261 -Exceptions 262 263 1) Parse failures do not cause this routine to signal errors; 264 instead, the error and errmsg outputs indicate invalid 265 QUERIES. 266 267 2) Queries cannot be parsed correctly unless at least one EK 268 is loaded. 269 270 -Files 271 272 None. 273 274 -Particulars 275 276 This routine allows callers of the EK fetch routines to determine 277 at run time the attributes of the columns from which data is to be 278 fetched. 279 280 -Examples 281 282 1) Use of ekpsel_c to assist in fetching rows matching queries 283 supplied at run time. 284 285 The code fragment shown here does not rely on advance 286 knowledge of the input query or the contents of any loaded EK 287 files. 288 289 To simplify the example, we assume that all columns are scalar- 290 valued. 291 292 293 #include "SpiceUsr.h" 294 #include <stdio.h> 295 #include <string.h> 296 297 298 void main() 299 { 300 /. 301 The kernel names that appear here are examples; to use this 302 program, you would have to replace these names with those of 303 kernels available on your own system. 304 ./ 305 #define EK "/kernels/galileo/ek/EK97148A.BSE" 306 #define LSK "/kernels/gen/lsk/leapseconds.ker" 307 #define MSGLEN 320 308 #define LNSIZE 80 309 #define TIMELEN 25 310 311 SpiceBoolean error; 312 SpiceBoolean found; 313 SpiceBoolean null; 314 315 SpiceChar cdata [LNSIZE]; 316 SpiceChar cols [SPICE_EK_MAXQSEL] 317 [SPICE_EK_CSTRLN]; 318 SpiceChar errmsg [MSGLEN]; 319 SpiceChar outstr [LNSIZE]; 320 SpiceChar * query; 321 SpiceChar tabs [SPICE_EK_MAXQSEL] 322 [SPICE_EK_TSTRLN]; 323 SpiceChar utc [TIMELEN]; 324 325 SpiceDouble ddata; 326 SpiceDouble tdata; 327 328 SpiceEKDataType xtypes [SPICE_EK_MAXQSEL]; 329 SpiceEKExprClass xclass [SPICE_EK_MAXQSEL]; 330 331 SpiceInt col; 332 SpiceInt exprlen; 333 SpiceInt handle; 334 SpiceInt idata; 335 SpiceInt n; 336 SpiceInt nmrows; 337 SpiceInt row; 338 339 SpiceInt xbegs [SPICE_EK_MAXQSEL]; 340 SpiceInt xends [SPICE_EK_MAXQSEL]; 341 342 343 344 /. 345 Load leapseconds and E-kernels. 346 ./ 347 furnsh_c ( LSK ); 348 eklef_c ( EK, &handle ); 349 350 351 while ( SPICETRUE ) 352 { 353 354 /. 355 Prompt for query. Parse the SELECT clause using ekpsel_c. 356 ./ 357 query = prompt_c ( "Enter query > " ); 358 359 ekpsel_c ( query, 360 MSGLEN, 361 &n, 362 xbegs, 363 xends, 364 xtypes, 365 xclass, 366 tabs, 367 cols, 368 &error, 369 errmsg ); 370 371 if ( error ) 372 { 373 printf ( "Error: <%s>\n", errmsg ); 374 } 375 376 else 377 { 378 /. 379 Submit query to the EK query system. 380 ./ 381 382 ekfind_c ( query, MSGLEN, &nmrows, &error, errmsg ); 383 384 if ( error ) 385 { 386 printf ( "Error found: %s\n", errmsg ); 387 } 388 389 else 390 { 391 printf ( "Number of matching rows = %d\n", nmrows ); 392 393 /. 394 Fetch the rows that matched the query. 395 ./ 396 397 for ( row = 0; row < nmrows; row++ ) 398 { 399 /. 400 Fetch data from the current row. 401 ./ 402 403 printf ( "\nROW = %d\n", row ); 404 405 406 for ( col = 0; col < n; col++ ) 407 { 408 /. 409 Fetch data from the current selected column. 410 ./ 411 412 if ( xclass[col] == SPICE_EK_EXP_COL ) 413 { 414 printf ( "COLUMN = %s.%s\n", 415 tabs[col], 416 cols[col] ); 417 } 418 else 419 { 420 exprlen = xends[col] - xbegs[col] + 1; 421 422 strncpy ( outstr, query+xbegs[col], 423 exprlen ); 424 425 outstr[exprlen] = (char)0; 426 427 printf ( "%s\n", outstr ); 428 } 429 430 431 /. 432 Write out the data. 433 ./ 434 435 switch ( xtypes[col] ) 436 { 437 case SPICE_CHR: 438 439 ekgc_c ( col, row, 0, LNSIZE, 440 cdata, &null, &found ); 441 442 if ( !null ) 443 { 444 printf ( "%s\n", cdata ); 445 } 446 447 break; 448 449 450 case SPICE_DP: 451 452 ekgd_c ( col, row, 0, 453 &ddata, &null, &found ); 454 455 if ( !null ) 456 { 457 printf ( "%f\n", ddata ); 458 } 459 460 break; 461 462 463 case SPICE_INT: 464 465 ekgi_c ( col, row, 0, 466 &idata, &null, &found ); 467 468 if ( !null ) 469 { 470 printf ( "%d\n", cdata ); 471 } 472 473 break; 474 475 476 case SPICE_TIME: 477 478 /. 479 The item is a time value. Convert it 480 to UTC for output. 481 ./ 482 483 ekgd_c ( col, row, 0, 484 &tdata, &null, &found ); 485 486 if ( !null ) 487 { 488 et2utc_c ( tdata, "C", 3, 489 TIMELEN, utc ); 490 491 printf ( "%s\n", utc ); 492 } 493 494 break; 495 496 497 default: 498 499 ; 500 } 501 502 /. 503 Handle null values here. 504 ./ 505 506 if ( null ) 507 { 508 printf ( "%s\n", "<Null>" ); 509 } 510 511 /. 512 End of data type switch. 513 ./ 514 515 } 516 /. 517 We're done with the column having index col. 518 ./ 519 } 520 /. 521 We're done with the row having index row. 522 ./ 523 } 524 /. 525 We either processed the query or ekfind_c detected an 526 error. 527 ./ 528 } 529 /. 530 We either parsed the SELECT clause or ekpsel_c detected an 531 error. 532 ./ 533 534 } 535 536 } 537 538 539 540 541 -Restrictions 542 543 1) Currently, column names are the only supported expressions. 544 545 -Literature_References 546 547 None. 548 549 -Author_and_Institution 550 551 N.J. Bachman (JPL) 552 553 -Version 554 555 -CSPICE Version 2.1.2, 22-MAR-2016 (NJB) 556 557 Updated brief I/O to describe inputs `tablen' and `collen'. 558 Also added to Detailed_Output descriptions of declarations 559 of the outputs `tabs' and 'cols'. 560 561 -CSPICE Version 2.1.1, 14-AUG-2006 (EDW) 562 563 Replace mention of ldpool_c with furnsh_c. 564 565 -CSPICE Version 2.1.0, 02-SEP-1999 (NJB) 566 567 Local type logical variable now used for error flag used in 568 interface of ekpsel_. 569 570 -CSPICE Version 2.0.0, 19-JUL-1999 (NJB) 571 572 The data types of the tabs and cols arguments were changed 573 to (void *), and associated string length arguments were added. 574 This style of interface for string arrays is now standard within 575 CSPICE. 576 577 Some corrections of the header comments were made. 578 579 -CSPICE Version 1.0.0, 21-FEB-1999 (NJB) 580 581 -Index_Entries 582 583 parse select clause of EK query 584 585 -& 586 */ 587 588 { /* Begin ekpsel_c */ 589 590 591 /* 592 Local constants 593 594 595 XCLASSLEN is the maximum length of a short string indicating the 596 class of a SELECT clause item in a QUERY. The set of expected 597 strings is defined by the Fortran SPICELIB routine EKPSEL. The 598 current set of strings is {"COL", "FUNC", "EXPR"}. 599 */ 600 #define XCLASSLEN 4 601 602 603 /* 604 TYPSIZ is the string length associated with the array locXtypes. 605 */ 606 #define TYPSIZ ( SPICE_EK_TYPLEN + 1 ) 607 608 609 /* 610 EXPSIZ is the string length associated with the array locXclass. 611 */ 612 #define EXPSIZ ( XCLASSLEN + 1 ) 613 614 615 /* 616 Local variables 617 */ 618 logical err; 619 620 SpiceChar locXtypes[SPICE_EK_MXCLSG][TYPSIZ]; 621 SpiceChar locXclass[SPICE_EK_MXCLSG][EXPSIZ]; 622 SpiceChar * strptr; 623 624 SpiceInt i; 625 SpiceInt lastnb; 626 627 628 629 /* 630 Participate in error tracing. 631 */ 632 633 chkin_c ( "ekpsel_c" ); 634 635 /* 636 Check the input query string to make sure the pointer is non-null and 637 the string length is non-zero. 638 */ 639 CHKFSTR ( CHK_STANDARD, "ekpsel_c", query ); 640 641 642 /* 643 Make sure the output error message string has at least enough room 644 for one output character and a null terminator. Also check for a 645 null pointer. 646 */ 647 CHKOSTR ( CHK_STANDARD, "ekpsel_c", errmsg, msglen ); 648 649 650 /* 651 Call the f2c'd function. 652 */ 653 ekpsel_ ( ( char * ) query, 654 ( integer * ) n, 655 ( integer * ) xbegs, 656 ( integer * ) xends, 657 ( char * ) locXtypes, 658 ( char * ) locXclass, 659 ( char * ) tabs, 660 ( char * ) cols, 661 ( logical * ) &err, 662 ( char * ) errmsg, 663 ( ftnlen ) strlen(query), 664 ( ftnlen ) SPICE_EK_TYPLEN, 665 ( ftnlen ) XCLASSLEN, 666 ( ftnlen ) tablen-1, 667 ( ftnlen ) collen-1, 668 ( ftnlen ) msglen-1 ); 669 670 671 /* 672 Assign the SpiceBoolean error flag. 673 */ 674 675 *error = err; 676 677 678 if ( failed_c() ) 679 { 680 chkout_c ( "ekpsel_c" ); 681 return; 682 } 683 684 685 /* 686 Convert the error message to a C style string. 687 */ 688 F2C_ConvertStr ( msglen, errmsg ); 689 690 691 /* 692 If there was a parse error, the other outputs are undefined. 693 */ 694 if ( *error ) 695 { 696 chkout_c ( "ekpsel_c" ); 697 return; 698 } 699 700 701 /* 702 Map the token begin and end indices from Fortran to C style. 703 */ 704 for ( i = 0; i < *n; i++ ) 705 { 706 xbegs[i]--; 707 xends[i]--; 708 } 709 710 711 /* 712 Map the expression data types from strings to SpiceEKDataType values. 713 First, map the Fortran-style strings returned by ekpsel_ to C 714 style strings. 715 */ 716 F2C_ConvertStrArr ( *n, TYPSIZ, (SpiceChar *)locXtypes ); 717 718 719 for ( i = 0; i < *n; i++ ) 720 { 721 if ( eqstr_c( locXtypes[i], "CHR" ) ) 722 { 723 xtypes[i] = SPICE_CHR; 724 } 725 726 else if ( eqstr_c( locXtypes[i], "DP" ) ) 727 { 728 xtypes[i] = SPICE_DP; 729 } 730 731 else if ( eqstr_c( locXtypes[i], "INT" ) ) 732 { 733 xtypes[i] = SPICE_INT; 734 } 735 736 else if ( eqstr_c( locXtypes[i], "TIME" ) ) 737 { 738 xtypes[i] = SPICE_TIME; 739 } 740 741 else 742 { 743 setmsg_c ( "Unrecognized data type string <#> returned " 744 "by ekpsel_ for item #." ); 745 errch_c ( "#", locXtypes[i] ); 746 errint_c ( "#", i ); 747 sigerr_c ( "SPICE(BUG)" ); 748 chkout_c ( "ekpsel_c" ); 749 return; 750 } 751 } 752 753 /* 754 Map the expression classes from strings to SpiceEKExprClass values. 755 First, map the Fortran-style strings returned by ekpsel_ to C 756 style strings. 757 */ 758 F2C_ConvertStrArr ( *n, EXPSIZ, (SpiceChar *)locXclass ); 759 760 for ( i = 0; i < *n; i++ ) 761 { 762 if ( eqstr_c( locXclass[i], "COL" ) ) 763 { 764 xclass[i] = SPICE_EK_EXP_COL; 765 } 766 767 else if ( eqstr_c( locXclass[i], "FUNC" ) ) 768 { 769 xclass[i] = SPICE_EK_EXP_FUNC; 770 } 771 772 else if ( eqstr_c( locXclass[i], "EXPR" ) ) 773 { 774 xclass[i] = SPICE_EK_EXP_EXPR; 775 } 776 777 else 778 { 779 setmsg_c ( "Unrecognized item class string <#> returned " 780 "by ekpsel_ for item #." ); 781 errch_c ( "#", locXclass[i] ); 782 errint_c ( "#", i ); 783 sigerr_c ( "SPICE(BUG)" ); 784 chkout_c ( "ekpsel_c" ); 785 return; 786 } 787 } 788 789 790 /* 791 Convert the array of table names to a C style array of strings. 792 Null-terminate each string so as to eliminate trailing blanks. 793 */ 794 F2C_ConvertStrArr ( *n, tablen, (SpiceChar *)tabs ); 795 796 for ( i = 0; i < *n; i++ ) 797 { 798 strptr = ((SpiceChar *)tabs) + i*tablen; 799 800 lastnb = F_StrLen ( tablen-1, strptr ); 801 802 *( strptr + lastnb ) = (char)0; 803 } 804 805 /* 806 Convert the array of column names to a C style array of strings. 807 Null-terminate each string so as to eliminate trailing blanks. 808 */ 809 F2C_ConvertStrArr ( *n, collen, (SpiceChar *)cols ); 810 811 for ( i = 0; i < *n; i++ ) 812 { 813 strptr = ((SpiceChar *)cols) + i*collen; 814 815 lastnb = F_StrLen ( collen-1, strptr ); 816 817 *( strptr + lastnb ) = (char)0; 818 } 819 820 821 chkout_c ( "ekpsel_c" ); 822 823 } /* End ekpsel_c */ 824