github.com/jbking/gohan@v0.0.0-20151217002006-b41ccf1c2a96/extension/otto/gohan_db.go (about)

     1  // Copyright (C) 2015 NTT Innovation Institute, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package otto
    17  
    18  import (
    19  	"github.com/dop251/otto"
    20  
    21  	"github.com/cloudwan/gohan/db/sql"
    22  	"github.com/cloudwan/gohan/db/transaction"
    23  	"github.com/cloudwan/gohan/schema"
    24  )
    25  
    26  func init() {
    27  	gohanDBInit := func(env *Environment) {
    28  		vm := env.VM
    29  		builtins := map[string]interface{}{
    30  			"gohan_db_list": func(call otto.FunctionCall) otto.Value {
    31  				VerifyCallArguments(&call, "gohan_db_list", 3)
    32  				rawTransaction, _ := call.Argument(0).Export()
    33  				transaction, ok := rawTransaction.(transaction.Transaction)
    34  				var err error
    35  				if !ok {
    36  					dataStore := env.DataStore
    37  					transaction, err = dataStore.Begin()
    38  					if err != nil {
    39  						ThrowOttoException(&call, noTransactionErrorMessage)
    40  					}
    41  					defer transaction.Close()
    42  				}
    43  				schemaID := call.Argument(1).String()
    44  				filterObj, _ := call.Argument(2).Export()
    45  				var filter map[string]interface{}
    46  				if filterObj != nil {
    47  					filter = filterObj.(map[string]interface{})
    48  				}
    49  				manager := schema.GetManager()
    50  				schema, ok := manager.Schema(schemaID)
    51  				if !ok {
    52  					ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID)
    53  				}
    54  				resources, _, err := transaction.List(schema, filter, nil)
    55  				if err != nil {
    56  					ThrowOttoException(&call, "Error during gohan_db_list: %s", err.Error())
    57  				}
    58  				resp := []map[string]interface{}{}
    59  				for _, resource := range resources {
    60  					resp = append(resp, resource.Data())
    61  				}
    62  				value, _ := vm.ToValue(resp)
    63  				return value
    64  			},
    65  			"gohan_db_fetch": func(call otto.FunctionCall) otto.Value {
    66  				VerifyCallArguments(&call, "gohan_db_fetch", 4)
    67  				rawTransaction, _ := call.Argument(0).Export()
    68  				transaction, ok := rawTransaction.(transaction.Transaction)
    69  				var err error
    70  				if !ok {
    71  					dataStore := env.DataStore
    72  					transaction, err = dataStore.Begin()
    73  					if err != nil {
    74  						ThrowOttoException(&call, noTransactionErrorMessage)
    75  					}
    76  					defer transaction.Close()
    77  				}
    78  				schemaID := call.Argument(1).String()
    79  				ID := call.Argument(2).String()
    80  				tenantID := call.Argument(3).String()
    81  				manager := schema.GetManager()
    82  				schema, ok := manager.Schema(schemaID)
    83  				if !ok {
    84  					ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID)
    85  				}
    86  				var tenantFilter []string
    87  				if tenantID != "" {
    88  					tenantFilter = []string{tenantID}
    89  				}
    90  				resp, err := transaction.Fetch(schema, ID, tenantFilter)
    91  				if err != nil {
    92  					ThrowOttoException(&call, "Error during gohan_db_fetch: %s", err.Error())
    93  				}
    94  				if resp == nil {
    95  					otto.NullValue()
    96  				}
    97  				value, _ := vm.ToValue(resp.Data())
    98  				return value
    99  			},
   100  			"gohan_db_state_fetch": func(call otto.FunctionCall) otto.Value {
   101  				VerifyCallArguments(&call, "gohan_db_state_fetch", 4)
   102  				rawTransaction, _ := call.Argument(0).Export()
   103  				transaction, ok := rawTransaction.(transaction.Transaction)
   104  				if !ok {
   105  					ThrowOttoException(&call, noTransactionErrorMessage)
   106  				}
   107  				schemaID := call.Argument(1).String()
   108  				ID := call.Argument(2).String()
   109  				tenantID := call.Argument(3).String()
   110  				manager := schema.GetManager()
   111  				schema, ok := manager.Schema(schemaID)
   112  				if !ok {
   113  					ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID)
   114  				}
   115  				var tenantFilter []string
   116  				if tenantID != "" {
   117  					tenantFilter = []string{tenantID}
   118  				}
   119  				resp, err := transaction.StateFetch(schema, ID, tenantFilter)
   120  				if err != nil {
   121  					ThrowOttoException(&call, "Error during gohan_db_state_fetch: %s", err.Error())
   122  				}
   123  				data := map[string]interface{}{
   124  					"config_version": resp.ConfigVersion,
   125  					"state_version":  resp.StateVersion,
   126  					"error":          resp.Error,
   127  					"state":          resp.State,
   128  					"monitoring":     resp.Monitoring,
   129  				}
   130  				value, _ := vm.ToValue(data)
   131  				return value
   132  			},
   133  			"gohan_db_create": func(call otto.FunctionCall) otto.Value {
   134  				VerifyCallArguments(&call, "gohan_db_create", 3)
   135  				rawTransaction, _ := call.Argument(0).Export()
   136  				transaction, ok := rawTransaction.(transaction.Transaction)
   137  				needCommit := false
   138  				var err error
   139  				if !ok {
   140  					dataStore := env.DataStore
   141  					transaction, err = dataStore.Begin()
   142  					needCommit = true
   143  					if err != nil {
   144  						ThrowOttoException(&call, noTransactionErrorMessage)
   145  					}
   146  					defer transaction.Close()
   147  				}
   148  				schemaID := call.Argument(1).String()
   149  				data := ConvertOttoToGo(call.Argument(2))
   150  				dataMap, _ := data.(map[string]interface{})
   151  				manager := schema.GetManager()
   152  				resource, err := manager.LoadResource(schemaID, dataMap)
   153  				if err != nil {
   154  					ThrowOttoException(&call, "Error during gohan_db_create: %s", err.Error())
   155  				}
   156  				if err = transaction.Create(resource); err != nil {
   157  					ThrowOttoException(&call, "Error during gohan_db_create: %s", err.Error())
   158  				}
   159  				if needCommit {
   160  					err = transaction.Commit()
   161  					if err != nil {
   162  						ThrowOttoException(&call, "Error during gohan_db_create: %s", err.Error())
   163  					}
   164  				}
   165  				value, _ := vm.ToValue(resource.Data())
   166  				return value
   167  			},
   168  			"gohan_db_update": func(call otto.FunctionCall) otto.Value {
   169  				VerifyCallArguments(&call, "gohan_db_update", 3)
   170  				rawTransaction, _ := call.Argument(0).Export()
   171  				transaction, ok := rawTransaction.(transaction.Transaction)
   172  				needCommit := false
   173  				var err error
   174  				if !ok {
   175  					dataStore := env.DataStore
   176  					transaction, err = dataStore.Begin()
   177  					needCommit = true
   178  					if err != nil {
   179  						ThrowOttoException(&call, noTransactionErrorMessage)
   180  					}
   181  					defer transaction.Close()
   182  				}
   183  				schemaID := call.Argument(1).String()
   184  				data := ConvertOttoToGo(call.Argument(2))
   185  				dataMap, _ := data.(map[string]interface{})
   186  				manager := schema.GetManager()
   187  				resource, err := manager.LoadResource(schemaID, dataMap)
   188  				if err != nil {
   189  					ThrowOttoException(&call, "Error during gohan_db_update: %s", err.Error())
   190  				}
   191  				if err = transaction.Update(resource); err != nil {
   192  					ThrowOttoException(&call, "Error during gohan_db_update: %s", err.Error())
   193  				}
   194  				if needCommit {
   195  					err = transaction.Commit()
   196  					if err != nil {
   197  						ThrowOttoException(&call, "Error during gohan_db_create: %s", err.Error())
   198  					}
   199  				}
   200  				value, _ := vm.ToValue(resource.Data())
   201  				return value
   202  			},
   203  			"gohan_db_state_update": func(call otto.FunctionCall) otto.Value {
   204  				VerifyCallArguments(&call, "gohan_db_state_update", 3)
   205  				rawTransaction, _ := call.Argument(0).Export()
   206  				transaction, ok := rawTransaction.(transaction.Transaction)
   207  				needCommit := false
   208  				var err error
   209  				if !ok {
   210  					dataStore := env.DataStore
   211  					transaction, err = dataStore.Begin()
   212  					needCommit = true
   213  					if err != nil {
   214  						ThrowOttoException(&call, noTransactionErrorMessage)
   215  					}
   216  					defer transaction.Close()
   217  				}
   218  				schemaID := call.Argument(1).String()
   219  				data := ConvertOttoToGo(call.Argument(2))
   220  				dataMap, _ := data.(map[string]interface{})
   221  				manager := schema.GetManager()
   222  				resource, err := manager.LoadResource(schemaID, dataMap)
   223  				if err != nil {
   224  					ThrowOttoException(&call, "Error during gohan_db_state_update: %s", err.Error())
   225  				}
   226  				if err = transaction.StateUpdate(resource, nil); err != nil {
   227  					ThrowOttoException(&call, "Error during gohan_db_state_update: %s", err.Error())
   228  				}
   229  				if needCommit {
   230  					err = transaction.Commit()
   231  					if err != nil {
   232  						ThrowOttoException(&call, "Error during gohan_db_create: %s", err.Error())
   233  					}
   234  				}
   235  				value, _ := vm.ToValue(resource.Data())
   236  				return value
   237  			},
   238  			"gohan_db_delete": func(call otto.FunctionCall) otto.Value {
   239  				VerifyCallArguments(&call, "gohan_db_delete", 3)
   240  				rawTransaction, _ := call.Argument(0).Export()
   241  				transaction, ok := rawTransaction.(transaction.Transaction)
   242  				needCommit := false
   243  				var err error
   244  				if !ok {
   245  					dataStore := env.DataStore
   246  					transaction, err = dataStore.Begin()
   247  					needCommit = true
   248  					if err != nil {
   249  						ThrowOttoException(&call, noTransactionErrorMessage)
   250  					}
   251  					defer transaction.Close()
   252  				}
   253  				schemaID := call.Argument(1).String()
   254  				ID := call.Argument(2).String()
   255  				manager := schema.GetManager()
   256  				schema, _ := manager.Schema(schemaID)
   257  				if err := transaction.Delete(schema, ID); err != nil {
   258  					ThrowOttoException(&call, "Error during gohan_db_delete: %s", err.Error())
   259  				}
   260  				if needCommit {
   261  					err = transaction.Commit()
   262  					if err != nil {
   263  						ThrowOttoException(&call, "Error during gohan_db_create: %s", err.Error())
   264  					}
   265  				}
   266  				return otto.NullValue()
   267  			},
   268  			"gohan_db_query": func(call otto.FunctionCall) otto.Value {
   269  				VerifyCallArguments(&call, "gohan_db_query", 4)
   270  				rawTransaction, _ := call.Argument(0).Export()
   271  				transaction, ok := rawTransaction.(transaction.Transaction)
   272  				needCommit := false
   273  				var err error
   274  				if !ok {
   275  					dataStore := env.DataStore
   276  					transaction, err = dataStore.Begin()
   277  					needCommit = true
   278  					if err != nil {
   279  						ThrowOttoException(&call, noTransactionErrorMessage)
   280  					}
   281  					defer transaction.Close()
   282  				}
   283  				schemaID := call.Argument(1).String()
   284  				sqlString := call.Argument(2).String()
   285  				rawArguments, _ := call.Argument(3).Export()
   286  
   287  				manager := schema.GetManager()
   288  				s, ok := manager.Schema(schemaID)
   289  				if !ok {
   290  					ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID)
   291  				}
   292  
   293  				arguments, ok := rawArguments.([]interface{})
   294  				if !ok {
   295  					ThrowOttoException(&call, "Gievn arguments is not []interface{}")
   296  				}
   297  
   298  				resources, err := transaction.Query(s, sqlString, arguments)
   299  				if err != nil {
   300  					ThrowOttoException(&call, "Error during gohan_db_query: %s", err.Error())
   301  				}
   302  				if needCommit {
   303  					err = transaction.Commit()
   304  					if err != nil {
   305  						ThrowOttoException(&call, "Error during gohan_db_create: %s", err.Error())
   306  					}
   307  				}
   308  				resp := []map[string]interface{}{}
   309  				for _, resource := range resources {
   310  					resp = append(resp, resource.Data())
   311  				}
   312  				value, _ := vm.ToValue(resp)
   313  				return value
   314  			},
   315  			"gohan_db_sql_make_columns": func(call otto.FunctionCall) otto.Value {
   316  				VerifyCallArguments(&call, "gohan_db_query", 1)
   317  				schemaID := call.Argument(0).String()
   318  				manager := schema.GetManager()
   319  				s, ok := manager.Schema(schemaID)
   320  				if !ok {
   321  					ThrowOttoException(&call, unknownSchemaErrorMesssageFormat, schemaID)
   322  				}
   323  				results := sql.MakeColumns(s, false)
   324  				value, _ := vm.ToValue(results)
   325  				return value
   326  			},
   327  		}
   328  
   329  		for name, object := range builtins {
   330  			vm.Set(name, object)
   331  		}
   332  	}
   333  	RegisterInit(gohanDBInit)
   334  }