unkodb

package module
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 28, 2023 License: MIT Imports: 14 Imported by: 1

README

unkodb

データを単一ファイルに読み書きする感じ?
DBではないです。


説明?
  • ファイルサイズは2GB以下までしか扱えない
  • ファイルに対しては直接の操作ではなくインターフェース(io.ReadWriteSeeker)越しの読み書きしか行わない(共有ロックやFlushCloseなどの処理等は呼び出し側のほうで行う必要がある)
  • データのサイズの変わる更新や削除を行うと使用できないゴミ領域が発生するが対処はしてない
  • テーブルの名前やカラムを変える仕組みは無い
  • 無駄なIO処理やメモリ確保が多いため大量のデータの取り扱いや頻繁なアクセスには向いてない
  • トランザクションのような仕組みは無い
  • スレッドセーフではない
  • フェイルセーフではない
  • ファイルフォーマットを確認しないため不正なファイル読み込みでパニックするかも
  • テーブル名とカラム名は1バイト以上255バイト以下で指定する必要がある(Goのstringを[]byteにキャストした際のサイズ)
  • テーブル名とカラム名に使える文字は今のところ制限は設けていない
  • カラム数はテーブルごとに100個まで
  • 内部的にはAVL木で管理されている(AVL木の実装が正しければよいが・・・)
  • 各テーブルにキーを1つ指定する
  • データの検索はキーでのみ行える(キーの重複は許されてない)
  • デバッグ不十分なのでバグだらけなのでバグでデータが破壊される可能性が高いです(死)
map[string]anyでデータを取り扱う

キー名やカラム名をマップのキーとして各値を保持する。(値の型に注意する必要がある)

package example

import (
	"fmt"
	"log"
	"os"

	"github.com/neetsdkasu/unkodb"
)

func ExampleUnkoDB() {

	// Exampleのテスト用のファイルなのでテスト実行後は削除する・・・
	const FileExists = false
	file, err := os.CreateTemp("", "example.unkodb")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(file.Name())

	var (
		db    *unkodb.UnkoDB
		table *unkodb.Table
	)

	if FileExists {
		// file, err := os.OpenFile("example.unkodb", os.O_RDWR, 0755)
		// defer file.Close()

		db, err = unkodb.Open(file)
		if err != nil {
			log.Fatal(err)
		}

		table = db.Table("food_table")
		if table == nil {
			log.Fatal("not found food_table")
		}

	} else {
		// file, err := os.Create("example.unkodb")
		// defer file.Close()

		db, err = unkodb.Create(file)
		if err != nil {
			log.Fatal(err)
		}

		tc, err := db.CreateTable("food_table")
		if err != nil {
			log.Fatal(err)
		}

		tc.CounterKey("id")
		tc.ShortStringColumn("name")
		tc.Int64Column("price")

		table, err = tc.Create()
		if err != nil {
			log.Fatal(err)
		}

		list := []map[string]any{
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "クリームパン",
				"price": int64(234),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "あんぱん",
				"price": int64(123),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "カレーパン",
				"price": int64(345),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "ジャムパン",
				"price": int64(222),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "食パン",
				"price": int64(333),
			},
		}

		// Insert
		for _, item := range list {
			_, err = table.Insert(item)
			if err != nil {
				log.Fatal(err)
			}
		}

		// Delete id=3 カレーパン
		err = table.Delete(unkodb.CounterType(3))
		if err != nil {
			log.Fatal(err)
		}

		// Replace id=4 ジャムパン
		replace := map[string]any{
			"id":    unkodb.CounterType(4),
			"name":  "イチゴジャムパン",
			"price": int64(987),
		}
		_, err = table.Replace(replace)
		if err != nil {
			log.Fatal(err)
		}

	}

	// Find id=2 あんぱん
	r, err := table.Find(unkodb.CounterType(2))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("[FIND] ID: %d, NAME: %s, PRICE: %d\n", r.Key(), r.Column("name"), r.Column("price"))

	// Iteration データを順番に辿る
	err = table.IterateAll(func(r *unkodb.Record) (breakIteration bool) {
		fmt.Printf("[ITER] id: %d, name: %s, price: %d\n", r.Column("id"), r.Column("name"), r.Column("price"))
		return
	})
	if err != nil {
		log.Fatal(err)
	}

	// Output:
	// [FIND] ID: 2, NAME: あんぱん, PRICE: 123
	// [ITER] id: 1, name: クリームパン, price: 234
	// [ITER] id: 2, name: あんぱん, price: 123
	// [ITER] id: 4, name: イチゴジャムパン, price: 987
	// [ITER] id: 5, name: 食パン, price: 333
}
unkodb.Dataでデータを取り扱う

キーの値とカラムの値だけを保持するunkodb.Dataを用いる。(値の型に注意する必要がある)

package example

import (
	"fmt"
	"log"
	"os"

	"github.com/neetsdkasu/unkodb"
)

func ExampleUnkoDB_withDataStruct() {

	// Exampleのテスト用のファイルなのでテスト実行後は削除する・・・
	const FileExists = false
	file, err := os.CreateTemp("", "example.unkodb")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(file.Name())

	var (
		db    *unkodb.UnkoDB
		table *unkodb.Table
	)

	if FileExists {
		// file, err := os.OpenFile("example.unkodb", os.O_RDWR, 0755)
		// defer file.Close()

		db, err = unkodb.Open(file)
		if err != nil {
			log.Fatal(err)
		}

		table = db.Table("food_table")
		if table == nil {
			log.Fatal("not found food_table")
		}

	} else {
		// file, err := os.Create("example.unkodb")
		// defer file.Close()

		db, err = unkodb.Create(file)
		if err != nil {
			log.Fatal(err)
		}

		tc, err := db.CreateTable("food_table")
		if err != nil {
			log.Fatal(err)
		}

		tc.CounterKey("id")
		tc.ShortStringColumn("name")
		tc.Int64Column("price")

		table, err = tc.Create()
		if err != nil {
			log.Fatal(err)
		}

		list := []*unkodb.Data{
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"クリームパン", int64(234)},
			},
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"あんぱん", int64(123)},
			},
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"カレーパン", int64(345)},
			},
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"ジャムパン", int64(222)},
			},
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"食パン", int64(333)},
			},
		}

		// Insert
		for _, item := range list {
			_, err = table.Insert(item)
			if err != nil {
				log.Fatal(err)
			}
		}

		// Delete id=3 カレーパン
		err = table.Delete(unkodb.CounterType(3))
		if err != nil {
			log.Fatal(err)
		}

		// Replace id=4 ジャムパン
		replace := &unkodb.Data{
			Key:     unkodb.CounterType(4),
			Columns: []any{"イチゴジャムパン", int64(987)},
		}
		_, err = table.Replace(replace)
		if err != nil {
			log.Fatal(err)
		}

	}

	// Find id=2 あんぱん
	r, err := table.Find(unkodb.CounterType(2))
	if err != nil {
		log.Fatal(err)
	}
	var food unkodb.Data
	err = r.MoveTo(&food)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("[FIND] ID: %d, NAME: %s, PRICE: %d\n", food.Key, food.Columns[0], food.Columns[1])

	// Iteration データを順番に辿る
	err = table.IterateAll(func(r *unkodb.Record) (breakIteration bool) {
		f := &unkodb.Data{}
		err := r.MoveTo(f)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("[ITER] id: %d, name: %s, price: %d\n", f.Key, f.Columns[0], f.Columns[1])
		return
	})
	if err != nil {
		log.Fatal(err)
	}

	// Output:
	// [FIND] ID: 2, NAME: あんぱん, PRICE: 123
	// [ITER] id: 1, name: クリームパン, price: 234
	// [ITER] id: 2, name: あんぱん, price: 123
	// [ITER] id: 4, name: イチゴジャムパン, price: 987
	// [ITER] id: 5, name: 食パン, price: 333
}
unkodbのタグをつけた構造体でデータを取り扱う

