Repository: SETI/rms-cspyce (language: python)

Issue:
`ekrcei` is not giving correct result
`ekrcei` is a function that reads from an integer column in a specified EK record. Here are the inputs and returns:

```
    Inputs:
      int    handle = Handle attached to EK file.
      int    segno  = Index of segment containing record.
      int    recno  = Record from which data is to be read.
      string column = Column name.
    
    Returns:
      int[*] ivals  = Integer values in column entry.
      bool   isnull = Flag indicating whether column entry is null.
```

Here is a pared-down unit test for your use:
```
import cspyce as cs
import numpy.testing as npt
import os
import pytest

from gettestkernels import TEST_FILE_DIR


def cleanup_kernel(path):
    cs.kclear()
    cs.reset()
    if os.path.isfile(path):
        os.remove(path)  # pragma: no cover
    pass


ekpath = os.path.join(TEST_FILE_DIR, "example_ekmany.ek")
tablename = "test_table_ekmany"
cleanup_kernel(ekpath)
# Create new EK and new segment with table
handle = cs.ekopn(ekpath, ekpath, 0)
decls = [
    "DATATYPE = CHARACTER*(10),   NULLS_OK = FALSE, SIZE = VARIABLE",
    "DATATYPE = DOUBLE PRECISION, NULLS_OK = FALSE, SIZE = VARIABLE",
    "DATATYPE = INTEGER,          NULLS_OK = FALSE, SIZE = VARIABLE",
]
segno = cs.ekbseg(handle, tablename, ["c1", "d1", "i1"], decls)
# Insert records:  1, 2, and 3 entries at rows 0, 1, 2, respectively
c_data = [["100"], ["101", "101"], ["102", "102", "102"]]
d_data = [[100.0], [101.0, 101.0], [102.0, 102.0, 102.0]]
i_data = [[100], [101, 101], [102, 102, 102]]
for r in range(0, 3):
    cs.ekinsr(handle, segno, r)
    cs.ekacec(handle, segno, r, "c1", c_data[r], False)
    cs.ekaced(handle, segno, r, "d1", d_data[r], False)
    cs.ekacei(handle, segno, r, "i1", i_data[r], False)
# Try record insertion beyond the next available, verify the exception
with pytest.raises(Exception):
    cs.ekinsr(handle, segno, 4)
# Close EK, then reopen for reading
cs.ekcls(handle)
cs.kclear()
handle = cs.eklef(ekpath)
assert handle is not None
# Test query using ekpsel
query = "SELECT c1, d1, i1 from {}".format(tablename)
nmrows = cs.ekfind(query)
# Validate the content of each field, including exceptions when
# Loop over rows, test .ekgc/.ekgd/.ekgi
for r in range(nmrows):
    # get row int data
    ri_data, i_null = cs.ekrcei(handle, segno, r, "i1")
    assert not i_null
    npt.assert_array_equal(ri_data, i_data[r])
```

The expected result for `ri_data` is an `int` array of size 1. However, the current output is `[4.94e-322]`. This value also needs to be 100, to match to the correct value in i_data. 

I did preemptively take a look at the `ekrcei` section in `cspyce0_part2.i`, which contains the following:

```
%rename (ekrcei) ekrcei_c;
%apply (void RETURN_VOID) {void ekrcei_c};
%apply (SpiceInt *SIZE1, SpiceDouble OUT_ARRAY1[ANY])
                {(SpiceInt *nvals, SpiceInt ivals[MAXVALS])};

extern void ekrcei_c(
        SpiceInt       handle,
        SpiceInt       segno,
        SpiceInt       recno,
        ConstSpiceChar *CONST_STRING,
        SpiceInt       *nvals, SpiceInt ivals[MAXVALS],
        SpiceBoolean   *OUTPUT
);
```

Would it be correct to assume that the `SpiceDouble` needs to be a `SpiceInt` in this case?


Discussion / hints:
It looks like you found the bug!!


On Tue, Jun 13, 2023 at 16:01 esimpsons3ti ***@***.***> wrote:

> Assigned #90 <https://github.com/SETI/pds-cspyce/issues/90> to @fyellin
> <https://github.com/fyellin>.
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/SETI/pds-cspyce/issues/90#event-9521697314>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABC2LILYUVCXRZ4RTAQQH6DXLDWLNANCNFSM6AAAAAAZFRBEFE>
> .
> You are receiving this because you were assigned.Message ID:
> ***@***.***>
>
-- 
Sent from Gmail Mobile

Great! Then I will attempt the fix and open a pull request when I can confirm functionality locally. 

