Skip to content
Browse files

first commit

  • Loading branch information...
0 parents commit b54071be897125f50c5db15b1ef11366e0a83bf5 @yyyc514 committed
Showing with 269 additions and 0 deletions.
  1. +4 −0 .gitignore
  2. +22 −0 LICENSE
  3. +18 −0 Makefile
  4. +4 −0 README.txt
  5. +175 −0 dm.go
  6. BIN states.db
  7. +46 −0 states.go
4 .gitignore
@@ -0,0 +1,4 @@
+_obj
+*.6
+6.out
+states
22 LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2009 Josh Goebel
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
18 Makefile
@@ -0,0 +1,18 @@
+# Copyright 2009 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.
+
+include $(GOROOT)/src/Make.$(GOARCH)
+
+TARG=dm
+GOFILES=\
+ dm.go\
+
+include $(GOROOT)/src/Make.pkg
+
+states: dm.a
+ $(GC) states.go
+ $(LD) -o $@ states.$O
+
+dm.a: dm.go
+ $(GC) dm.go
4 README.txt
@@ -0,0 +1,4 @@
+This is still very raw and I'm still learning Go.
+
+The idea is to provide some sort of ActiveRecord like wrapper on top of the
+sqlite3 C API (mapped to go via cgo).
175 dm.go
@@ -0,0 +1,175 @@
+package dm
+
+import (
+ "sqlite3";
+ "fmt";
+ "strings";
+ "reflect";
+ "container/vector";
+ "os";
+ )
+
+type Connection sqlite3.Handle;
+
+type Model struct {
+ table_name string;
+ connection Connection;
+}
+
+type ResultSet struct {
+ Results *vector.Vector;
+}
+
+type Opts map[string] interface{};
+
+// func main()
+// {
+//
+// }
+
+const (
+ SQLITE_INTEGER = 1;
+ SQLITE_TEXT = 3;
+ SQLITE_ROW = 100;
+ )
+
+var conn *sqlite3.Handle;
+var model_map map[string] reflect.Type;
+
+func Init(dbname string) {
+ conn = new(sqlite3.Handle);
+ model_map = make(map[string] reflect.Type);
+ r := conn.Open(dbname);
+ if r!="" {
+ println("ERROR");
+ }
+
+}
+
+func RegisterModel(model string, t reflect.Type) {
+ model_map[model]=t;
+}
+
+func Find(model string, id int) interface{}
+{
+ sql := select_one_sql(model, id);
+ return single_result(sql, model);
+}
+
+func FindLast(model string) interface{} {
+ sql := select_all_sql(model) + " order by id desc limit 1";
+ return single_result(sql, model);
+}
+
+func FindFirst(model string) interface{} {
+ sql := select_all_sql(model) + " limit 1";
+ return single_result(sql, model);
+}
+
+func Count(model string) int {
+ sql := select_count_sql(model);
+ res, err := Execute(sql);
+ if err!=0 {
+ defer res.Finalize();
+ }
+ return res.ColumnInt(0);
+}
+
+func single_result(sql string, model string) interface{} {
+ res, err := Execute(sql);
+ if err!=0 {
+ defer res.Finalize();
+ }
+ o := reflect.MakeZero(model_map[model]);
+ build_result(o, res);
+ return o.Interface();
+}
+
+func parse_options(opts ...) (options Opts) {
+ v := reflect.NewValue(opts).(*reflect.StructValue);
+ if v.NumField() > 0 {
+ options = v.Field(0).Interface().(Opts);
+ } else {
+ options = Opts{};
+ }
+ return;
+}
+
+func FindAll(model string, opts ...) (r ResultSet) {
+ options := parse_options(opts);
+ r = ResultSet{};
+ sql := "";
+ limit, ok := options["limit"];
+ if ok && limit.(int) > 0 {
+ sql = select_all_sql(model) + fmt.Sprintf (" limit %d", options["limit"].(int))
+ }
+ else
+ {
+ sql = select_all_sql(model);
+ }
+ res, err := Execute(sql);
+ if err!=0 {
+ defer res.Finalize();
+ }
+ r.Results = build_results(model, res);
+ return;
+}
+
+func camel_case(s string) string {
+ return strings.ToUpper(s[0:1]) + s[1:len(s)]
+}
+
+func build_results(model string, st *sqlite3.Statement) (r *vector.Vector)
+{
+ r = vector.New(0);
+ for i := SQLITE_ROW; i == SQLITE_ROW; i= st.Step() {
+ o := reflect.MakeZero(model_map[model]);
+ x := build_result(o, st);
+ r.Push(x.Interface());
+ }
+ return;
+}
+
+func build_result(o reflect.Value, st *sqlite3.Statement ) reflect.Value
+{
+ cc := st.ColumnCount();
+ for i:=0; i<cc; i++ {
+ cn := camel_case(st.ColumnName(i));
+ ct := st.ColumnType(i);
+ f := o.(*reflect.StructValue).FieldByName(cn);
+ switch ct {
+ case SQLITE_INTEGER: f.(*reflect.IntValue).Set(st.ColumnInt(i));
+ case SQLITE_TEXT: f.(*reflect.StringValue).Set(st.ColumnText(i));
+ }
+ }
+ return o;
+}
+
+func Execute(sql string) (s *sqlite3.Statement, err int)
+{
+ errs := "";
+ // println(sql);
+ s, errs = conn.Prepare(sql);
+ if errs!="" {
+ println("SQL ERROR: " + conn.ErrMsg());
+ die();
+ }
+ err = s.Step();
+ return s, err;
+}
+
+func die() {
+ os.Exit(1);
+}
+
+func select_one_sql(model string, id int) string {
+ return fmt.Sprintf("select * from " + model + "s where id = %d", id);
+}
+
+func select_all_sql(model string) string {
+ return fmt.Sprintf("select * from " + model + "s");
+}
+
+func select_count_sql(model string) string {
+ return fmt.Sprintf("select count(id) from " + model + "s");
+}
BIN states.db
Binary file not shown.
46 states.go
@@ -0,0 +1,46 @@
+package main
+
+import (
+ "./dm";
+ "reflect";
+ "fmt";
+ )
+
+type State struct {
+ Id int;
+ Name string;
+ Abbv string;
+ *dm.Model;
+}
+
+func main()
+{
+ dm.Init("states.db");
+ dm.RegisterModel("State", reflect.Typeof(State{}));
+ state := dm.Find("State", 12).(State);
+ fmt.Printf("FIND BY ID: %s\n", state.Name);
+
+ state = dm.FindFirst("State").(State);
+ fmt.Printf("FIRST: %s\n", state.Name);
+
+ state = dm.FindLast("State").(State);
+ fmt.Printf("LAST: %s\n", state.Name);
+
+ count := dm.Count("State");
+ fmt.Printf("COUNT: %d\n", count);
+
+ println("First 5 states");
+ states := dm.FindAll("State", dm.Opts {"limit": 5});
+ for s := range states.Results.Iter() {
+ state = s.(State);
+ fmt.Printf("id: %d name: %s abbv: %s\n", state.Id, state.Name, state.Abbv);
+ }
+ println();
+
+ println("States");
+ states = dm.FindAll("State");
+ for s := range states.Results.Iter() {
+ state = s.(State);
+ fmt.Printf("id: %d name: %s abbv: %s\n", state.Id, state.Name, state.Abbv);
+ }
+}

0 comments on commit b54071b

Please sign in to comment.
Something went wrong with that request. Please try again.