Skip to content

Commit

Permalink
feat(postgres): integrate keys with collections
Browse files Browse the repository at this point in the history
  • Loading branch information
calebmer committed Oct 9, 2016
1 parent 950737a commit 0e50110
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 11 deletions.
8 changes: 8 additions & 0 deletions src/graphql/utils/__tests__/formatName-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ test('type will format in pascal case', () => {
expect(formatName.type('_helloWorld')).toBe('_HelloWorld')
expect(formatName.type('__hello_world__')).toBe('__HelloWorld__')
expect(formatName.type('HELLO_WORLD_')).toBe('HelloWorld_')
expect(formatName.type('person_id_1')).toBe('PersonId1')
expect(formatName.type('person_id_2')).toBe('PersonId2')
})

test('field will format in camel case', () => {
Expand All @@ -20,6 +22,8 @@ test('field will format in camel case', () => {
expect(formatName.field('_HelloWorld')).toBe('_helloWorld')
expect(formatName.field('__hello_world__')).toBe('__helloWorld__')
expect(formatName.field('HELLO_WORLD_')).toBe('helloWorld_')
expect(formatName.field('person_id_1')).toBe('personId1')
expect(formatName.field('person_id_2')).toBe('personId2')
})

test('arg will format in camel case', () => {
Expand All @@ -31,6 +35,8 @@ test('arg will format in camel case', () => {
expect(formatName.arg('_HelloWorld')).toBe('_helloWorld')
expect(formatName.arg('__hello_world__')).toBe('__helloWorld__')
expect(formatName.arg('HELLO_WORLD_')).toBe('helloWorld_')
expect(formatName.arg('person_id_1')).toBe('personId1')
expect(formatName.arg('person_id_2')).toBe('personId2')
})

test('enumValue will format in constant case', () => {
Expand All @@ -42,4 +48,6 @@ test('enumValue will format in constant case', () => {
expect(formatName.enumValue('_HelloWorld')).toBe('_HELLO_WORLD')
expect(formatName.enumValue('__hello_world__')).toBe('__HELLO_WORLD__')
expect(formatName.enumValue('HELLO_WORLD_')).toBe('HELLO_WORLD_')
expect(formatName.enumValue('person_id_1')).toBe('PERSON_ID_1')
expect(formatName.enumValue('person_id_2')).toBe('PERSON_ID_2')
})
4 changes: 2 additions & 2 deletions src/graphql/utils/formatName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ const formatInsideUnderscores = (formatter: (string: string) => string) => (stri
return `${start}${formatter(name)}${finish}`
}

const camelCaseInsideUnderscores = formatInsideUnderscores(camelCase)
const pascalCaseInsideUnderscores = formatInsideUnderscores(pascalCase)
const camelCaseInsideUnderscores = formatInsideUnderscores(name => camelCase(name, undefined, true))
const pascalCaseInsideUnderscores = formatInsideUnderscores(name => pascalCase(name, undefined, true))
const constantCaseInsideUnderscores = formatInsideUnderscores(constantCase)

namespace formatName {
Expand Down
2 changes: 1 addition & 1 deletion src/interface/collection/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ interface Collection {
* by.
*/
// TODO: Test that we don’t have any keys with the same name.
readonly keys: Set<CollectionKey<mixed>>
readonly keys: Array<CollectionKey<mixed>>

/**
* Gets the primary unique identifier for this collection. While a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ exports[`test forum example 1`] = `
query: Query
}
type CompoundKey {
personId_2: Int!
personId_1: Int!
type CompoundKey implements Node {
__id: ID!
personId2: Int!
personId1: Int!
}
scalar Email
Expand All @@ -18,15 +19,17 @@ type NoUpdate {
column: Int
}
type Person {
type Person implements Node {
__id: ID!
id: Int!
name: String!
about: String
email: Email
createdAt: String
}
type Post {
type Post implements Node {
__id: ID!
id: Int!
headline: String!
body: String
Expand All @@ -35,6 +38,13 @@ type Post {
type Query {
node(__id: ID!): Node
post(__id: ID!): Post
postById(id: Int!): Post
person(__id: ID!): Person
personById(id: Int!): Person
personByEmail(email: Email): Person
compoundKey(__id: ID!): CompoundKey
compoundKeyByPersonId1AndPersonId2(personId1: Int!, personId2: Int!): CompoundKey
}
type UpdatableView {
Expand Down
32 changes: 30 additions & 2 deletions src/postgres/inventory/collection/PGCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { memoize1, sql, memoizeMethod, objectToMap } from '../../utils'
import { PGCatalog, PGCatalogClass, PGCatalogNamespace, PGCatalogAttribute } from '../../introspection'
import PGObjectType from '../type/PGObjectType'
import isPGContext from '../isPGContext'
import PGCollectionKey from './PGCollectionKey'

/**
* Creates a collection object for Postgres that can be used to access the
Expand Down Expand Up @@ -49,8 +50,35 @@ class PGCollection implements Collection {
pgAttributes: this._pgAttributes,
})

public keys = new Set()
public primaryKey = null
/**
* An array of all the keys which can be used to uniquely identify a value
* in our collection.
*
* The keys are a representation of the primary key constraints and unique
* constraints in Postgres on the table.
*/
public keys = (
this._pgCatalog.getConstraints()
.filter(pgConstraint =>
// We only want the constraints that apply to this Postgres class.
pgConstraint.classId === this._pgClass.id &&
// …and the constraints that are either a primary key constraint or a
// unique constraint.
(pgConstraint.type === 'p' || pgConstraint.type === 'u')
)
// Tell TypeScript our constraint is ok (verified in the filter above)
// with `as any`.
.map(pgConstraint => new PGCollectionKey(this, pgConstraint as any))
)

/**
* The primary key for our collection is just an instance of `CollectionKey`
* representing the single primary key constraint in Postgres. We choose one
* key to be our primary key so that consumers have a clear choice in what id
* should be used.
*/
public primaryKey = this.keys.find(key => key._pgConstraint.type === 'p')

public paginator = null

// If we can’t insert into this class, there should be no `create`
Expand Down
2 changes: 1 addition & 1 deletion src/postgres/inventory/collection/PGCollectionKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import PGCollection from './PGCollection'
class PGCollectionKey implements CollectionKey<PGObjectType.Value> {
constructor (
private _collection: PGCollection,
private _pgConstraint: PGCatalogPrimaryKeyConstraint | PGCatalogUniqueConstraint,
public _pgConstraint: PGCatalogPrimaryKeyConstraint | PGCatalogUniqueConstraint,
) {}

// Steal the catalog reference from our collection ;)
Expand Down

0 comments on commit 0e50110

Please sign in to comment.