ユーザ定義の型の各フィールドにタグunkodbを振る。カラム名とカラム型を記述する必要がある。キーとなるフィールドのカラム型にはkey@プリフィクスをつける。

package example

import (
	"fmt"
	"log"
	"os"

	"github.com/neetsdkasu/unkodb"
)

func ExampleUnkoDB_withTaggedStruct() {

	// Exampleのテスト用のファイルなのでテスト実行後は削除する・・・
	const FileExists = false
	file, err := os.CreateTemp("", "example.unkodb")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(file.Name())

	type Food struct {
		Id    unkodb.CounterType `unkodb:"id,key@Counter"`
		Name  string             `unkodb:"name,ShortString"`
		Price int64              `unkodb:"price,Int64"`
	}

	var (
		db    *unkodb.UnkoDB
		table *unkodb.Table
	)

	if FileExists {
		// file, err := os.OpenFile("example.unkodb", os.O_RDWR, 0755)
		// defer file.Close()

		db, err = unkodb.Open(file)
		if err != nil {
			log.Fatal(err)
		}

		table = db.Table("food_table")
		if table == nil {
			log.Fatal("not found food_table")
		}

	} else {
		// file, err := os.Create("example.unkodb")
		// defer file.Close()

		db, err = unkodb.Create(file)
		if err != nil {
			log.Fatal(err)
		}

		table, err = db.CreateTableByTaggedStruct("food_table", (*Food)(nil))
		if err != nil {
			log.Fatal(err)
		}

		list := []*Food{
			&Food{
				Name:  "クリームパン",
				Price: 234,
			},
			&Food{
				Name:  "あんぱん",
				Price: 123,
			},
			&Food{
				Name:  "カレーパン",
				Price: 345,
			},
			&Food{
				Name:  "ジャムパン",
				Price: 222,
			},
			&Food{
				Name:  "食パン",
				Price: 333,
			},
		}

		// Insert
		for _, item := range list {
			_, err = table.Insert(item)
			if err != nil {
				log.Fatal(err)
			}
		}

		// Delete id=3 カレーパン
		err = table.Delete(unkodb.CounterType(3))
		if err != nil {
			log.Fatal(err)
		}

		// Replace id=4 ジャムパン
		replace := &Food{
			Id:    4,
			Name:  "イチゴジャムパン",
			Price: 987,
		}
		_, err = table.Replace(replace)
		if err != nil {
			log.Fatal(err)
		}

	}

	// Find id=2 あんぱん
	r, err := table.Find(unkodb.CounterType(2))
	if err != nil {
		log.Fatal(err)
	}
	var food Food
	err = r.MoveTo(&food)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("[FIND] ID: %d, NAME: %s, PRICE: %d\n", food.Id, food.Name, food.Price)

	// Iteration データを順番に辿る
	err = table.IterateAll(func(r *unkodb.Record) (breakIteration bool) {
		f := &Food{}
		err := r.MoveTo(f)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("[ITER] id: %d, name: %s, price: %d\n", f.Id, f.Name, f.Price)
		return
	})
	if err != nil {
		log.Fatal(err)
	}

	// Output:
	// [FIND] ID: 2, NAME: あんぱん, PRICE: 123
	// [ITER] id: 1, name: クリームパン, price: 234
	// [ITER] id: 2, name: あんぱん, price: 123
	// [ITER] id: 4, name: イチゴジャムパン, price: 987
	// [ITER] id: 5, name: 食パン, price: 333
}
カラムの型
カラムの型 キー カラム Goの型 備考
Counter uint32 データが挿入時に値が設定される。挿入ごとに1ずつ値が増えていく(最初は1から始まる)。unkodb.CounterTypeはuint32のエイリアス。
Int8 int8
Int16 int16
Int32 int32
Int64 int64
Uint8 uint8
Uint16 uint16
Uint32 uint32
Uint64 uint64
Float32 float32
Float64 float64
ShortString string 内部的には[]byteで保存される。0~255バイトに収まる必要がある。バイト長もデータごとに保存される。キーとして使う場合はstrings.Compareが順序に使用される。
FixedSizeShortString string 内部的には[]byteで保存される。テーブル作成時に指定した固定バイトサイズ(1~255バイト)で保存される。サイズ未満の文字列の場合、指定バイトサイズになるよう半角スペースが埋められる。キーとして使う場合はstrings.Compareが順序に使用される。
LongString string 内部的には[]byteで保存される。0~65535バイトに収まる必要がある。バイト長もデータごとに保存される。
FixedSizeLongString string 内部的には[]byteで保存される。テーブル作成時に指定した固定バイトサイズ(1~65535バイト)で保存される。サイズ未満の文字列の場合、指定バイトサイズになるよう半角スペースが埋められる。
Text string 内部的には[]byteで保存される。0~1073741823バイトに収まる必要がある。バイト長もデータごとに保存される。(データは丸ごとメモリ上にロードされるのでサイズに注意)
ShortBytes []byte 0~255バイトに収まる必要がある。バイト長もデータごとに保存される。キーとして使う場合はbytes.Compareが順序に使用される。
FixedSizeShortBytes []byte テーブル作成時に指定した固定バイトサイズ(1~255バイト)で保存される。サイズ未満のバイトスライスの場合、指定バイトサイズになるようbyte(0)が埋められる。キーとして使う場合はbytes.Compareが順序に使用される。
LongBytes []byte 0~65535バイトに収まる必要がある。バイト長もデータごとに保存される。
FixedSizeLongBytes []byte テーブル作成時に指定した固定バイトサイズ(1~65535バイト)で保存される。サイズ未満のバイトスライスの場合、指定バイトサイズになるようbyte(0)が埋められる。
Blob []byte 0~1073741823バイトに収まる必要がある。バイト長もデータごとに保存される。(データは丸ごとメモリ上にロードされるのでサイズに注意)
タグを用いる場合の表記例

カラム名とカラム型をカンマで区切って指定する。カラム型の指定は大文字小文字を区別するので注意。キーとなるフィールドのカラム型にはkey@プリフィクスをつける。カラム型の固定バイト長のサイズは角括弧でカラム型に続けて指定する。

type Foo struct {
	CounterValue unkodb.CounterType `unkodb:"id,key@Counter"`
	Int8value    int8               `unkodb:"i8,Int8"`
	Int16value   int16              `unkodb:"i16,Int16"`
	Int32value   int32              `unkodb:"i32,Int32"`
	Int64value   int64              `unkodb:"i64,Int64"`
	Uint8value   uint8              `unkodb:"u8,Uint8"`
	Uint16value  uint16             `unkodb:"u16,Uint16"`
	Uint32value  uint32             `unkodb:"u32,Uint32"`
	Uint64value  uint64             `unkodb:"u64,Uint64"`
	Float32value float32            `unkodb:"f32,Float32"`
	Float64value float64            `unkodb:"f64,Float64"`
	SSvalue      string             `unkodb:"ss,ShortString"`
	FSSSvalue    string             `unkodb:"fsss,FixedSizeShortString[100]"`
	LSvalue      string             `unkodb:"ls,LongString"`
	FSLSvalue    string             `unkodb:"fsls,FixedSizeLongString[500]"`
	Text         string             `unkodb:"tx,Text"`
	SBvalue      []byte             `unkodb:"sb,ShortBytes"`
	FSSBvalue    []byte             `unkodb:"fssb,FixedSizeShortBytes[20]"`
	LBvalue      []byte             `unkodb:"lb,LongBytes"`
	FSLBvalue    []byte             `unkodb:"fslb,FixedSizeLongBytes[300]"`
	Blob         []byte             `unkodb:"bl,Blob"`
}

Documentation

Overview

unkodb

データを単一ファイルに読み書きする感じ?

DBではないです。

- ファイルサイズは2GB以下までしか扱えない。

