Passing postgres test with user

This commit is contained in:
Drew Gross
2016-06-10 14:09:48 -07:00
parent f75c8b3a4d
commit 2cafd6919f
4 changed files with 47 additions and 13 deletions

View File

@@ -9,6 +9,13 @@ const parseTypeToPostgresType = type => {
case 'Date': return 'timestamp'; case 'Date': return 'timestamp';
case 'Object': return 'jsonb'; case 'Object': return 'jsonb';
case 'Boolean': return 'boolean'; case 'Boolean': return 'boolean';
case 'Pointer': return 'char(10)';
case 'Array':
if (type.contents && type.contents.type === 'String') {
return 'text[]';
} else {
throw `no type for ${JSON.stringify(type)} yet`;
}
default: throw `no type for ${JSON.stringify(type)} yet`; default: throw `no type for ${JSON.stringify(type)} yet`;
} }
}; };
@@ -50,7 +57,11 @@ export class PostgresStorageAdapter {
let patternsArray = []; let patternsArray = [];
Object.keys(schema.fields).forEach((fieldName, index) => { Object.keys(schema.fields).forEach((fieldName, index) => {
valuesArray.push(fieldName); valuesArray.push(fieldName);
valuesArray.push(parseTypeToPostgresType(schema.fields[fieldName])); let parseType = schema.fields[fieldName];
if (['_rperm', '_wperm'].includes(fieldName)) {
parseType.contents = { type: 'String' };
}
valuesArray.push(parseTypeToPostgresType(parseType));
patternsArray.push(`$${index * 2 + 2}:name $${index * 2 + 3}:raw`); patternsArray.push(`$${index * 2 + 2}:name $${index * 2 + 3}:raw`);
}); });
return this._client.query(`CREATE TABLE $1:name (${patternsArray.join(',')})`, [className, ...valuesArray]) return this._client.query(`CREATE TABLE $1:name (${patternsArray.join(',')})`, [className, ...valuesArray])
@@ -128,7 +139,7 @@ export class PostgresStorageAdapter {
} }
// Return a promise for all schemas known to this adapter, in Parse format. In case the // Return a promise for all schemas known to this adapter, in Parse format. In case the
// schemas cannot be retrieved, returns a promise that rejects. Requirements for the // schemas cannot be retrieved, returns a promise that rejects. Rquirements for the
// rejection reason are TBD. // rejection reason are TBD.
getAllClasses() { getAllClasses() {
return this._ensureSchemaCollectionExists() return this._ensureSchemaCollectionExists()
@@ -143,7 +154,7 @@ export class PostgresStorageAdapter {
return this._client.query('SELECT * FROM "_SCHEMA" WHERE "className"=$<className>', { className }) return this._client.query('SELECT * FROM "_SCHEMA" WHERE "className"=$<className>', { className })
.then(result => { .then(result => {
if (result.length === 1) { if (result.length === 1) {
return result; return result[0];
} else { } else {
throw undefined; throw undefined;
} }
@@ -152,24 +163,40 @@ export class PostgresStorageAdapter {
// TODO: remove the mongo format dependency // TODO: remove the mongo format dependency
createObject(className, schema, object) { createObject(className, schema, object) {
console.log(object);
let columnsArray = []; let columnsArray = [];
let valuesArray = []; let valuesArray = [];
Object.keys(object).forEach(fieldName => { Object.keys(object).forEach(fieldName => {
columnsArray.push(fieldName); columnsArray.push(fieldName);
valuesArray.push(object[fieldName]); switch (schema.fields[fieldName].type) {
case 'Date':
valuesArray.push(object[fieldName].iso);
break;
case 'Pointer':
valuesArray.push(object[fieldName].objectId);
break;
default:
valuesArray.push(object[fieldName]);
break;
}
}); });
let columnsPattern = columnsArray.map((col, index) => `$${index + 2}~`).join(','); let columnsPattern = columnsArray.map((col, index) => `$${index + 2}:name`).join(',');
let valuesPattern = valuesArray.map((val, index) => `$${index + 2 + columnsArray.length}`).join(','); let valuesPattern = valuesArray.map((val, index) => `$${index + 2 + columnsArray.length}`).join(',');
return this._client.query(`INSERT INTO $1~ (${columnsPattern}) VALUES (${valuesPattern})`, [className, ...columnsArray, ...valuesArray]) return this._client.query(`INSERT INTO $1~ (${columnsPattern}) VALUES (${valuesPattern})`, [className, ...columnsArray, ...valuesArray])
.then(() => ({ ops: [object] })); .then(() => ({ ops: [object] }))
} }
// Remove all objects that match the given Parse Query. // Remove all objects that match the given Parse Query.
// If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined. // If no objects match, reject with OBJECT_NOT_FOUND. If objects are found and deleted, resolve with undefined.
// If there is some other error, reject with INTERNAL_SERVER_ERROR. // If there is some other error, reject with INTERNAL_SERVER_ERROR.
deleteObjectsByQuery(className, schema, query) { deleteObjectsByQuery(className, schema, query) {
return Promise.reject('Not implented yet.') return this._client.query(`WITH deleted AS (DELETE FROM $<className:name> RETURNING *) SELECT count(*) FROM deleted`, { className })
.then(result => {
if (result[0].count === 0) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
} else {
return result[0].count;
}
});
} }
// Apply the update to all objects that match the given Parse Query. // Apply the update to all objects that match the given Parse Query.
@@ -190,6 +217,12 @@ export class PostgresStorageAdapter {
// Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }. // Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }.
find(className, schema, query, { skip, limit, sort }) { find(className, schema, query, { skip, limit, sort }) {
return this._client.query("SELECT * FROM $<className:name>", { className }) return this._client.query("SELECT * FROM $<className:name>", { className })
.then(results => results.map(object => {
Object.keys(schema.fields).filter(field => schema.fields[field].type === 'Pointer').forEach(fieldName => {
object[fieldName] = { objectId: object[fieldName], __type: 'Pointer', className: schema.fields[fieldName].targetClass };
});
return object;
}))
} }
// Create a unique index. Unique indexes on nullable fields are not allowed. Since we don't // Create a unique index. Unique indexes on nullable fields are not allowed. Since we don't

View File

@@ -410,7 +410,7 @@ DatabaseController.prototype.create = function(className, object, { acl } = {})
.then(() => this.handleRelationUpdates(className, null, object)) .then(() => this.handleRelationUpdates(className, null, object))
.then(() => schemaController.enforceClassExists(className)) .then(() => schemaController.enforceClassExists(className))
.then(() => schemaController.getOneSchema(className, true)) .then(() => schemaController.getOneSchema(className, true))
.then(schema => this.adapter.createObject(className, schema, object)) .then(schema => this.adapter.createObject(className, SchemaController.convertSchemaToAdapterSchema(schema), object))
.then(result => sanitizeDatabaseResult(originalObject, result.ops[0])); .then(result => sanitizeDatabaseResult(originalObject, result.ops[0]));
}) })
}; };

View File

@@ -223,6 +223,8 @@ const fieldTypeIsInvalid = ({ type, targetClass }) => {
const convertSchemaToAdapterSchema = schema => { const convertSchemaToAdapterSchema = schema => {
schema = injectDefaultSchema(schema); schema = injectDefaultSchema(schema);
delete schema.fields.ACL; delete schema.fields.ACL;
schema.fields._rperm = { type: 'Array' };
schema.fields._wperm = { type: 'Array' };
if (schema.className === '_User') { if (schema.className === '_User') {
delete schema.fields.password; delete schema.fields.password;
@@ -837,4 +839,5 @@ export {
buildMergedSchemaObject, buildMergedSchemaObject,
systemClasses, systemClasses,
defaultColumns, defaultColumns,
convertSchemaToAdapterSchema,
}; };

View File

@@ -526,16 +526,14 @@ function findPointers(object, path) {
} }
if (typeof object !== 'object') { if (typeof object !== 'object') {
throw new Parse.Error(Parse.Error.INVALID_QUERY, throw new Parse.Error(Parse.Error.INVALID_QUERY, 'can only include pointer fields');
'can only include pointer fields');
} }
if (path.length == 0) { if (path.length == 0) {
if (object.__type == 'Pointer') { if (object.__type == 'Pointer') {
return [object]; return [object];
} }
throw new Parse.Error(Parse.Error.INVALID_QUERY, throw new Parse.Error(Parse.Error.INVALID_QUERY, 'can only include pointer fields');
'can only include pointer fields');
} }
var subobject = object[path[0]]; var subobject = object[path[0]];