Search code examples
javakdb

How to get a Date object in q when inserting from Java


According to QforMortals2, the equivalent representation of q's date is java.util.Date. Likewise, q's datetime is equal to java.sql.Timestamp.

However, when I push a table from Java to q, q automatically converts the java.util.Date object to a datetime object, which also has the time included. I then tried to push the object as being java.sql.Date and the same thing happened: again q recognised it as a datetime atom.

How can I pass Java's Date object to q such that q recognised it correctly (without the time)?

Note: I'd rather not specify the table's format beforehand ["d"$()], but would rather have that q automatically recognizes the object correctly.

Update [solved]

Thanks to user2393012 I found my error.

First of all, q does not accept inserts into an undefined table directly. However, when you call upon a process a which in turn performs an insert into a process b, it does allow inserts into undefined tables.

E.g. define a process b with \p 5002, and define a process a with:

\p 5001
h:hopen `::5002;
.u.upd:{[x;y] h (insert; x; y)};

Now when calling .u.upd, it is actually possible to insert into an undefined table in process b.

Now when using c.ks(Object), the object should consist of arrays which hold the data.

My error was that I defined the data array as

new Date[] {new java.sql.Date(new java.util.Date().getTime())}

opposed to:

new java.sql.Date[] {new java.sql.Date(new java.util.Date().getTime())}

Therefore, the java.sql.Date got parsed back into a java.util.Date when putting it in the array.

The following Java code therefore works as expected:

import java.io.IOException;
import kx.c;
import kx.c.*;

public class testingDate {

    public static c conn;

    public static void main(String[] args) throws KException, IOException {

        Object[] data     = new Object[] {new java.sql.Date[] {new java.sql.Date(new java.util.Date().getTime())}};
        c.Flip tab        = new c.Flip(new c.Dict(new String[] {"date"}, data));
        Object[] updquery = new Object[] { ".u.upd", "test", tab };

        conn = new c("localhost", 5001);

        try {
            conn.k(updquery);
        } catch (IOException e) {
            System.err.println("error sending data to server.");
        }   
    }
}

Which saves the table test in process b with content:

date      
----------
2015.03.10

Solution

  • the equivalent representation of q's date is java.util.Date. Likewise, q's datetime is equal to java.sql.Timestamp.

    If you are using c.java from https://github.com/KxSystems/kdb/blob/master/c/kx/c.java:

    Object r() {
         // read from stream
         ....
         case-14:return rd()
         ....
    }
    Date rd(){int i=ri();return new Date(i==ni?nj:gl(k+86400000L*i));}
    

    (Date there refers to java.sql.Date)

    Similarly for what you're doing, i.e. writing a Date to stream (calculating offset for 2000.01.01):

    void w(Date d){long j=d.getTime();w(j==nj?ni:(int)(lg(j)/86400000-10957));}
    

    Looking at the reference page for Java/Kx, http://code.kx.com/q/interfaces/java-client-for-q/:

    java.util.Date  -15 (=== q datetime)
    Date    -14         (=== q date)
    

    (latter is java.sql.Date)

    If you are using a third party API, it might be different of course.