- ファイルに対しては直接の操作ではなくインターフェース(`io.ReadWriteSeeker`)越しの読み書きしか行わない(共有ロックや`Flush`や`Close`などの処理等は呼び出し側のほうで行う必要がある)。

- データのサイズの変わる更新や削除を行うと使用できないゴミ領域が発生するが対処はしてない。

- テーブルの名前やカラムを変える仕組みは無い。

- 無駄なIO処理やメモリ確保が多いため大量のデータの取り扱いや頻繁なアクセスには向いてない。

- トランザクションのような仕組みは無い。

- スレッドセーフではない。

- フェイルセーフではない。

- ファイルフォーマットを確認しないため不正なファイル読み込みでパニックするかも。

- テーブル名とカラム名は1バイト以上255バイト以下で指定する必要がある(Goのstringを[]byteにキャストした際のサイズ)。

- テーブル名とカラム名に使える文字は今のところ制限は設けていない。

- カラム数はテーブルごとに100個まで。

- 内部的にはAVL木で管理されている(AVL木の実装が正しければよいが・・・)。 / - 各テーブルにキーを1つ指定する。

- データの検索はキーでのみ行える(キーの重複は許されてない)。

- デバッグ不十分なのでバグだらけなのでバグでデータが破壊される可能性が高いです(死)。

package example
import (
	"fmt"
	"log"
	"os"
	"github.com/neetsdkasu/unkodb"
)
func ExampleUnkoDB() {
	// Exampleのテスト用のファイルなのでテスト実行後は削除する・・・
	const FileExists = false
	file, err := os.CreateTemp("", "example.unkodb")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(file.Name())
	var (
		db    *unkodb.UnkoDB
		table *unkodb.Table
	)
	if FileExists {
		// file, err := os.OpenFile("example.unkodb", os.O_RDWR, 0755)
		// defer file.Close()
		db, err = unkodb.Open(file)
		if err != nil {
			log.Fatal(err)
		}
		table = db.Table("food_table")
		if table == nil {
			log.Fatal("not found food_table")
		}
	} else {
		// file, err := os.Create("example.unkodb")
		// defer file.Close()
		db, err = unkodb.Create(file)
		if err != nil {
			log.Fatal(err)
		}
		tc, err := db.CreateTable("food_table")
		if err != nil {
			log.Fatal(err)
		}
		tc.CounterKey("id")
		tc.ShortStringColumn("name")
		tc.Int64Column("price")
		table, err = tc.Create()
		if err != nil {
			log.Fatal(err)
		}
		list := []map[string]any{
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "クリームパン",
				"price": int64(234),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "あんぱん",
				"price": int64(123),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "カレーパン",
				"price": int64(345),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "ジャムパン",
				"price": int64(222),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "食パン",
				"price": int64(333),
			},
		}
		// Insert
		for _, item := range list {
			_, err = table.Insert(item)
			if err != nil {
				log.Fatal(err)
			}
		}
		// Delete id=3 カレーパン
		err = table.Delete(unkodb.CounterType(3))
		if err != nil {
			log.Fatal(err)
		}
		// Replace id=4 ジャムパン
		replace := map[string]any{
			"id":    unkodb.CounterType(4),
			"name":  "イチゴジャムパン",
			"price": int64(987),
		}
		_, err = table.Replace(replace)
		if err != nil {
			log.Fatal(err)
		}
	}
	// Find id=2 あんぱん
	r, err := table.Find(unkodb.CounterType(2))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("[FIND] ID: %d, NAME: %s, PRICE: %d\n", r.Key(), r.Column("name"), r.Column("price"))
	// Iteration データを順番に辿る
	err = table.IterateAll(func(r *unkodb.Record) (breakIteration bool) {
		fmt.Printf("[ITER] id: %d, name: %s, price: %d\n", r.Column("id"), r.Column("name"), r.Column("price"))
		return
	})
	if err != nil {
		log.Fatal(err)
	}
	// Output:
	// [FIND] ID: 2, NAME: あんぱん, PRICE: 123
	// [ITER] id: 1, name: クリームパン, price: 234
	// [ITER] id: 2, name: あんぱん, price: 123
	// [ITER] id: 4, name: イチゴジャムパン, price: 987
	// [ITER] id: 5, name: 食パン, price: 333
}

Index

Examples

Constants

View Source
const (
	// テーブル名として使える最大のバイトサイズ(stringを[]byteにキャストしたさいのサイズ)
	MaximumTableNameByteSize = 255

	// カラム名として使える最大のバイトサイズ(stringを[]byteにキャストしたさいのサイズ)
	MaximumColumnNameByteSize = 255

	// テーブルに設定できる最大のカラム数(このカラム数にキーは含めない)
	MaximumColumnCountWithoutKey = 100
)

Variables

View Source
var (
	// テーブル名が長すぎるときのエラー
	ErrTableNameIsTooLong = errors.New("ErrTableNameIsTooLong")

	// String系やBytes系のカラム型に収まらないサイズのデータが渡されたときのエラー
	ErrTooLargeData = errors.New("ErrTooLargeData")

	// キーのカラム型がCounterのときに対応しないGoの型でデータが渡されたときのエラー
	ErrKeyIsNotCounter = errors.New("ErrKeyIsNotCounter")

	// FindやDeleteなどで存在しないキーが指定されたときのエラー
	ErrNotFoundKey = errors.New("ErrNotFoundKey")

	// InsertやReplaceなどで引数に受け付けない型を受け取ったときのエラー
	ErrNotFoundData = errors.New("ErrNotFoundData")

	// 存在しないテーブル名を指定されたときのエラー
	ErrNotFoundTable = errors.New("ErrNotFoundTable")

	// unkodbタグをつけたフィールドのGoの型が指定のカラム型に対応しないときのエラー
	ErrCannotAssignValueToField = errors.New("ErrCannotAssignValueToField")

	// 既に存在するテーブル名で新しくテーブルを作ろうとしたときのエラー
	ErrTableNameAlreadyExists = errors.New("ErrTableNameAlreadyExists")

	// テーブルでのInsertにおいて既に存在するキーでデータを追加しようとしたときのエラー
	// あるいは
	// テーブル作成時に2つめのキーを作成しようとしたときのエラー
	ErrKeyAlreadyExists = errors.New("ErrKeyAlreadyExists")

	// テーブルの作成時に同じカラム名のカラムを追加しようとしたときのエラー
	ErrColumnNameAlreadyExists = errors.New("ErrColumnNameAlreadyExists")

	// テーブルの作成時にカラム名が長すぎるときのエラー
	ErrColumnNameIsTooLong = errors.New("ErrColumnNameIsTooLong")

	// テーブル作成時に空のカラム名を設定しようとしたときのエラー
	ErrNeedColumnName = errors.New("ErrNeedColumnName")

	// 不正にメソッドを呼び出しされたときのエラー
	// 例えば、イテレーション中にテーブルを変更するメソッドを呼び出したときなど
	ErrInvalidOperation = errors.New("ErrInvalidOperation")

	// テーブル作成時にキーが設定されないままテーブルの生成処理が実行されたときのエラー
	ErrNeedToSetAKey = errors.New("ErrNeedToSetAKey")

	// テーブル作成時に固定長タイプのカラム型でサイズに0が指定されたときのエラー
	ErrSizeMustBePositiveValue = errors.New("ErrSizeMustBePositiveValue")

	// テーブル作成時にテーブルに設定できる最大カラム数を超えてカラムを作ろうとしたときのエラー
	ErrColumnCountIsFull = errors.New("ErrColumnCountIsFull")
)

Functions

func ColumnTypeHint

func ColumnTypeHint(col Column) string

unkodbタグに書き込むカラム型名と対応するGoの型を文字列にして返す。

Types

type Column

type Column interface {
	// カラム名
	Name() string

	// カラムのデータ型
	Type() ColumnType

	// 引数の値の型がカラム型として使えるかを判定
	// 文字列やバイト列の場合は許容サイズかどうかも判定される
	IsValidValueType(value any) bool

	// データ領域の最小バイトサイズ
	MinimumDataByteSize() uint64

	// データ領域の最大バイトサイズ
	MaximumDataByteSize() uint64
	// contains filtered or unexported methods
}

