Commit b37b1644 authored by cznic's avatar cznic

WIP snapshot

parent 02caa576
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
QL type Go type
-----------------------------------------
blob []byte
bigint big.Int
bigrat big.Rat
time time.Time
duration time.Duration
Memory back-end stores the Go type directly.
File back-end must resort to encode all of the above as (tagged) []byte due to
the lack of more types supported natively by lldb.
NULL values of the above types are encoded as nil (gbNull in lldb/gb.go),
exactly the same as the already existing QL types are.
Encoding
The values of the above types are first encoded into a []byte slice:
blob
raw
bigint, bigrat, time
gob encoded
duration
gob encoded int64
If the length of the resulting slice is <= shortBlob, the first and only chunk
is encoded using lldb.EncodeScalars from
[]interface{}{typeTag, slice}.
len(slice) can be zero.
If the resulting slice is long, the first chunk comes from encoding
[]interface{}{typeTag, nextHandle, firstPart}.
len(firstPart) <= shortBlob.
Second and other chunks
If the chunk is the last one, src is
[]interface{lastPart}.
len(lastPart) <= 64kB.
If the chunk is not the last one, src is
[]interface{}{nextHandle, part}.
len(part) == 64kB.
*/
package ql
import (
"bytes"
"encoding/gob"
"log"
"math/big"
"time"
)
const shortBlob = 512 // bytes
var (
gobInitBuf = bytes.NewBuffer(nil)
gobInitInt = big.NewInt(42)
gobInitRat = big.NewRat(355, 113)
gobInitTime time.Time
)
func init() {
var err error
if gobInitTime, err = time.ParseInLocation(
"Jan 2, 2006 at 3:04pm (MST)",
"Jul 9, 2012 at 5:02am (CEST)",
time.FixedZone("UTC", 0),
); err != nil {
log.Panic(err)
}
newGobEncoder0(gobInitBuf)
newGobDecoder()
}
func newGobEncoder0(buf *bytes.Buffer) (enc *gob.Encoder) {
enc = gob.NewEncoder(buf)
if err := enc.Encode(gobInitInt); err != nil {
log.Panic(err)
}
if err := enc.Encode(gobInitRat); err != nil {
log.Panic(err)
}
if err := enc.Encode(gobInitTime); err != nil {
log.Panic(err)
}
return
}
func newGobEncoder() (enc *gob.Encoder) {
return newGobEncoder0(bytes.NewBuffer(nil))
}
func newGobDecoder() (dec *gob.Decoder) {
dec = gob.NewDecoder(bytes.NewBuffer(gobInitBuf.Bytes()))
i := big.NewInt(0)
if err := dec.Decode(i); err != nil {
log.Panic(err)
}
r := big.NewRat(3, 5)
if err := dec.Decode(r); err != nil {
log.Panic(err)
}
t := time.Now()
if err := dec.Decode(&t); err != nil {
log.Panic(err)
}
return
}
......@@ -28,7 +28,11 @@ const (
qUint32 = 0x77 // 'w'
qUint64 = 0x78 // 'x', alias uint
//LATER Gob = 'o'
qBigInt = 0x49 // 'I'
qBigRat = 0x52 // 'R'
qBlob = 0x42 // 'B'
qDuration = 0x44 // 'D'
qTime = 0x54 // 'T'
)
var (
......
......@@ -10,6 +10,7 @@ package ql
import (
"crypto/sha1"
"encoding/gob"
"fmt"
"io"
"io/ioutil"
......@@ -273,10 +274,10 @@ func read2(a *lldb.Allocator, dst []interface{}, h int64, cols ...*col) (data []
type fileTemp struct {
a *lldb.Allocator
f lldb.OSFile
t *lldb.BTree
colsK []*col
colsV []*col
f lldb.OSFile
t *lldb.BTree
}
func (t *fileTemp) BeginTransaction() error {
......@@ -350,8 +351,11 @@ func (t *fileTemp) Set(k, v []interface{}) (err error) {
type file struct {
a *lldb.Allocator
dec *gob.Decoder
enc *gob.Encoder
f lldb.Filer
f0 lldb.OSFile
gobmu sync.Mutex
id int64
lck io.Closer
name string
......@@ -440,6 +444,8 @@ func newFileFromOSFile(f lldb.OSFile) (fi *file, err error) {
a.Compress = true
s := &file{
a: a,
dec: newGobDecoder(),
enc: newGobEncoder(),
f0: f,
f: filer,
lck: lck,
......@@ -507,6 +513,8 @@ func newFileFromOSFile(f lldb.OSFile) (fi *file, err error) {
a.Compress = true
s := &file{
a: a,
dec: newGobDecoder(),
enc: newGobEncoder(),
f0: f,
f: filer,
id: id,
......
......@@ -56,6 +56,7 @@ func (t *memTemp) Get(k []interface{}) (v []interface{}, err error) {
}
func (t *memTemp) Create(data ...interface{}) (h int64, err error) {
//TODO append(nil, ...) not enough with new types
s := t.store
switch n := len(s.recycler); {
case n != 0:
......@@ -211,6 +212,7 @@ func (s *mem) ID() (id int64, err error) {
}
func (s *mem) Create(data ...interface{}) (h int64, err error) {
//TODO append(nil, ...) not enough with new types
switch n := len(s.recycler); {
case n != 0:
h = int64(s.recycler[n-1])
......@@ -234,6 +236,7 @@ func (s *mem) Create(data ...interface{}) (h int64, err error) {
}
func (s *mem) Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error) {
//TODO append(nil, ...) not enough with new types
if i := int(h); i != 0 && i < len(s.data) {
return append(dst[:0], s.data[h]...), nil
}
......
......@@ -3,7 +3,7 @@
//TODO Put your favorite license here
// yacc source generated by ebnf2y[1]
// at 2013-11-12 11:58:39.613860181 +0100 CET
// at 2013-11-19 12:55:21.615334751 +0100 CET
//
// $ ebnf2y -o ql.y -oe ql.ebnf -start StatementList -pkg ql -p _
//
......
......@@ -3101,3 +3101,22 @@ COMMIT;
SELECT count() FROM t;
|l
[6]
-- 297
BEGIN TRANSACTION;
CREATE TABLE t(S string);
INSERT INTO t SELECT "perfect!" FROM (SELECT count() AS cnt FROM t WHERE S == "perfect!") WHERE cnt == 0;
COMMIT;
SELECT count() FROM t;
|l
[1]
-- 298
BEGIN TRANSACTION;
CREATE TABLE t(S string);
INSERT INTO t SELECT "perfect!" FROM (SELECT count() AS cnt FROM t WHERE S == "perfect!") WHERE cnt == 0;
INSERT INTO t SELECT "perfect!" FROM (SELECT count() AS cnt FROM t WHERE S == "perfect!") WHERE cnt == 0;
COMMIT;
SELECT count() FROM t;
|l
[1]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment