Yang Xia 2016-04-29 10:45:32 +08:00
Родитель 4b8e2b933d
Коммит d70a574f9d
6 изменённых файлов: 2785 добавлений и 1473 удалений

Просмотреть файл

@ -1,6 +1,12 @@
Note: This is an Azure Storage only package. The all up Azure node sdk still has the old storage bits in there. In a future release, those storage bits will be removed and an npm dependency to this storage node sdk will
be taken. This is a GA preview release and the changes described below indicate the changes from the Azure node SDK 0.9.8 available here - https://github.com/Azure/azure-sdk-for-node.
2016.05 Version 1.0.0
TABLE
* Fixed the issue that loses the data type for Edm.Double value like: 1.0.
* Fixed the issue that loses the data precision for Edm.Int64 value when it is outisde of the range (2^53 - 1) to -(2^53 - 1).
2016.03 Version 0.10.0
ALL

Просмотреть файл

@ -25,6 +25,7 @@ var guid = require('node-uuid');
var os = require('os');
var crypto = require('crypto');
var extend = require('extend');
var Parser = require('json-edm-parser');
var azureutil = require('../util/util');
var validate = require('../util/validate');
@ -36,6 +37,7 @@ var StorageServiceSettings = require('./storageservicesettings');
var Constants = require('../util/constants');
var StorageUtilities = require('../util/storageutilities');
var ServicePropertiesResult = require('../models/servicepropertiesresult');
var TableUtilities = require('../../services/table/tableutilities');
var SharedKey = require('../signing/sharedkey');
var SharedAccessSignature = require('../signing/sharedaccesssignature');
@ -289,7 +291,7 @@ StorageServiceClient.prototype._performRequest = function (webResource, body, op
if (error) {
responseObject = { error: error, response: null };
} else {
responseObject = self._processResponse(webResource, response);
responseObject = self._processResponse(webResource, response, options);
responseObject.contentMD5 = response.contentMD5;
responseObject.length = response.length;
}
@ -576,11 +578,13 @@ StorageServiceClient.prototype._buildRequestOptions = function (webResource, bod
* Process the response.
* @ignore
*
* @param {WebResource} webResource The web resource that made the request.
* @param {Response} response The response object.
* @param {WebResource} webResource The web resource that made the request.
* @param {Response} response The response object.
* @param {Options} options The response parsing options.
* @param {String} options.payloadFormat The payload format.
* @return The normalized responseObject.
*/
StorageServiceClient.prototype._processResponse = function (webResource, response) {
StorageServiceClient.prototype._processResponse = function (webResource, response, options) {
var self = this;
var validResponse = WebResource.validResponse(response.statusCode);
@ -591,7 +595,7 @@ StorageServiceClient.prototype._processResponse = function (webResource, respons
responseObject = { error: null, response: rsp };
} else {
// attempt to parse the response body, errors will be returned in rsp.error without modifying the body
rsp = StorageServiceClient._parseResponse(rsp, self.xml2jsSettings);
rsp = StorageServiceClient._parseResponse(rsp, self.xml2jsSettings, options);
if (validResponse && !rsp.error) {
responseObject = { error: null, response: rsp };
@ -712,10 +716,13 @@ StorageServiceClient._buildResponse = function (isSuccessful, body, headers, sta
* This is done using the xml2js library.
* @ignore
*
* @param {object} response The response object with a property "body" with a XML or JSON string content.
* @param {object} response The response object with a property "body" with a XML or JSON string content.
* @param {object} xml2jsSettings The XML to json settings.
* @param {Options} options The response parsing options.
* @param {String} options.payloadFormat The payload format.
* @return {object} The same response object with the body part as a JS object instead of a XML or JSON string.
*/
StorageServiceClient._parseResponse = function (response, xml2jsSettings) {
StorageServiceClient._parseResponse = function (response, xml2jsSettings, options) {
function parseXml(body) {
var parsed;
var parser = new xml2js.Parser(xml2jsSettings);
@ -738,7 +745,15 @@ StorageServiceClient._parseResponse = function (response, xml2jsSettings) {
try {
if (contentType.indexOf('application/json') !== -1) {
response.body = JSON.parse(response.body);
if (options && options.payloadFormat && options.payloadFormat !== TableUtilities.PayloadFormat.NO_METADATA) {
var parser = new Parser();
parser.onValue = function (value) {
response.body = value;
};
parser.write(response.body);
} else {
response.body = JSON.parse(response.body);
}
} else if (contentType.indexOf('application/xml') !== -1 || contentType.indexOf('application/atom+xml') !== -1) {
response.body = parseXml(response.body);
} else {

Просмотреть файл

@ -119,12 +119,8 @@ exports.serializeValue = function (type, value) {
}
return value;
case EdmType.INT64:
return value.toString();
case EdmType.DOUBLE:
if(azureutil.objectIsInt(value)) {
return value + '.0';
}
return value;
return value.toString();
case EdmType.INT32:
if (value === Number.POSITIVE_INFINITY) {
return 'Infinity';
@ -153,9 +149,9 @@ exports.isTypeRequired = function(type, value) {
case EdmType.INT64:
case EdmType.DATETIME:
case EdmType.GUID:
case EdmType.DOUBLE:
return true;
case EdmType.INT32:
case EdmType.DOUBLE:
if (value === Number.POSITIVE_INFINITY || value === Number.NEGATIVE_INFINITY || (Number.isNaN(value))) {
return true;
}
@ -182,7 +178,7 @@ exports.serializeQueryValue = function (value, type) {
case EdmType.BOOLEAN:
return value ? 'true' : 'false';
case EdmType.DOUBLE:
return azureutil.objectIsInt(value) ? '\'' + value + '.0' + '\'': value.toString();
return value.toString();
case EdmType.INT64:
return value.toString() + 'L';
case EdmType.DATETIME:

Просмотреть файл

@ -21,6 +21,7 @@
"dependencies": {
"extend": "~1.2.1",
"browserify-mime": "~1.2.9",
"json-edm-parser": "0.1.1",
"node-uuid": "~1.4.0",
"readable-stream": "~2.0.0",
"request": "~2.69.0",

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -199,6 +199,20 @@ describe('tableservice-payload-tests', function () {
});
});
describe('Data/Type Integrity', function () {
it('FullMetadata', function (done) {
var options = {};
options.payloadFormat = TableUtilities.PayloadFormat.FULL_METADATA;
fnHelper(dataTypeIntegrityTest, options, done);
});
it('MinimalMetadata', function (done) {
var options = {};
options.payloadFormat = TableUtilities.PayloadFormat.MINIMAL_METADATA;
fnHelper(dataTypeIntegrityTest, options, done);
});
});
describe('EntityResolver', function () {
it('FullMetadata', function (done) {
var options = {};
@ -276,7 +290,11 @@ function compareProperties (propFromService, prop, expectTypeOnService) {
// check type
if (expectTypeOnService.val) {
if (expectTypeOnService.stringOverride) {
assert.strictEqual(propFromService['$'], 'Edm.String');
if (prop['$'] === 'Edm.Double' && azureutil.objectIsInt(parseFloat(prop['_'])) ) {
assert.strictEqual(propFromService['$'], prop['$']);
} else {
assert.strictEqual(propFromService['$'], 'Edm.String');
}
} else {
assert.strictEqual(propFromService['$'], prop['$']);
}
@ -286,12 +304,18 @@ function compareProperties (propFromService, prop, expectTypeOnService) {
// check value, make sure typeof is equal as Number.NaN should not equal 'Nan'
if (propFromService.hasOwnProperty('$') && !expectTypeOnService.stringOverride) {
assert.strictEqual(typeof propFromService['_'], typeof prop['_']);
if (prop['$'] === 'Edm.Double' && azureutil.objectIsInt(parseFloat(prop['_'])) ) {
assert.strictEqual(typeof propFromService['_'], "number");
} else {
assert.strictEqual(typeof propFromService['_'], typeof prop['_']);
}
}
if (prop['$'] === 'Edm.Binary' && (!propFromService.hasOwnProperty('$') || propFromService['$'] === 'Edm.String')) {
assert.strictEqual(new Buffer(propFromService['_'], 'base64').toString(), prop['_'].toString());
} else if (prop['$'] === 'Edm.DateTime' && (!propFromService.hasOwnProperty('$') || propFromService['$'] === 'Edm.String')){
assert.strictEqual((new Date(propFromService['_'])).toString(), prop['_'].toString());
} else if (prop['$'] === 'Edm.Double') {
assert.strictEqual(propFromService['_'].toString(), parseFloat(prop['_']).toString());
} else {
assert.strictEqual(propFromService['_'].toString(), prop['_'].toString());
}
@ -310,8 +334,13 @@ var expectPropType = function (options, property) {
}
if (property['$'] === 'Edm.Int32' || property['$'] === 'Edm.Double') {
if ((Number.isNaN(property['_']) || property['_'] === Number.POSITIVE_INFINITY || property['_'] === Number.NEGATIVE_INFINITY) && (options.payloadFormat !== TableUtilities.PayloadFormat.NO_METADATA || options.autoResolveProperties)) {
return {val: true, stringOverride: (options.autoResolveProperties && options.payloadFormat === TableUtilities.PayloadFormat.NO_METADATA)};
if ((Number.isNaN(property['_'])
|| property['_'] === Number.POSITIVE_INFINITY
|| property['_'] === Number.NEGATIVE_INFINITY
|| (property['$'] === 'Edm.Double' && azureutil.objectIsInt(parseFloat(property['_'])) ) )
&& (options.payloadFormat !== TableUtilities.PayloadFormat.NO_METADATA || options.autoResolveProperties)) {
var overrideDouble = (property['$'] === 'Edm.Double') && (parseFloat(property['_']).toString() !== property['_'].toString());
return {val: true, stringOverride: overrideDouble || (options.autoResolveProperties && options.payloadFormat === TableUtilities.PayloadFormat.NO_METADATA)};
} else {
return {val: false};
}
@ -448,6 +477,39 @@ function specialNumbersTest (options, done) {
});
}
function dataTypeIntegrityTest (options, done) {
tableService.createTable(tableName, function (error1) {
assert.equal(error1, null);
var entityToTest = {
PartitionKey: eg.String('partition1'),
RowKey: eg.String('row1'),
RegularDouble: eg.Double(4.81516423423),
NanDouble: eg.Double(Number.NaN),
DoubleInInt: eg.Double(10.0),
DoubleInIntString: eg.Double('10.0'),
PositiveInfinityDouble: eg.Double(Number.POSITIVE_INFINITY),
NegativeInfinityDouble: eg.Double(Number.NEGATIVE_INFINITY),
MinDouble: eg.Double(Number.MIN_VALUE),
MaxDouble: eg.Double(Number.MAX_VALUE),
MaxInt64: eg.Int64('9223372036854775807')
};
tableService.insertEntity(tableName, entityToTest, function (error2) {
assert.equal(error2, null);
tableService.retrieveEntity(tableName, entityToTest.PartitionKey['_'], entityToTest.RowKey['_'], options, function (error3, entity) {
assert.equal(error3, null);
assert.notEqual(entity, null);
compareEntities(entity, entityToTest, options);
done();
});
});
});
}
function entityResolverTest (options, done) {
tableService.createTable(tableName, function (error1) {
assert.equal(error1, null);