Fix patch:
diff --git a/swig/cspyce0_part2.i b/swig/cspyce0_part2.i
index 5c99dab9..2948f983 100644
--- a/swig/cspyce0_part2.i
+++ b/swig/cspyce0_part2.i
@@ -5472,7 +5472,7 @@ extern void ekrced_c(
 
 %rename (ekrcei) ekrcei_c;
 %apply (void RETURN_VOID) {void ekrcei_c};
-%apply (SpiceInt *SIZE1, SpiceDouble OUT_ARRAY1[ANY])
+%apply (SpiceInt *SIZE1, SpiceInt OUT_ARRAY1[ANY])
                 {(SpiceInt *nvals, SpiceInt ivals[MAXVALS])};
 
 extern void ekrcei_c(


Test patch:
diff --git a/unittests/test_e.py b/unittests/test_e.py
index f98e047d..eb2f1e10 100644
--- a/unittests/test_e.py
+++ b/unittests/test_e.py
@@ -525,6 +525,7 @@ def test_ekifld():
 
 # Fails due to reliance on ekfind
 def fail_ekinsr_eknelt_ekpsel_ekrcec_ekrced_ekrcei():
+    cs.use_flags(cs.ekpsel)
     ekpath = os.path.join(TEST_FILE_DIR, "example_ekmany.ek")
     tablename = "test_table_ekmany"
     cleanup_kernel(ekpath)
@@ -542,9 +543,9 @@ def fail_ekinsr_eknelt_ekpsel_ekrcec_ekrced_ekrcei():
     i_data = [[100], [101, 101], [102, 102, 102]]
     for r in range(0, 3):
         cs.ekinsr(handle, segno, r)
-        cs.ekacec(handle, segno, r, "c1", len(c_data[r]), c_data[r], False)
-        cs.ekaced(handle, segno, r, "d1", len(d_data[r]), d_data[r], False)
-        cs.ekacei(handle, segno, r, "i1", len(i_data[r]), i_data[r], False)
+        cs.ekacec(handle, segno, r, "c1", c_data[r], False)
+        cs.ekaced(handle, segno, r, "d1", d_data[r], False)
+        cs.ekacei(handle, segno, r, "i1", i_data[r], False)
     # Try record insertion beyond the next available, verify the exception
     with pytest.raises(Exception):
         cs.ekinsr(handle, segno, 4)
@@ -558,23 +559,18 @@ def fail_ekinsr_eknelt_ekpsel_ekrcec_ekrced_ekrcei():
     assert handle is not None
     # Test query using ekpsel
     query = "SELECT c1, d1, i1 from {}".format(tablename)
-    n, xbegs, xends, xtypes, xclass, tabs, cols, err, errmsg = cs.ekpsel(
-        query, 99, 99, 99
-    )
-    assert n == 3
-    assert cs.stypes.csEKDataType.cs_CHR == xtypes[0]
-    assert cs.stypes.csEKDataType.cs_DP == xtypes[1]
-    assert cs.stypes.csEKDataType.cs_INT == xtypes[2]
-    assert ([cs.stypes.csEKExprClass.cs_EK_EXP_COL] * 3) == list(xclass)
-    assert (["TEST_TABLE_EKMANY"] * 3) == tabs
-    assert "C1 D1 I1".split() == cols
+    xbegs, xends, xtypes, xclass, tabs, cols, err, errmsg = cs.ekpsel(query)
+    assert xtypes[0] == 0
+    assert xtypes[1] == 1
+    assert xtypes[2] == 2
+    assert ([0] * 3) == list(xclass)
+    assert ([["TEST_TABLE_EKMANY"] * 3]) == tabs
+    assert ["C1 D1 I1".split()] == cols
     assert not err
     assert "" == errmsg
     # Run query to retrieve the row count
-    nmrows, error, errmsg = cs.ekfind(query, 99)
+    nmrows, error, errmsg = cs.ekfind(query)
     assert nmrows == 3
-    assert not error
-    assert "" == errmsg
     # test fail case for eknelt
     with pytest.raises(Exception):
         cs.eknelt(0, nmrows + 1)
@@ -594,25 +590,23 @@ def fail_ekinsr_eknelt_ekpsel_ekrcec_ekrced_ekrcei():
             assert not d_null
             assert d_datum == d_data[r][e]
             # get row char data
-            c_datum, c_null = cs.ekgc(0, r, e)
+            c_datum, c_null, __ = cs.ekgc(0, r, e)
             assert not c_null
             assert c_datum == c_data[r][e]
     # Loop over rows, test .ekrcec/.ekrced/.ekrcei
     for r in range(nmrows):
         # get row int data
-        ni_vals, ri_data, i_null = cs.ekrcei(handle, segno, r, "i1")
+        ri_data, i_null = cs.ekrcei(handle, segno, r, "i1")
         assert not i_null
-        assert ni_vals == r + 1
+
         npt.assert_array_equal(ri_data, i_data[r])
         # get row double data
-        nd_vals, rd_data, d_null = cs.ekrced(handle, segno, r, "d1")
+        rd_data, d_null = cs.ekrced(handle, segno, r, "d1")
         assert not d_null
-        assert nd_vals == r + 1
         npt.assert_array_equal(rd_data, d_data[r])
         # get row char data
-        nc_vals, rc_data, c_null = cs.ekrcec(handle, segno, r, "c1", 11)
+        rc_data, c_null = cs.ekrcec(handle, segno, r, "c1")
         assert not c_null
-        assert nc_vals == r + 1
         assert rc_data == c_data[r]
     # test out of bounds
     with pytest.raises(Exception):