https://github.com/google/cayley
Raw File
Tip revision: 6033bc1d4d75d8d6e7dffc791853087c7948303f authored by Derek Liang on 31 October 2017, 05:50:19 UTC
remove console log
Tip revision: 6033bc1
database.go
package sql

import (
	"database/sql"
	"github.com/cayleygraph/cayley/graph"
	"fmt"
)

var types = make(map[string]Registration)

func Register(name string, f Registration) {
	if f.Driver == "" {
		panic("no sql driver in type definition")
	}
	types[name] = f

	registerQuadStore(name, name)
}

type Registration struct {
	Driver             string // sql driver to use on dial
	HashType           string // type for hash fields
	BytesType          string // type for binary fields
	TimeType           string // type for datetime fields
	HorizonType        string // type for horizon counter
	NodesTableExtra    string // extra SQL to append to nodes table definition
	ConditionalIndexes bool   // database supports conditional indexes
	FillFactor         bool   // database supports fill percent on indexes
	NoForeignKeys      bool   // database has no support for FKs

	FieldQuote          func(name string) string     // function to escape field names
	Placeholder         func(n int) string           // function to generate n-th query placeholder
	Error               func(error) error            // error conversion function
	Estimated           func(table string) string    // query that string that returns an estimated number of rows in table
	RunTx               func(tx *sql.Tx, in []graph.Delta, opts graph.IgnoreOpts) error
	NoSchemaChangesInTx bool
}

func (r Registration) nodesTable() string {
	htyp := r.HashType
	if htyp == "" {
		htyp = "BYTEA"
	}
	btyp := r.BytesType
	if btyp == "" {
		btyp = "BYTEA"
	}
	ttyp := r.TimeType
	if ttyp == "" {
		ttyp = "timestamp with time zone"
	}
	end := "\n);"
	if r.NodesTableExtra != "" {
		end = ",\n" + r.NodesTableExtra + end
	}
	return `CREATE TABLE nodes (
	hash ` + htyp + ` PRIMARY KEY,
	value ` + btyp + `,
	value_string TEXT,
	datatype TEXT,
	language TEXT,
	iri BOOLEAN,
	bnode BOOLEAN,
	value_int BIGINT,
	value_bool BOOLEAN,
	value_float double precision,
	value_time ` + ttyp +
		end
}

func (r Registration) quadsTable() string {
	htyp := r.HashType
	if htyp == "" {
		htyp = "BYTEA"
	}
	hztyp := r.HorizonType
	if hztyp == "" {
		hztyp = "SERIAL"
	}
	return `CREATE TABLE quads (
	horizon ` + hztyp + ` PRIMARY KEY,
	subject_hash ` + htyp + ` NOT NULL,
	predicate_hash ` + htyp + ` NOT NULL,
	object_hash ` + htyp + ` NOT NULL,
	label_hash ` + htyp + `,
	id BIGINT,
	ts timestamp
);`
}

func (r Registration) quadIndexes(options graph.Options) []string {
	indexes := make([]string, 0, 10)
	if r.ConditionalIndexes {
		indexes = append(indexes,
			`CREATE UNIQUE INDEX spo_unique ON quads (subject_hash, predicate_hash, object_hash) WHERE label_hash IS NULL;`,
			`CREATE UNIQUE INDEX spol_unique ON quads (subject_hash, predicate_hash, object_hash, label_hash) WHERE label_hash IS NOT NULL;`,
		)
	} else {
		indexes = append(indexes,
			`CREATE UNIQUE INDEX spo_unique ON quads (subject_hash, predicate_hash, object_hash);`,
			`CREATE UNIQUE INDEX spol_unique ON quads (subject_hash, predicate_hash, object_hash, label_hash);`,
		)
	}
	if !r.NoForeignKeys {
		indexes = append(indexes,
			`ALTER TABLE quads ADD CONSTRAINT subject_hash_fk FOREIGN KEY (subject_hash) REFERENCES nodes (hash);`,
			`ALTER TABLE quads ADD CONSTRAINT predicate_hash_fk FOREIGN KEY (predicate_hash) REFERENCES nodes (hash);`,
			`ALTER TABLE quads ADD CONSTRAINT object_hash_fk FOREIGN KEY (object_hash) REFERENCES nodes (hash);`,
			`ALTER TABLE quads ADD CONSTRAINT label_hash_fk FOREIGN KEY (label_hash) REFERENCES nodes (hash);`,
		)
	}
	if r.FillFactor {
		const defaultFillFactor = 50
		factor, ok, _ := options.IntKey("db_fill_factor")
		if !ok {
			factor = defaultFillFactor
		}
		indexes = append(indexes,
			fmt.Sprintf(`CREATE INDEX spo_index ON quads (subject_hash) WITH (FILLFACTOR = %d);`, factor),
			fmt.Sprintf(`CREATE INDEX pos_index ON quads (predicate_hash) WITH (FILLFACTOR = %d);`, factor),
			fmt.Sprintf(`CREATE INDEX osp_index ON quads (object_hash) WITH (FILLFACTOR = %d);`, factor),
		)
	} else {
		indexes = append(indexes,
			`CREATE INDEX spo_index ON quads (subject_hash);`,
			`CREATE INDEX pos_index ON quads (predicate_hash);`,
			`CREATE INDEX osp_index ON quads (object_hash);`,
		)
	}
	return indexes
}
back to top