カラム定義に関する情報を保持する。

type ColumnType

type ColumnType int

カラム型の種類を表す。

const (
	Counter ColumnType
	Int8
	Uint8
	Int16
	Uint16
	Int32
	Uint32
	Int64
	Uint64
	Float32
	Float64
	ShortString
	FixedSizeShortString
	LongString
	FixedSizeLongString
	Text
	ShortBytes
	FixedSizeShortBytes
	LongBytes
	FixedSizeLongBytes
	Blob
)

カラム型を表現する値

func (ColumnType) GoTypeHint

func (ct ColumnType) GoTypeHint() string

カラム型に対応するGoの型を返す。

func (ColumnType) String

func (ct ColumnType) String() string

type CounterType

type CounterType = uint32

カラム型のCounterで用いるGoの型。ただのuint32のエイリアス。

type Data

type Data struct {
	Key     any
	Columns []any
}

テーブルとデータをやりとりする際に使うことができる簡易データホルダー。 キーやカラムのカラム型に対応したGoの型で値を設定する必要がある。 Columnsの値はテーブルのColumnsと同じ順番で設定する必要がある。

tc, _ := db.CreateTable("my_book_table")
tc.CounterKey("id")
tc.ShortStringColumn("title")
tc.ShortStringColumn("author")
tc.Int64Column("price")
table, _ := tc.Create()
table.Insert(unkodb.Data{
	Key: unkodb.CounterType(0),
	Columns: []any{
		"プログラミング入門",
		"いにしえのプログラマー",
		int64(4800),
	},
})

type ErrNotFoundColumnName added in v0.3.0

type ErrNotFoundColumnName struct{ Column }

InsertやReplaceなどでテーブルのデータに必要なカラムが不足しているときのエラー

func (*ErrNotFoundColumnName) Error added in v0.3.0

func (err *ErrNotFoundColumnName) Error() string

type ErrUnmatchColumnValueType added in v0.3.0

type ErrUnmatchColumnValueType struct{ Column }

テーブルに定義されたカラム型に対応しないGoの型で値を受け取ったときのエラー

func (*ErrUnmatchColumnValueType) Error added in v0.3.0

func (err *ErrUnmatchColumnValueType) Error() string

type ErrWrongFileFormat added in v0.3.0

type ErrWrongFileFormat struct {
	// contains filtered or unexported fields
}

壊れているunkodbファイルあるいは無関係なファイルを読み込んだときのエラー

func (*ErrWrongFileFormat) Error added in v0.3.0

func (err *ErrWrongFileFormat) Error() string

type ErrWrongTag added in v0.3.0

type ErrWrongTag struct {
	// contains filtered or unexported fields
}

unkodbタグにおけるタグの記述に関するエラー

func (*ErrWrongTag) Error added in v0.3.0

func (err *ErrWrongTag) Error() string

type IterateCallbackFunc

type IterateCallbackFunc = func(r *Record) (breakIteration bool)

データのイテレーションに使用するコールバック関数。 イテレーションを中断したい場合には戻り値breakIterationにtrueを指定する。

type IterateKeyCallbackFunc

type IterateKeyCallbackFunc = func(key any) (breakIteration bool)

キーのイテレーションに使用するコールバック関数。 イテレーションを中断したい場合には戻り値breakIterationにtrueを指定する。

type Record

type Record struct {
	// contains filtered or unexported fields
}

データのコピーを保持する。

func (*Record) Column

func (r *Record) Column(name string) any

指定カラム名のカラムの値を参照する。 テーブルに存在しないカラム名の場合はnilが返る。 キー名も指定できる。

r, _ := table.Find(unkodb.CounterType(123))
fmt.Println("id=", r.Column("id"), "name=", r.Column("name"))

func (*Record) Columns

func (r *Record) Columns() []any

カラムの値を参照するリストを返す。 値の順序はテーブルのカラムの順序と同じ。

func (*Record) CopyTo

func (r *Record) CopyTo(dst any) (err error)

データの値をdstで渡した構造体にコピーする。 dstにはunkodb.Dataかunkodbタグ付きの構造体のインスタンスを指定する。 引数のdstに対応できない型などが渡された場合はエラーが返る。

r, _ := table.Find(unkodb.CounterType(123))
var dst1, dst2 unkodb.Data
r.CopyTo(&dst1)
r.CopyTo(&dst2)

func (*Record) Key

func (r *Record) Key() (value any)

データのキーを参照する。

r, _ := table.Find(unkodb.CounterType(123))
fmt.Println("key=", r.Key(), "value=", r.Column("value"))

func (*Record) MoveTo

func (r *Record) MoveTo(dst any) (err error)

データの値をdstで渡した構造体に移動する。 dstにはunkodb.Dataかunkodbタグ付きの構造体のインスタンスを指定する。 データ移動後はこの*Recordは使用不可になる。 引数のdstに対応できない型などが渡された場合はエラーが返る。

r, _ := table.Find(unkodb.CounterType(123))
var dst unkodb.Data
r.MoveTo(&dst)

func (*Record) Table

func (r *Record) Table() *Table

データ元のテーブルを参照する。

func (*Record) Take

func (r *Record) Take() (data map[string]any)

内部で保持してるデータを取り出す。 このメソッドの実行後はこの*Recordは使用不可になる。

r, _ := table.Find(unkodb.CounterType(123))
fmt.Println("id=", r.Column("id"), "name=", r.Column("name"))
data := r.Take()
fmt.Println("id=", data["id"], "name=", data["name"])

type Table

type Table struct {
	// contains filtered or unexported fields
}

func (*Table) CheckData

func (table *Table) CheckData(data any) (err error)

InsertやReplaceに渡すデータにおいて各カラムのデータの型に問題にないかを確認をする(カラム情報のIsValidValueTypeメソッドで確認する)。 引数のdataにはmap[string]anyもしくはunkodb.Dataもしくはunkodbタグを付けた構造体のインスタンスを渡す。 データ型に問題がある場合はErrUnmatchColumnValueTypeが返る。それ以外の問題がある場合はErrWrongTagなどのエラーが返る。

func (*Table) Column

func (table *Table) Column(name string) Column

指定したカラム名のカラム情報を返す。 指定したカラム名が存在しない場合はnilを返す。 キー名も指定できる。

func (*Table) Columns

func (table *Table) Columns() []Column

このテーブルの全てのカラムのカラム情報をリストにして返す。 このリストにはキーは含まれない。

func (*Table) Count

func (table *Table) Count() int

テーブルに存在するキーの数を返す。

func (*Table) Delete

func (table *Table) Delete(key any) (err error)

指定したキーに対応するデータとキーを削除する。 キーのカラム型に対応したGoの型で渡す必要がある。 指定したキーに対応するデータが存在しない場合には戻り値のエラーはErrNotFoundKeyとなる。 それ以外のエラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー)

func (*Table) Find

func (table *Table) Find(key any) (r *Record, err error)

指定したキーに対応するデータを取得する。 キーのカラム型に対応したGoの型で渡す必要がある。 指定したキーに対応するデータが存在しない場合には戻り値は全てnilとなる。 キーの型が不正な場合は対応するエラーが返る。 それ以外のエラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー)

func (*Table) Insert

func (table *Table) Insert(data any) (r *Record, err error)

テーブルにデータを挿入する。 引数のdataにはmap[string]anyもしくはunkodb.Dataもしくはunkodbタグを付けた構造体のインスタンスを渡す。 dataにはキーとカラムの全ての値をセットしておく必要がある。 キーのカラム型がCounterの場合はセットされたキーの値は無視される。 戻り値の*Recordには挿入されたデータのコピーが入る。 キーのカラム型がCounterの場合は戻り値の*Recordにキーがセットされるのでキーの確認ができる。 キーが既にテーブルに存在する場合はKeyAlreadyExistsのエラーが返る。 引数のdataに不正がある場合は対応したエラーが返る。 それ以外のエラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー)

