Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BigInt is sometimes reported as TYPE.Int #94

Closed
derjust opened this issue Nov 7, 2014 · 0 comments
Closed

BigInt is sometimes reported as TYPE.Int #94

derjust opened this issue Nov 7, 2014 · 0 comments
Labels

Comments

@derjust
Copy link

derjust commented Nov 7, 2014

This whole issue seems to be an edge case because it happens only sometimes.
Therefore sorry in advance for all the text that follows.

I condensed the problem to the following problem so you may reproduce it (seen on MSSQL 2012 Std and Dev):

Given the following database setup:

CREATE TABLE t1 (c1 bigint, c2 int);
INSERT INTO t1 (c1, c2) VALUES(1, 2);
CREATE VIEW v1 as  (SELECT * FROM t1);

The following code just works fine

var request = new sql.Request(connection);
request.query("with tt1 as ( select * from t1 ), " +
    " tt2 as (select count(c1) as x from tt1) " +
    " select * from tt2, tt1 "
    , function (err, recordset) {
        if (err) return done(err);

        assert.equal(recordset.length, 1, 'There should be a result set');
        var tt2type = recordset.columns.x.type;
        var c1type = recordset.columns.c1.type;
        var c2type = recordset.columns.c2.type;

        assert.equal(tt2type, sql.Int);
        assert.equal(c1type, sql.BigInt);
        assert.equal(c2type, sql.Int);

        done();
});

But the following code fails as c1type becomes sql.Int

var request = new sql.Request(connection);
request.query("with tt1 as ( select * from t1 ), " +
    " tt2 as (select count(c1) as x from tt1) " +
    " select * from tt2 left outer join tt1 on 1=1 "
    , function (err, recordset) {
        if (err) return done(err);

        assert.equal(recordset.length, 1, 'There should be a result set');
        var tt2type = recordset.columns.x.type;
        var c1type = recordset.columns.c1.type;
        var c2type = recordset.columns.c2.type;

        assert.equal(tt2type, sql.Int);
        assert.equal(c1type, sql.BigInt); //This fails because now c1type === sql.Int
        assert.equal(c2type, sql.Int);

        done();
});

To me it seems that the metadata-parser is too simple. It correctly interprets the byte stream returned by the server (it says in the second example 0x38 which is in fact TYPE.Int) but does not consider dataLength at all.

For example for the example above, a TYPE.Int with a dataLength of 8 should become a TYPE.BigInt. And there are a lot of other situations where the dataLength alters the type.

The Java-guys from jTDS have a quite comprehensive list of this "type promotions":
http://grepcode.com/file/repo1.maven.org/maven2/net.sourceforge.jtds/jtds/1.3.1/net/sourceforge/jtds/jdbc/TdsData.java/#467

For those who stumble across the same problem, my workaround for the moment is this.
What it should be - I.e. while handling this tediousjs/tedious#163:

if ((column.type === sql.TYPES.BigInt)) { 
    //...whatever
}

Workaround

if ((column.type === sql.TYPES.BigInt) 
    || (column.type === sql.TYPES.Int && column.length=== 8)) {
    //...whatever
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants