Skip to content
No description or website provided.
Go Other
  1. Go 99.7%
  2. Other 0.3%
Branch: master
Clone or download
Latest commit 07bce46 Oct 16, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
cmd/handy-spanner initial commit Oct 4, 2019
fake more compatible for array data type Oct 12, 2019
server update README Oct 14, 2019
.gitignore initial commit Oct 4, 2019
Dockerfile add tzdata Oct 16, 2019
LICENSE initial commit Oct 4, 2019
Makefile add json1 tags to use json extension in sqlite Oct 12, 2019 update README Oct 14, 2019
go.mod initial commit Oct 4, 2019
go.sum initial commit Oct 4, 2019

An emulator for Cloud Spanner


go get

The Spanner emulator uses sqlite3 internally. You may need to build go-sqlite3 explicitly. It also requires cgo to use sqlite3.

go get -u
go install


Run as an independent process



docker run --rm -it -p 9999:9999 handy-spanner

It runs a fake spanner server as a process. It serves spanner gRPC server by port 9999 by default.

Access to the server

The google-cloud-go, the official Spanner SDK, supports to access an emulator server. Set the address to an emulator server to environment variable SPANNER_EMULATOR_HOST, then google-cloud-go transparently use the server in the client.

So if you want to replace spanner server with the fake server you run, just do:

export SPANNER_EMULATOR_HOST=localhost:9999

Note that the fake spanner server has no databases nor tables by default. You need to create them by yourself.

Run as a buillt-in server in Go

If you use a fake spanner server in tests in Go, it's easier to run it in a process. See an example for the details.

Note that it becomes specific implementations for a fake server, which means you cannot switch the backend depending on the situation. If you want to test on both real spanner and fake, it's better to use a fake server as an independent process.

Can and Cannot

Supported features

  • Read
    • Keys and KeyRange as KeySet
    • Secondary index
    • STORING columns for secondary index
    • Respect column orders for index
  • Query
    • Select result set by column name and *
    • Most operators in WHERE clause: IN, BETWEEN, IS NULL
    • Conditions in WHERE clause: =, !=, >, <, AND, OR
    • Order By keyword with ASC, DESC
    • Group By and Having statement
    • SELECT alias
    • Query Parameters
    • Literals (except STRUCT)
    • JOINs
    • Subquery
    • SET operations: UNION, INTERSECT, EXCEPT
    • UNNEST
    • Functions (partially)
    • Arithmetic operations
  • Mutation
    • All mutation types: Insert, Update, InsertOrUpdate, Replace, Delete
    • Commit timestamp
  • DML
    • fully not yet supported
  • DDL
    • CreateTable, CreateIndex only
  • Data Types
    • Int, Float, String, Bool, Byte, Date, Timestamp, Array

Not supported features

  • Transaction
    • Applying mutations is not transactional
    • Optimistic lock
    • No check for transaction type RO/RW
  • Query
    • Strict type checking
    • More functions
    • Partionan Query
    • Merging INT64 and FLOAT64 in SET operations
    • Array operations
    • Struct
  • DML
    • not yet
  • DDL
    • Alter Table, Drop Table, Drop Index
    • Database management
    • Long running operations
  • Replace
    • wrong behavior on conflict


  • Author: Masahiro Sano (@kazegusuri)
  • Copyright: 2019 Masahiro Sano
  • License: Apache License, Version 2.0
You can’t perform that action at this time.