data := map[string]any{
	"id":     unkodb.CounterType(0),
	"title":  "プログラミング入門の本",
	"author": "プログラマーのティーチャー",
	"genre":  "技術書",
}
r, _ := table.Insert(data)
fmt.Println("idは", r.Key(), "になりました")

func (*Table) IterateAll

func (table *Table) IterateAll(callback IterateCallbackFunc) (err error)

テーブルに存在するデータのコピーをキーの昇順でコールバック関数に渡していく。 イテレーション中はInsert/Replace/Delete/DeleteTableなどのテーブル変更操作を行うとデータが壊れる。 エラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー) コールバック関数内でのpanicはエラーとして返ることがある。(その場合、スタックトレース取得などはコールバック関数内で頑張って)。

table.IterateAll(func(r *unkodb.Record) (breakIteration bool) {
	if r.Column("value").(int32) == 123 {
		fmt.Println("valueが123となる最初のキーは", r.Key(), "です")
		// IterateAllを中断する
		breakIteration = true
	}
	return
})

func (*Table) IterateAllKeys

func (table *Table) IterateAllKeys(callback IterateKeyCallbackFunc) (err error)

テーブルに存在するキーのコピーを昇順でコールバック関数に渡していく。 イテレーション中はInsert/Replace/Delete/DeleteTableなどのテーブル変更操作を行うとデータが壊れる。 エラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー) コールバック関数内でのpanicはエラーとして返ることがある。(その場合、スタックトレース取得などはコールバック関数内で頑張って)。

table.IterateAllKeys(func(key any) (breakIteration bool) {
	if key.(int32) > 123 {
		fmt.Println("123を超える最初のキーは", r.Key(), "です")
		// IterateAllKeysを中断する
		breakIteration = true
	}
	return
})

func (*Table) IterateBackAll

func (table *Table) IterateBackAll(callback IterateCallbackFunc) (err error)

テーブルに存在するデータのコピーをキーの降順でコールバック関数に渡していく。 イテレーション中はInsert/Replace/Delete/DeleteTableなどのテーブル変更操作を行うとデータが壊れる。 エラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー) コールバック関数内でのpanicはエラーとして返ることがある。(その場合、スタックトレース取得などはコールバック関数内で頑張って)。

table.IterateBackAll(func(r *unkodb.Record) (breakIteration bool) {
	if r.Column("value").(int32) == 123 {
		fmt.Println("valueが123となる最後のキーは", r.Key(), "です")
		// IterateBackAllを中断する
		breakIteration = true
	}
	return
})

func (*Table) IterateBackAllKeys

func (table *Table) IterateBackAllKeys(callback IterateKeyCallbackFunc) (err error)

テーブルに存在するキーのコピーを降順でコールバック関数に渡していく。 イテレーション中はInsert/Replace/Delete/DeleteTableなどのテーブル変更操作を行うとデータが壊れる。 エラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー) コールバック関数内でのpanicはエラーとして返ることがある。(その場合、スタックトレース取得などはコールバック関数内で頑張って)。

table.IterateBackAllKeys(func(r *unkodb.Record) (breakIteration bool) {
	if key.(int32) < 123 {
		fmt.Println("123未満の最後のキーは", r.Key(), "です")
		// IterateBackAllKeysを中断する
		breakIteration = true
	}
	return
})

func (*Table) IterateBackRange

func (table *Table) IterateBackRange(lowerKey, upperKey any, callback IterateCallbackFunc) (err error)

テーブルの指定範囲内に存在するデータのコピーをキーの降順でコールバック関数に渡していく。 lowerKey以上upperKey以下のキーの範囲のデータを辿る。 キーの指定にはキーのカラム型に合ったGoの型で指定する必要がある。 イテレーション中はInsert/Replace/Delete/DeleteTableなどのテーブル変更操作を行うとデータが壊れる。 エラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー) コールバック関数内でのpanicはエラーとして返ることがある。(その場合、スタックトレース取得などはコールバック関数内で頑張って)。

lowerKey := unkodb.Counter(1000)
upperKey := unkodb.Counter(1999)
table.IterateBackRange(lowerKey, upperKey, func(r *unkodb.Record) (breakIteration bool) {
	if r.Column("value").(int32) == 123 {
		fmt.Println("valueが123となる最後のキーは", r.Key(), "です")
		// IterateBackRangeを中断する
		breakIteration = true
	}
	return
})

func (*Table) IterateBackRangeKeys

func (table *Table) IterateBackRangeKeys(lowerKey, upperKey any, callback IterateKeyCallbackFunc) (err error)

テーブルの指定範囲内に存在するキーのコピーを降順でコールバック関数に渡していく。 lowerKey以上upperKey以下の範囲のキーを辿る。 キーの指定にはキーのカラム型に合ったGoの型で指定する必要がある。 イテレーション中はInsert/Replace/Delete/DeleteTableなどのテーブル変更操作を行うとデータが壊れる。 エラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー) コールバック関数内でのpanicはエラーとして返ることがある。(その場合、スタックトレース取得などはコールバック関数内で頑張って)。

lowerKey := int32(100)
upperKey := int32(199)
table.IterateBackRangeKeys(lowerKey, upperKey, func(key any) (breakIteration bool) {
	if key.(int32) % 7 == 0 {
		fmt.Println("7の倍数である最後のキーは", r.Key(), "です")
		// IterateBackRangeKeysを中断する
		breakIteration = true
	}
	return
})

func (*Table) IterateRange

func (table *Table) IterateRange(lowerKey, upperKey any, callback IterateCallbackFunc) (err error)

テーブルの指定範囲内に存在するデータのコピーをキーの昇順でコールバック関数に渡していく。 lowerKey以上upperKey以下のキーの範囲のデータを辿る。 キーの指定にはキーのカラム型に合ったGoの型で指定する必要がある。 イテレーション中はInsert/Replace/Delete/DeleteTableなどのテーブル変更操作を行うとデータが壊れる。 エラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー) コールバック関数内でのpanicはエラーとして返ることがある。(その場合、スタックトレース取得などはコールバック関数内で頑張って)。

lowerKey := unkodb.Counter(1000)
upperKey := unkodb.Counter(1999)
table.IterateRange(lowerKey, upperKey, func(r *unkodb.Record) (breakIteration bool) {
	if r.Column("value").(int32) == 123 {
		fmt.Println("valueが123となる最初のキーは", r.Key(), "です")
		// IterateRangeを中断する
		breakIteration = true
	}
	return
})

func (*Table) IterateRangeKeys

func (table *Table) IterateRangeKeys(lowerKey, upperKey any, callback IterateKeyCallbackFunc) (err error)

テーブルの指定範囲内に存在するキーのコピーを昇順でコールバック関数に渡していく。 lowerKey以上upperKey以下の範囲のキーを辿る。 キーの指定にはキーのカラム型に合ったGoの型で指定する必要がある。 イテレーション中はInsert/Replace/Delete/DeleteTableなどのテーブル変更操作を行うとデータが壊れる。 エラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー) コールバック関数内でのpanicはエラーとして返ることがある。(その場合、スタックトレース取得などはコールバック関数内で頑張って)。

lowerKey := int32(100)
upperKey := int32(199)
table.IterateRangeKeys(lowerKey, upperKey, func(key any) (breakIteration bool) {
	if key.(int32) % 7 == 0 {
		fmt.Println("7の倍数である最初のキーは", r.Key(), "です")
		// IterateRangeKeysを中断する
		breakIteration = true
	}
	return
})

func (*Table) Key

func (table *Table) Key() Column

キーのカラム情報を返す。

func (*Table) Name

func (table *Table) Name() string

テーブル名を返す。

func (*Table) NextCounterID

func (table *Table) NextCounterID() (CounterType, error)

キーのカラム型をCounterにしている場合に次にInsertするときに付与されるキーの値を取得できる。 キーのカラム型がCounterではない場合はErrKeyIsNotCounterのエラーが返る。

func (*Table) Replace

func (table *Table) Replace(data any) (r *Record, err error)

キーに対応するデータを置き換える。 引数のdataにはmap[string]anyもしくはunkodb.Dataもしくはunkodbタグを付けた構造体のインスタンスを渡す。 dataにはキーとカラムの全てをセットしておく必要がある。 dataのキーに対応するデータを置き換えることになる。 戻り値の*Recordには置換後のデータのコピーが入る。 対応するキーが存在しない場合はErrNotFoundKeyのエラーが返る。 引数のdataに不正がある場合は対応したエラーが返る。 それ以外のエラー(IOエラーなど)がある場合は戻り値エラーにnil以外が返る。(たいていプログラムの実行に致命的なエラー)

r, _ := table.Find(unkodb.CounterType(123))
m := r.Take()
m["value"] = m["value"].(int32) + 99
table.Replace(m)

type TableCreator

type TableCreator struct {
	// contains filtered or unexported fields
}

新しいテーブルの作成に使用される。

var tc *TableCreator
tc, _ = db.CreateTable("my_book_table")
tc.CounterKey("id")
tc.ShortStringColumn("title")
tc.ShortStringColumn("author")
tc.ShortStringColumn("genre")
table, _ := tc.Create()

func (*TableCreator) BlobColumn

func (tc *TableCreator) BlobColumn(newColumnName string) error

Blobのカラムを追加する。 値はGoの[]byteとして扱われる。 0~1073741823バイトに収まる必要がある。バイト長もデータごとに一緒に保存される。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) CounterKey

func (tc *TableCreator) CounterKey(newColumnName string) error

Counterのキーを設定する。 値はGoのuint32の型として扱われる。 データが挿入時にファイルにCounterの値が書き込まれる。データの挿入ごとに1ずつ値が増えていく(最初は1から始まる)。unkodb.CounterTypeはuint32のエイリアス。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Create

func (tc *TableCreator) Create() (table *Table, err error)

設定したキーとカラムを持つテーブルを作成する。 キーが設定されてないなどがある場合に対応したエラーが返る。 それ以外のエラー(IOエラーなど)がある場合にも戻り値エラーにはnil以外が返る。(たいていプログラムの実行に致命的なエラー)。

var tc *TableCreator
tc, _ = db.CreateTable("my_book_table")
tc.CounterKey("id")
tc.ShortStringColumn("title")
tc.ShortStringColumn("author")
tc.ShortStringColumn("genre")
table, _ := tc.Create()

func (*TableCreator) FixedSizeLongBytesColumn

func (tc *TableCreator) FixedSizeLongBytesColumn(newColumnName string, size uint16) error

FixedSizeLongBytesのカラムを追加する。 sizeは1~65535の範囲の中から指定する。 値はGoの[]byteとして扱われる。 テーブル作成時に指定した固定バイトサイズ(1~65535バイト)で保存される。サイズ未満の文字列の場合、指定バイトサイズになるよう値0が埋められる。 カラム名やサイズ指定に不正がある場合に対応したエラーが返る。

func (*TableCreator) FixedSizeLongStringColumn

func (tc *TableCreator) FixedSizeLongStringColumn(newColumnName string, size uint16) error

FixedSizeLongStringのカラムを追加する。 sizeは1~65535の範囲の中から指定する。 値はGoのstringとして扱われる。 内部的にはstringを[]byteキャストした形で保存される。テーブル作成時に指定した固定バイトサイズ(1~65535バイト)で保存される。サイズ未満の文字列の場合、指定バイトサイズになるよう半角スペースが埋められる。 カラム名やサイズ指定に不正がある場合に対応したエラーが返る。

func (*TableCreator) FixedSizeShortBytesColumn

func (tc *TableCreator) FixedSizeShortBytesColumn(newColumnName string, size uint8) error

FixedSizeShortBytesのカラムを追加する。 sizeは1~255の範囲の中から指定する。 値はGoの[]byteとして扱われる。 テーブル作成時に指定した固定バイトサイズ(1~255バイト)で保存される。サイズ未満の文字列の場合、指定バイトサイズになるよう値0が埋められる。 カラム名やサイズ指定に不正がある場合に対応したエラーが返る。

func (*TableCreator) FixedSizeShortBytesKey

func (tc *TableCreator) FixedSizeShortBytesKey(newColumnName string, size uint8) error

FixedSizeShortBytesのキーを設定する。 sizeは1~255の範囲の中から指定する。 値はGoの[]byteとして扱われる。 テーブル作成時に指定した固定バイトサイズ(1~255バイト)で保存される。サイズ未満の文字列の場合、指定バイトサイズになるよう半角スペースが埋められる。キーとして使う場合は`bytes.Compare`が順序に使用される。 カラム名やサイズ指定に不正がある場合に対応したエラーが返る。

func (*TableCreator) FixedSizeShortStringColumn

func (tc *TableCreator) FixedSizeShortStringColumn(newColumnName string, size uint8) error

FixedSizeShortStringのカラムを追加する。 sizeは1~255の範囲の中から指定する。 値はGoのstringとして扱われる。 内部的にはstringを[]byteキャストした形で保存される。テーブル作成時に指定した固定バイトサイズ(1~255バイト)で保存される。サイズ未満の文字列の場合、指定バイトサイズになるよう半角スペースが埋められる。 カラム名やサイズ指定に不正がある場合に対応したエラーが返る。

func (*TableCreator) FixedSizeShortStringKey

func (tc *TableCreator) FixedSizeShortStringKey(newColumnName string, size uint8) error

FixedSizeShortStringのキーを設定する。 sizeは1~255の範囲の中から指定する。 値はGoのstringとして扱われる。 内部的にはstringを[]byteキャストした形で保存される。テーブル作成時に指定した固定バイトサイズ(1~255バイト)で保存される。サイズ未満の文字列の場合、指定バイトサイズになるよう半角スペースが埋められる。キーとして使う場合は`strings.Compare`が順序に使用される。 カラム名やサイズ指定に不正がある場合に対応したエラーが返る。

func (*TableCreator) Float32Column

func (tc *TableCreator) Float32Column(newColumnName string) error

Float32のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Float64Column

func (tc *TableCreator) Float64Column(newColumnName string) error

Float64のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Int16Column

func (tc *TableCreator) Int16Column(newColumnName string) error

Int16のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Int16Key

func (tc *TableCreator) Int16Key(newColumnName string) error

Int16のキーを設定する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Int32Column

func (tc *TableCreator) Int32Column(newColumnName string) error

Int32のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Int32Key

func (tc *TableCreator) Int32Key(newColumnName string) error

Int32のキーを設定する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Int64Column

func (tc *TableCreator) Int64Column(newColumnName string) error

Int64のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Int64Key

func (tc *TableCreator) Int64Key(newColumnName string) error

Int64のキーを設定する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Int8Column

func (tc *TableCreator) Int8Column(newColumnName string) error

Int8のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Int8Key

func (tc *TableCreator) Int8Key(newColumnName string) error

Int8のキーを設定する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) LongBytesColumn

func (tc *TableCreator) LongBytesColumn(newColumnName string) error

LongBytesのカラムを追加する。 値はGoの[]byteとして扱われる。 0~65535バイトに収まる必要がある。バイト長もデータごとに一緒に保存される。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) LongStringColumn

func (tc *TableCreator) LongStringColumn(newColumnName string) error

LongStringのカラムを追加する。 値はGoのstringとして扱われる。 内部的にはstringを[]byteキャストした形で保存される。0~65535バイトに収まる必要がある。バイト長もデータごとに一緒に保存される。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) ShortBytesColumn

func (tc *TableCreator) ShortBytesColumn(newColumnName string) error

ShortBytesのカラムを追加する。 値はGoの[]byteとして扱われる。 0~255バイトに収まる必要がある。バイト長もデータごとに一緒に保存される。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) ShortBytesKey

func (tc *TableCreator) ShortBytesKey(newColumnName string) error

ShortBytesのキーを設定する。 値はGoの[]byteとして扱われる。 0~255バイトに収まる必要がある。バイト長もデータごとに一緒に保存される。キーとして使う場合はbytes.Compareが順序に使用される。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) ShortStringColumn

func (tc *TableCreator) ShortStringColumn(newColumnName string) error

ShortStringのカラムを追加する。 値はGoのstringとして扱われる。 内部的にはstringを[]byteキャストした形で保存される。0~255バイトに収まる必要がある。バイト長もデータごとに一緒に保存される。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) ShortStringKey

func (tc *TableCreator) ShortStringKey(newColumnName string) error

ShortStringのキーを設定する。 値はGoのstringとして扱われる。 内部的にはstringを[]byteキャストした形で保存される。0~255バイトに収まる必要がある。バイト長もデータごとに一緒に保存される。キーとして使う場合は`strings.Compare`が順序に使用される。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) TextColumn

func (tc *TableCreator) TextColumn(newColumnName string) error

Textのカラムを追加する。 値はGoのstringとして扱われる。 内部的にはstringを[]byteキャストした形で保存される。0~1073741823バイトに収まる必要がある。バイト長もデータごとに一緒に保存される。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Uint16Column

func (tc *TableCreator) Uint16Column(newColumnName string) error

Uint16のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Uint16Key

func (tc *TableCreator) Uint16Key(newColumnName string) error

Uint16のキーを設定する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Uint32Column

func (tc *TableCreator) Uint32Column(newColumnName string) error

Uint32のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Uint32Key

func (tc *TableCreator) Uint32Key(newColumnName string) error

Uint32のキーを設定する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Uint64Column

func (tc *TableCreator) Uint64Column(newColumnName string) error

Uint64のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Uint64Key

func (tc *TableCreator) Uint64Key(newColumnName string) error

Uint64のキーを設定する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Uint8Column

func (tc *TableCreator) Uint8Column(newColumnName string) error

Uint8のカラムを追加する。 カラム名に不正がある場合に対応したエラーが返る。

func (*TableCreator) Uint8Key

func (tc *TableCreator) Uint8Key(newColumnName string) error

Uint8のキーを設定する。 カラム名に不正がある場合に対応したエラーが返る。

type UnkoDB

type UnkoDB struct {
	// contains filtered or unexported fields
}
Example
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/neetsdkasu/unkodb"
)

