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

Make result field values accessible by name on BinaryDataPackets, too #8

Merged
merged 3 commits into from
Apr 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion connection.options
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ user=root
port=3306
db=sqljockeytest
#defaults to localhost
host=localhost
host=localhost
40 changes: 14 additions & 26 deletions lib/src/prepared_statements/binary_data_packet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,21 @@ import '../results/field.dart';
import '../results/row.dart';

class BinaryDataPacket extends Row {
List<Object> values;
final Logger log;
final Logger log = new Logger("BinaryDataPacket");

BinaryDataPacket.forTests(this.values) : log = new Logger("BinaryDataPacket");
BinaryDataPacket.forTests(List _values) {
values = _values;
}

BinaryDataPacket(Buffer buffer, List<Field> fields)
: log = new Logger("BinaryDataPacket") {
BinaryDataPacket(Buffer buffer, List<Field> fieldPackets) {
buffer.skip(1);
var nulls = buffer.readList(((fields.length + 7 + 2) / 8).floor().toInt());
var nulls =
buffer.readList(((fieldPackets.length + 7 + 2) / 8).floor().toInt());
log.fine("Nulls: $nulls");
var nullMap = new List<bool>(fields.length);
var nullMap = new List<bool>(fieldPackets.length);
var shift = 2;
var byte = 0;
for (var i = 0; i < fields.length; i++) {
for (var i = 0; i < fieldPackets.length; i++) {
var mask = 1 << shift;
nullMap[i] = (nulls[byte] & mask) != 0;
shift++;
Expand All @@ -34,16 +35,17 @@ class BinaryDataPacket extends Row {
}
}

values = new List(fields.length);
for (var i = 0; i < fields.length; i++) {
log.fine("$i: ${fields[i].name}");
values = new List<dynamic>(fieldPackets.length);
for (var i = 0; i < fieldPackets.length; i++) {
log.fine("$i: ${fieldPackets[i].name}");
if (nullMap[i]) {
log.fine("Value: null");
values[i] = null;
continue;
}
var field = fields[i];
var field = fieldPackets[i];
values[i] = readField(field, buffer);
fields[field.name] = values[i];
}
}

Expand Down Expand Up @@ -218,18 +220,4 @@ class BinaryDataPacket extends Row {
}
return null;
}

int get length => values.length;

dynamic operator [](int index) => values[index];

void operator []=(int index, dynamic value) {
throw new UnsupportedError("Cannot modify row");
}

set length(int newLength) {
throw new UnsupportedError("Cannot set length of results");
}

String toString() => "Value: $values";
}
155 changes: 76 additions & 79 deletions lib/src/query/standard_data_packet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
library mysql1.standard_data_packet;

import 'dart:convert';
import 'package:logging/logging.dart';

import '../constants.dart';
import '../blob.dart';
Expand All @@ -12,93 +13,89 @@ import '../results/row.dart';
import '../results/field.dart';

class StandardDataPacket extends Row {
/// Values as List
final List<dynamic> values;
final Logger log = new Logger("StandardDataPacket");

/// Values as Map
final Map<String, dynamic> fields = <String, dynamic>{};

StandardDataPacket(Buffer buffer, List<Field> fieldPackets)
: values = new List<dynamic>(fieldPackets.length) {
StandardDataPacket(Buffer buffer, List<Field> fieldPackets) {
values = new List<dynamic>(fieldPackets.length);
for (var i = 0; i < fieldPackets.length; i++) {
var list;
int length = buffer.readLengthCodedBinary();
if (length != null) {
list = buffer.readList(length);
} else {
values[i] = null;
continue;
}
switch (fieldPackets[i].type) {
case FIELD_TYPE_TINY: // tinyint/bool
case FIELD_TYPE_SHORT: // smallint
case FIELD_TYPE_INT24: // mediumint
case FIELD_TYPE_LONGLONG: // bigint/serial
case FIELD_TYPE_LONG: // int
var s = utf8.decode(list);
values[i] = int.parse(s);
break;
case FIELD_TYPE_NEWDECIMAL: // decimal
case FIELD_TYPE_FLOAT: // float
case FIELD_TYPE_DOUBLE: // double
var s = utf8.decode(list);
values[i] = double.parse(s);
break;
case FIELD_TYPE_BIT: // bit
var value = 0;
for (var num in list) {
value = (value << 8) + num;
}
values[i] = value;
break;
case FIELD_TYPE_DATE: // date
case FIELD_TYPE_DATETIME: // datetime
case FIELD_TYPE_TIMESTAMP: // timestamp
var s = utf8.decode(list);
values[i] = DateTime.parse(s).toUtc();
break;
case FIELD_TYPE_TIME: // time
var s = utf8.decode(list);
var parts = s.split(":");
values[i] = new Duration(
days: 0,
hours: int.parse(parts[0]),
minutes: int.parse(parts[1]),
seconds: int.parse(parts[2]),
milliseconds: 0);
break;
case FIELD_TYPE_YEAR: // year
var s = utf8.decode(list);
values[i] = int.parse(s);
break;
case FIELD_TYPE_STRING: // char/binary/enum/set
case FIELD_TYPE_VAR_STRING: // varchar/varbinary
var s = utf8.decode(list);
values[i] = s;
break;
case FIELD_TYPE_BLOB: // tinytext/text/mediumtext/longtext/tinyblob/mediumblob/blob/longblob
values[i] = new Blob.fromBytes(list);
break;
case FIELD_TYPE_GEOMETRY: // geometry
var s = utf8.decode(list);
values[i] = s;
break;
}
fields[fieldPackets[i].name] = values[i];
}
}

StandardDataPacket.forTests(this.values);

int get length => values.length;
var field = fieldPackets[i];

dynamic operator [](int index) => values[index];
log.fine("$i: ${field.name}");

void operator []=(int index, dynamic value) {
throw new UnsupportedError("Cannot modify row");
values[i] = readField(field, buffer);
fields[field.name] = values[i];
}
}

set length(int newLength) {
throw new UnsupportedError("Cannot set length of results");
Object readField(Field field, Buffer buffer) {
var list;
int length = buffer.readLengthCodedBinary();
if (length != null) {
list = buffer.readList(length);
} else {
return null;
}

switch (field.type) {
case FIELD_TYPE_TINY: // tinyint/bool
case FIELD_TYPE_SHORT: // smallint
case FIELD_TYPE_INT24: // mediumint
case FIELD_TYPE_LONGLONG: // bigint/serial
case FIELD_TYPE_LONG: // int
var s = utf8.decode(list);
return int.parse(s);
break;
case FIELD_TYPE_NEWDECIMAL: // decimal
case FIELD_TYPE_FLOAT: // float
case FIELD_TYPE_DOUBLE: // double
var s = utf8.decode(list);
return double.parse(s);
break;
case FIELD_TYPE_BIT: // bit
var value = 0;
for (var num in list) {
value = (value << 8) + num;
}
return value;
break;
case FIELD_TYPE_DATE: // date
case FIELD_TYPE_DATETIME: // datetime
case FIELD_TYPE_TIMESTAMP: // timestamp
var s = utf8.decode(list);
return DateTime.parse(s).toUtc();
break;
case FIELD_TYPE_TIME: // time
var s = utf8.decode(list);
var parts = s.split(":");
return new Duration(
days: 0,
hours: int.parse(parts[0]),
minutes: int.parse(parts[1]),
seconds: int.parse(parts[2]),
milliseconds: 0);
break;
case FIELD_TYPE_YEAR: // year
var s = utf8.decode(list);
return int.parse(s);
break;
case FIELD_TYPE_STRING: // char/binary/enum/set
case FIELD_TYPE_VAR_STRING: // varchar/varbinary
var s = utf8.decode(list);
return s;
break;
case FIELD_TYPE_BLOB: // tinytext/text/mediumtext/longtext/tinyblob/mediumblob/blob/longblob
return new Blob.fromBytes(list);
break;
case FIELD_TYPE_GEOMETRY: // geometry
var s = utf8.decode(list);
return s;
break;
default:
return null;
}
}

String toString() => "Fields: $fields";
Expand Down
33 changes: 32 additions & 1 deletion lib/src/results/row.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,41 @@ library mysql1.row;

import 'dart:collection';

import 'field.dart';
import '../buffer.dart';

/**
* A row of data. Fields can be retrieved by index, or by name.
*
* When retrieving a field by name, only fields which are valid Dart
* identifiers, and which aren't part of the List object, can be used.
*/
abstract class Row extends ListBase<dynamic> {}
abstract class Row extends ListBase<dynamic> {
/// Values as List
List<dynamic> values;

/// Values as Map
final Map<String, dynamic> fields = <String, dynamic>{};

int get length => values.length;

set length(int newLength) {
throw new UnsupportedError("Cannot set length of results");
}

dynamic operator [](dynamic index) {
if (index is int) {
return values[index];
} else {
return fields[index.toString()];
}
}

void operator []=(int index, dynamic value) {
throw new UnsupportedError("Cannot modify row");
}

String toString() => "Fields: $fields";

Object readField(Field field, Buffer buffer);
}
36 changes: 36 additions & 0 deletions test/integration/one_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,42 @@ void main() {
expect(dt, equals(dt2));
});

test('result fields are accessible by name', () async {
var results = await conn.query(
"insert into test1 (atinyint, asmallint, amediumint, abigint, aint, "
"adecimal, afloat, adouble, areal, "
"aboolean, abit, aserial, "
"adate, adatetime, atimestamp, atime, ayear, "
"achar, avarchar, atinytext, atext, amediumtext, alongtext, "
"abinary, avarbinary, atinyblob, amediumblob, ablob, alongblob, "
"aenum, aset) values"
"(?, ?, ?, ?, ?, "
"?, ?, ?, ?, "
"?, ?, ?, "
"?, ?, ?, ?, ?, "
"?, ?, ?, ?, ?, ?, "
"?, ?, ?, ?, ?, ?, "
"?, ?)",
insertValues);

// Normal
results = await conn.query('select atinyint from test1');
int v1 = results.first.fields['atinyint'];
int v2 = results.first['atinyint'];
expect(v1, isNotNull);
expect(v2, equals(v1));

// Binary packet
results =
await conn.query('select atinyint from test1 WHERE ? = ?', [1, 1]);
int v3 = results.first.fields['atinyint'];
int v4 = results.first['atinyint'];
expect(v3, isNotNull);
expect(v4, equals(v3));

expect(v1, equals(v3));
});

test('disallow non-utc datetime serialization', () async {
expect(() async {
var results = await conn.query(
Expand Down