pike.git / lib / modules / Sql.pmod / tds.pike

version» Context lines:

pike.git/lib/modules/Sql.pmod/tds.pike:1:   /* -  * $Id: tds.pike,v 1.9 2006/02/10 16:33:48 grubba Exp $ +  * $Id: tds.pike,v 1.10 2006/02/13 14:04:17 grubba Exp $    *    * A Pike implementation of the TDS protocol.    *    * Henrik Grubbström 2006-02-08.    */      #define TDS_DEBUG -  + #define TDS_CONVERT_DEBUG      #ifdef TDS_DEBUG   #define TDS_WERROR(X...) werror("TDS:" + X)   #else   #define TDS_WERROR(X...)   #endif -  + #ifdef TDS_CONVERT_DEBUG + #define TDS_CONV_WERROR(X...) werror("TDS: Convert: " + X) + #else + #define TDS_CONV_WERROR(X...) + #endif      static int filter_noprint(int char)   {    return ((char == 32) || ((char != 0x7f) && (char & 0x60)))?char:'.';   }      static string hex_dump(string data) {    array(string) lines = data/16.0;    int off;    foreach(lines; int i; string line) {
pike.git/lib/modules/Sql.pmod/tds.pike:824:    "usertype":inp->get_smallint(),    "flags":inp->get_smallint(),    "column_type":inp->get_byte(),    ]);    res->nullable == res->flags & 0x01;    res->writeable == !!(res->flags & 0x08);    res->identity == !!(res->flags & 0x10);       res->cardinal_type = get_cardinal_type(res->column_type);    res->varint_size = get_varint_size(res->column_type); -  TDS_WERROR("Intermediate info: %O\n", res); +     switch(res->varint_size) {    case 0:    res->column_size = get_size_by_type(res->column_type);    break;    case 4:    res->column_size = inp->get_int();    break;    case 2:    res->column_size = inp->get_smallint();    break;    case 1:    res->column_size = inp->get_byte();    break;    } -  TDS_WERROR("Column size: %d bytes\n", res->column_size); +        res->timestamp = (res->cardinal_type == SYBBINARY) ||    (res->cardinal_type == TDS_UT_TIMESTAMP);       if (is_numeric_type(res->cardinal_type)) {    TDS_WERROR("is_numeric\n");    res->column_prec = inp->get_byte();    res->column_scale = inp->get_byte();    }    if (is_collate_type(res->column_type)) {    TDS_WERROR("is_collate\n");    inp->get_raw(4); // Collation    inp->get_byte(); // charset    }    if (is_blob_type(res->cardinal_type)) {    TDS_WERROR("is_blob\n");    res->table = inp->get_string(inp->get_smallint()); -  TDS_WERROR("Table name: %O\n", res->table); +     }    res->name = inp->get_string(inp->get_byte());    TDS_WERROR("Column info: %O\n", res);    return res;    }       static array(mapping(string:mixed)) tds7_process_result(InPacket inp)    {    int num_cols = inp->get_smallint();    if (num_cols == 0xffff) {
pike.git/lib/modules/Sql.pmod/tds.pike:1043:    if (info->cardinal_type == SYBDATETIME4) {    TDS_WERROR("Datetime4:%{ %d}\n", (array)raw);    }    TDS_WERROR("ROW: %O\n", raw);    return raw;    }    }       static string|int convert(string|int raw, mapping(string:mixed) info)    { -  if (!raw) return raw; /* NULL */ +  if (!raw) { +  TDS_CONV_WERROR("%O ==> NULL\n", raw); +  return raw; /* NULL */ +  }    int cardinal_type;    switch(cardinal_type = info->cardinal_type) {    case SYBCHAR:    case SYBVARCHAR:    case SYBTEXT:    case XSYBCHAR:    case XSYBVARCHAR:    case SYBNVARCHAR:    case SYBNTEXT:    case SYBLONGBINARY:    case SYBBINARY:    case SYBVARBINARY:    case SYBIMAGE:    case XSYBBINARY:    case XSYBVARBINARY: -  +  TDS_CONV_WERROR("%O ==> %O\n", raw, raw);    return raw; -  +  case SYBMONEYN:    case SYBMONEY4: -  { -  int val; -  sscanf(raw, "%-4c", val); -  if (val < 0) { -  int cents = -(val/50 - 1)/2; -  return sprintf("-%d.%02d", cents/100, cents%100); -  } else { -  int cents = (val/50 + 1)/2; -  return sprintf("%d.%02d", cents/100, cents%100); -  } -  } +     case SYBMONEY:    {    int val;    string sgn = ""; -  +  if (sizeof(raw) == 8) {    sscanf(raw, "%-8c", val); -  +  } else { +  sscanf(raw, "%-4c", val); +  }    if (val < 0) {    sgn = "-";    val = -val;    }    int cents = (val + 50)/100; -  return sprintf("%s%d.%02d", sgn, cents/100, cents%100); +  string res = sprintf("%s%d.%02d", sgn, cents/100, cents%100); +  TDS_CONV_WERROR("%O ==> %O\n", raw, res); +  return res;    }    case SYBNUMERIC: -  +  { +  string res = +  sprintf("%d", array_sscanf(raw[1..], +  "%-" + (sizeof(raw)-1) + "c")[0]); +  +  // Move decimal point @[scale] positions. +  int scale = info->column_scale; +  if (sizeof(res) < scale) { +  res = "0." + ("0" * (scale - sizeof(res))) + res; +  } else if (sizeof(res) == scale) { +  res = "0." + res; +  } else if (scale) { +  res = res[..sizeof(res)-(scale+1)] + "." + +  res[sizeof(res)-scale..]; +  } +  +  // Fix the sign. +  if (!res[0]) { +  res = "-" + res; +  } +  TDS_CONV_WERROR("%O (scale: %d) ==> %O\n", +  raw, scale, res); +  return res; +  }    case SYBDECIMAL:    case SYBREAL:    case SYBFLT8:    case SYBUNIQUE:    default:    // FIXME: -  TDS_WERROR("Not yet supported: %d\n", info->cardinal_type); +  TDS_CONV_WERROR("Not yet supported: %d (%O)\n", +  info->cardinal_type, raw);    return raw;    case SYBBIT:    case SYBBITN: -  +  TDS_CONV_WERROR("%O ==> \"%d\"", raw, !!raw[0]);    return raw[0]?"1":"0";    case SYBINT1:    case SYBINT2:    case SYBINT4:    case SYBINT8:    case SYBINTN:    {    int val;    if (raw[-1]& 0x80) {    // Negative.    val = ~array_sscanf((~raw) + ("\x00"*8), "%-8c")[0];    } else {    val = array_sscanf(raw + ("\x00"*8), "%-8c")[0];    } -  TDS_WERROR("Converted %O ==> %d\n", raw, val); +  TDS_WERROR("%O ==> \"%d\"\n", raw, val);    return sprintf("%d", val);    }    case SYBDATETIMN: -  if (sizeof(raw) == 8) cardinal_type = SYBDATETIME; -  // FALL_THROUGH +     case SYBDATETIME:    case SYBDATETIME4:    {    int day, min, sec, sec_300; -  if (cardinal_type == SYBDATETIME) { +  if (sizeof(raw) == 8) {    sscanf(raw, "%-4c%-4c", day, sec_300);    sec = sec_300/300;    sec_300 %= 300;    min = sec/60;    sec %= 60;    } else {    sscanf(raw, "%-2c%-2c", day, min);    }    int hour = min/60;    min %= 60;
pike.git/lib/modules/Sql.pmod/tds.pike:1145:    l -= (year * 1461)/4;    int yday = (l > 306)?(l - 305):(l + 60);    l += 31;    int j = (l * 80)/2447;    int mday = l - (j * 2447)/80;    l = j/11;    int mon = j + 1 - l*12;    year += (century + 15)*100 + l;    if (!l && !(year & 3) && ((year % 100) || !(year % 400)))    yday++; -  return sprintf("%04d-%02d-%02dT%02d:%02d:%02d", +  string res = sprintf("%04d-%02d-%02dT%02d:%02d:%02d",    year, mon, mday, hour, min, sec); -  +  TDS_CONV_WERROR("%O ==> %O\n", raw, res); +  return res;    }    } -  return raw; +     }       static array(string|int) process_row(InPacket inp,    array(mapping(string:mixed)) col_info)    {    if (!col_info) return 0;    array(string|int) res = allocate(sizeof(col_info));    foreach(col_info; int i; mapping(string:mixed) info) {    res[i] = convert(get_data(inp, info, i), info);    }
pike.git/lib/modules/Sql.pmod/tds.pike:1176:    {    //if (!busy) return 0; // No more rows.    while (1) {    int token_type = inp->peek_byte();    TDS_WERROR("Process row tokens: Token type: %d\n", token_type);    switch(token_type) {    case TDS_RESULT_TOKEN:    case TDS_ROWFMT2_TOKEN:    case TDS7_RESULT_TOKEN:    // Some other result starts here. -  //busy = 0; +     return 0;    case TDS_ROW_TOKEN:    inp->get_byte();    return process_row(inp, col_info);    break;    case TDS_DONE_TOKEN:    case TDS_DONEPROC_TOKEN:    case TDS_DONEINPROC_TOKEN:    if (!leave_end_token) inp->get_byte(); -  //busy = 0; +     return 0;    default:    inp->get_byte();    process_default_tokens(inp, token_type);    break;    }    }    }       static void process_login_tokens(InPacket inp)
pike.git/lib/modules/Sql.pmod/tds.pike:1286:    username = tmp[1..]*"\\";    }       this_program::server = server;    this_program::port = port;    this_program::database = database;    this_program::username = username;    this_program::password = auth;    this_program::domain = domain;    -  TDS_WERROR("Connecting to %s:%d version %d.%d\n", +  TDS_WERROR("Connecting to %s:%d with TDS version %d.%d\n",    server, port, major_version, minor_version);       socket = Stdio.File();    if (!socket->connect(server, port)) {    socket = 0;    tds_error("Failed to connect to %s:%d\n", server, port);    }    process_login_tokens(send_login());    }    }
pike.git/lib/modules/Sql.pmod/tds.pike:1442:    if (!query->params) {    result_packet = con->submit_query(query);    } else {    result_packet = con->submit_execdirect(query, query->params);    }    column_info = con->process_result_tokens(result_packet);    if (!column_info) destruct();    }   }    + static compile_query compiled_insert_id = +  compile_query("SELECT @@identity AS insert_id"); +  + int insert_id() + { +  object res = big_query(compiled_insert_id); +  array(mapping(string:mixed)) field_info = +  res->fetch_fields(); +  if (!field_info) return 0; +  array(string|int) row = res->fetch_row(); +  if (!row) return 0; +  foreach(field_info->name; int i; string name) { +  if (name == "insert_id") return (int)row[i]; +  } +  return 0; + } +    string server_info()   {    return server_data;   }      string error()   {    return last_error;   }