func main() {

	// Exampleのテスト用のファイルなのでテスト実行後は削除する・・・
	const FileExists = false
	file, err := os.CreateTemp("", "example.unkodb")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(file.Name())

	var (
		db    *unkodb.UnkoDB
		table *unkodb.Table
	)

	if FileExists {
		// file, err := os.OpenFile("example.unkodb", os.O_RDWR, 0755)
		// defer file.Close()

		db, err = unkodb.Open(file)
		if err != nil {
			log.Fatal(err)
		}

		table = db.Table("food_table")
		if table == nil {
			log.Fatal("not found food_table")
		}

	} else {
		// file, err := os.Create("example.unkodb")
		// defer file.Close()

		db, err = unkodb.Create(file)
		if err != nil {
			log.Fatal(err)
		}

		tc, err := db.CreateTable("food_table")
		if err != nil {
			log.Fatal(err)
		}

		tc.CounterKey("id")
		tc.ShortStringColumn("name")
		tc.Int64Column("price")

		table, err = tc.Create()
		if err != nil {
			log.Fatal(err)
		}

		list := []map[string]any{
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "クリームパン",
				"price": int64(234),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "あんぱん",
				"price": int64(123),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "カレーパン",
				"price": int64(345),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "ジャムパン",
				"price": int64(222),
			},
			map[string]any{
				"id":    unkodb.CounterType(0),
				"name":  "食パン",
				"price": int64(333),
			},
		}

		// Insert
		for _, item := range list {
			_, err = table.Insert(item)
			if err != nil {
				log.Fatal(err)
			}
		}

		// Delete id=3 カレーパン
		err = table.Delete(unkodb.CounterType(3))
		if err != nil {
			log.Fatal(err)
		}

		// Replace id=4 ジャムパン
		replace := map[string]any{
			"id":    unkodb.CounterType(4),
			"name":  "イチゴジャムパン",
			"price": int64(987),
		}
		_, err = table.Replace(replace)
		if err != nil {
			log.Fatal(err)
		}

	}

	// Find id=2 あんぱん
	r, err := table.Find(unkodb.CounterType(2))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("[FIND] ID: %d, NAME: %s, PRICE: %d\n", r.Key(), r.Column("name"), r.Column("price"))

	// Iteration データを順番に辿る
	err = table.IterateAll(func(r *unkodb.Record) (breakIteration bool) {
		fmt.Printf("[ITER] id: %d, name: %s, price: %d\n", r.Column("id"), r.Column("name"), r.Column("price"))
		return
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

[FIND] ID: 2, NAME: あんぱん, PRICE: 123
[ITER] id: 1, name: クリームパン, price: 234
[ITER] id: 2, name: あんぱん, price: 123
[ITER] id: 4, name: イチゴジャムパン, price: 987
[ITER] id: 5, name: 食パン, price: 333
Example (WithDataStruct)
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/neetsdkasu/unkodb"
)

func main() {

	// Exampleのテスト用のファイルなのでテスト実行後は削除する・・・
	const FileExists = false
	file, err := os.CreateTemp("", "example.unkodb")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(file.Name())

	var (
		db    *unkodb.UnkoDB
		table *unkodb.Table
	)

	if FileExists {
		// file, err := os.OpenFile("example.unkodb", os.O_RDWR, 0755)
		// defer file.Close()

		db, err = unkodb.Open(file)
		if err != nil {
			log.Fatal(err)
		}

		table = db.Table("food_table")
		if table == nil {
			log.Fatal("not found food_table")
		}

	} else {
		// file, err := os.Create("example.unkodb")
		// defer file.Close()

		db, err = unkodb.Create(file)
		if err != nil {
			log.Fatal(err)
		}

		tc, err := db.CreateTable("food_table")
		if err != nil {
			log.Fatal(err)
		}

		tc.CounterKey("id")
		tc.ShortStringColumn("name")
		tc.Int64Column("price")

		table, err = tc.Create()
		if err != nil {
			log.Fatal(err)
		}

		list := []*unkodb.Data{
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"クリームパン", int64(234)},
			},
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"あんぱん", int64(123)},
			},
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"カレーパン", int64(345)},
			},
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"ジャムパン", int64(222)},
			},
			&unkodb.Data{
				Key:     unkodb.CounterType(0),
				Columns: []any{"食パン", int64(333)},
			},
		}

		// Insert
		for _, item := range list {
			_, err = table.Insert(item)
			if err != nil {
				log.Fatal(err)
			}
		}

		// Delete id=3 カレーパン
		err = table.Delete(unkodb.CounterType(3))
		if err != nil {
			log.Fatal(err)
		}

		// Replace id=4 ジャムパン
		replace := &unkodb.Data{
			Key:     unkodb.CounterType(4),
			Columns: []any{"イチゴジャムパン", int64(987)},
		}
		_, err = table.Replace(replace)
		if err != nil {
			log.Fatal(err)
		}

	}

	// Find id=2 あんぱん
	r, err := table.Find(unkodb.CounterType(2))
	if err != nil {
		log.Fatal(err)
	}
	var food unkodb.Data
	err = r.MoveTo(&food)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("[FIND] ID: %d, NAME: %s, PRICE: %d\n", food.Key, food.Columns[0], food.Columns[1])

	// Iteration データを順番に辿る
	err = table.IterateAll(func(r *unkodb.Record) (breakIteration bool) {
		f := &unkodb.Data{}
		err := r.MoveTo(f)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("[ITER] id: %d, name: %s, price: %d\n", f.Key, f.Columns[0], f.Columns[1])
		return
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

[FIND] ID: 2, NAME: あんぱん, PRICE: 123
[ITER] id: 1, name: クリームパン, price: 234
[ITER] id: 2, name: あんぱん, price: 123
[ITER] id: 4, name: イチゴジャムパン, price: 987
[ITER] id: 5, name: 食パン, price: 333
Example (WithTaggedStruct)
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/neetsdkasu/unkodb"
)

func main() {

	// Exampleのテスト用のファイルなのでテスト実行後は削除する・・・
	const FileExists = false
	file, err := os.CreateTemp("", "example.unkodb")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(file.Name())

	type Food struct {
		Id    unkodb.CounterType `unkodb:"id,key@Counter"`
		Name  string             `unkodb:"name,ShortString"`
		Price int64              `unkodb:"price,Int64"`
	}

	var (
		db    *unkodb.UnkoDB
		table *unkodb.Table
	)

	if FileExists {
		// file, err := os.OpenFile("example.unkodb", os.O_RDWR, 0755)
		// defer file.Close()

		db, err = unkodb.Open(file)
		if err != nil {
			log.Fatal(err)
		}

		table = db.Table("food_table")
		if table == nil {
			log.Fatal("not found food_table")
		}

	} else {
		// file, err := os.Create("example.unkodb")
		// defer file.Close()

		db, err = unkodb.Create(file)
		if err != nil {
			log.Fatal(err)
		}

		table, err = db.CreateTableByTaggedStruct("food_table", (*Food)(nil))
		if err != nil {
			log.Fatal(err)
		}

		list := []*Food{
			&Food{
				Name:  "クリームパン",
				Price: 234,
			},
			&Food{
				Name:  "あんぱん",
				Price: 123,
			},
			&Food{
				Name:  "カレーパン",
				Price: 345,
			},
			&Food{
				Name:  "ジャムパン",
				Price: 222,
			},
			&Food{
				Name:  "食パン",
				Price: 333,
			},
		}

		// Insert
		for _, item := range list {
			_, err = table.Insert(item)
			if err != nil {
				log.Fatal(err)
			}
		}

		// Delete id=3 カレーパン
		err = table.Delete(unkodb.CounterType(3))
		if err != nil {
			log.Fatal(err)
		}

		// Replace id=4 ジャムパン
		replace := &Food{
			Id:    4,
			Name:  "イチゴジャムパン",
			Price: 987,
		}
		_, err = table.Replace(replace)
		if err != nil {
			log.Fatal(err)
		}

	}

	// Find id=2 あんぱん
	r, err := table.Find(unkodb.CounterType(2))
	if err != nil {
		log.Fatal(err)
	}
	var food Food
	err = r.MoveTo(&food)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("[FIND] ID: %d, NAME: %s, PRICE: %d\n", food.Id, food.Name, food.Price)

	// Iteration データを順番に辿る
	err = table.IterateAll(func(r *unkodb.Record) (breakIteration bool) {
		f := &Food{}
		err := r.MoveTo(f)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("[ITER] id: %d, name: %s, price: %d\n", f.Id, f.Name, f.Price)
		return
	})
	if err != nil {
		log.Fatal(err)
	}

}
Output:

[FIND] ID: 2, NAME: あんぱん, PRICE: 123
[ITER] id: 1, name: クリームパン, price: 234
[ITER] id: 2, name: あんぱん, price: 123
[ITER] id: 4, name: イチゴジャムパン, price: 987
[ITER] id: 5, name: 食パン, price: 333

func Create

func Create(emptyFile io.ReadWriteSeeker) (db *UnkoDB, err error)

空の新しいファイルにUnkoDBを構築する。 IOエラーなどがある場合に戻り値のエラーにはnil以外が返る。(たいていプログラムの実行にとって致命的エラー)。

file, _ := os.Create("my_data.unkodb")
db, _ := unkodb.Create(file)

func Open

func Open(dbFile io.ReadWriteSeeker) (db *UnkoDB, err error)

UnkoDB構築済みのファイルからUnkoDBを開く。 IOエラーや不正なファイルのときのエラーなどがある場合に戻り値のエラーにはnil以外が返る。(たいていプログラムの実行にとって致命的エラー)。

file, _ := os.OpenFile("my_data.unkodb", os.O_RDWR, 0755)
db, _ := unkodb.Open(file)

func (*UnkoDB) CreateTable

func (db *UnkoDB) CreateTable(newTableName string) (creator *TableCreator, err error)

指定した名前の新しいテーブルを作成するためのTableCreaetorを返す。 テーブル名は他のテーブル名と重複はできない。 TableCreatorのCreateメソッドを呼び出すまではdbにテーブルは構築されない。 テーブル名に不正がある場合には対応したエラーが返る。

tc, _ := db.CreateTable("my_book_table")
tc.CounterKey("id")
tc.ShortStringColumn("title")
tc.ShortStringColumn("author")
tc.ShortStringColumn("genre")
table, _ := tc.Create()

func (*UnkoDB) CreateTableByOtherTable

func (db *UnkoDB) CreateTableByOtherTable(newTableName string, other *Table) (table *Table, err error)

キーとカラムの構造が指定のテーブルと同じ構造の新しいテーブルを作成する。 テーブル名に不正がある場合には対応したエラーが返る。 それ以外のエラー(IOエラーなど)がある場合にも戻り値エラーはnil以外が返る。(たいていプログラムの実行にとって致命的エラー)。

tc, _ := myDB.CreateTable("my_book_table")
tc.CounterKey("id")
tc.ShortStringColumn("title")
tc.ShortStringColumn("author")
tc.ShortStringColumn("genre")
myTable, _ := tc.Create()
mySecret, _ := myDB.CreateTableByOtherTable("my_secret_book_table", myTable)
yourTable, _ := yourDB.CreateTableByOtherTable("your_book_table", myTable)
yourSecret, _ := yourDB.CreateTableByOtherTable("your_secret_book_table", myTable)

func (*UnkoDB) CreateTableByTaggedStruct

func (db *UnkoDB) CreateTableByTaggedStruct(newTableName string, taggedStruct any) (table *Table, err error)

指定した名前の新しいテーブルをunkodbタグの情報を元に構築する。 テーブル名は他のテーブル名と重複はできない。 テーブル名やカラム名やキーやカラムの設定の仕方に不正がある場合には対応したエラーが返る。 それ以外のエラー(IOエラーなど)がある場合にも戻り値エラーはnil以外が返る。(たいていプログラムの実行にとって致命的エラー)。

type Book struct {
	Id     unkodb.CounterType `unkodb:"id,key@Counter"`
	Title  string             `unkodb:"title,ShortString"`
	Author string             `unkodb:"author,ShortString"`
	Genre  string             `unkodb:"genre,ShortString"`
}
table, _ := db.CreateTableByTaggedStruct("my_book_table", (*Book)(nil))

func (*UnkoDB) DeleteTable

func (db *UnkoDB) DeleteTable(name string) (err error)

指定の名前のテーブルを削除する。 テーブル名が存在しない場合はNotFoundTableのエラーが返る。 それ以外のエラー(IOエラーなど)がある場合にも戻り値エラーはnil以外が返る。(たいていプログラムの実行にとって致命的エラー)。

func (*UnkoDB) Table

func (db *UnkoDB) Table(name string) *Table

指定の名前のテーブルを取得する。 指定した名前のテーブルが存在しない場合はnilを返す。

table := db.Table("my_book_table")
if table == nil {
	// my_book_table is not existed in db
} else {
	// table is my_book_table
}

func (*UnkoDB) Tables

func (db *UnkoDB) Tables() []*Table

テーブルのリストを取得する。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL