Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/googleps04 94 map datatype #9

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions api/v1/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func parseUpdateExpresstion(actionValue string) *models.UpdateExpressionConditio
return expr
}

func performOperation(ctx context.Context, action string, actionValue string, updateAtrr models.UpdateAttr, oldRes map[string]interface{}) (map[string]interface{}, map[string]interface{}, error) {
func performOperation(ctx context.Context, action string, actionValue string, updateAtrr models.UpdateAttr, oldRes map[string]interface{}, spannerRow map[string]interface{}) (map[string]interface{}, map[string]interface{}, error) {
switch {
case action == "DELETE":
// perform delete
Expand All @@ -234,7 +234,7 @@ func performOperation(ctx context.Context, action string, actionValue string, up
case action == "SET":
// Update data in table
m, expr := parseActionValue(actionValue, updateAtrr, false)
res, err := services.Put(ctx, updateAtrr.TableName, m, expr, updateAtrr.ConditionExpression, updateAtrr.ExpressionAttributeMap, oldRes)
res, err := services.Put(ctx, updateAtrr.TableName, m, expr, updateAtrr.ConditionExpression, updateAtrr.ExpressionAttributeMap, oldRes, spannerRow)
return res, m, err
case action == "ADD":
// Add data in table
Expand All @@ -254,8 +254,9 @@ func performOperation(ctx context.Context, action string, actionValue string, up
func UpdateExpression(ctx context.Context, updateAtrr models.UpdateAttr) (interface{}, error) {
updateAtrr.ExpressionAttributeNames = ChangeColumnToSpannerExpressionName(updateAtrr.TableName, updateAtrr.ExpressionAttributeNames)
var oldRes map[string]interface{}
var spannerRow map[string]interface{}
if updateAtrr.ReturnValues != "NONE" {
oldRes, _ = services.GetWithProjection(ctx, updateAtrr.TableName, updateAtrr.PrimaryKeyMap, "", nil)
oldRes, spannerRow, _ = services.GetWithProjection(ctx, updateAtrr.TableName, updateAtrr.PrimaryKeyMap, "", nil)
}
var resp map[string]interface{}
var actVal = make(map[string]interface{})
Expand All @@ -266,7 +267,7 @@ func UpdateExpression(ctx context.Context, updateAtrr models.UpdateAttr) (interf
}
m := extractOperations(updateAtrr.UpdateExpression)
for k, v := range m {
res, acVal, err := performOperation(ctx, k, v, updateAtrr, oldRes)
res, acVal, err := performOperation(ctx, k, v, updateAtrr, oldRes, spannerRow)
resp = res
er = err
for k, v := range acVal {
Expand Down Expand Up @@ -454,7 +455,7 @@ func ChangeResponseColumn(obj map[string]interface{}) map[string]interface{} {
// ChangeColumnToSpanner converts original column name to spanner supported column names
func ChangeColumnToSpanner(obj map[string]interface{}) map[string]interface{} {
rs := make(map[string]interface{})

for k, v := range obj {

if k1, ok := models.ColumnToOriginalCol[k]; ok {
Expand Down Expand Up @@ -631,7 +632,7 @@ func ChangeQueryResponseColumn(tableName string, obj map[string]interface{}) map
return obj
}

//ChangeMaptoDynamoMap converts simple map into dynamo map
// ChangeMaptoDynamoMap converts simple map into dynamo map
func ChangeMaptoDynamoMap(in interface{}) (map[string]interface{}, error) {
if in == nil {
return nil, nil
Expand Down
12 changes: 6 additions & 6 deletions api/v1/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func RouteRequest(c *gin.Context) {
case "UpdateItem":
Update(c)
default:
c.JSON(errors.New("ValidationException", "Invalid X-Amz-Target header value of" + amzTarget).
c.JSON(errors.New("ValidationException", "Invalid X-Amz-Target header value of"+amzTarget).
shoaibcldcvr marked this conversation as resolved.
Show resolved Hide resolved
HTTPResponse("X-Amz-Target Header not supported"))
}
}
Expand Down Expand Up @@ -146,11 +146,11 @@ func put(ctx context.Context, tableName string, putObj map[string]interface{}, e
pKey := tableConf.PartitionKey
var oldResp map[string]interface{}

oldResp, err = storage.GetStorageInstance().SpannerGet(ctx, tableName, putObj[pKey], putObj[sKey], nil)
oldResp, spannerRow, err := storage.GetStorageInstance().SpannerGet(ctx, tableName, putObj[pKey], putObj[sKey], nil)
if err != nil {
return nil, err
}
res, err := services.Put(ctx, tableName, putObj, nil, conditionExp, expressionAttr, oldResp)
res, err := services.Put(ctx, tableName, putObj, nil, conditionExp, expressionAttr, oldResp, spannerRow)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -290,7 +290,7 @@ func GetItemMeta(c *gin.Context) {
return
}
getItemMeta.ExpressionAttributeNames = ChangeColumnToSpannerExpressionName(getItemMeta.TableName, getItemMeta.ExpressionAttributeNames)
res, rowErr := services.GetWithProjection(c.Request.Context(), getItemMeta.TableName, getItemMeta.PrimaryKeyMap, getItemMeta.ProjectionExpression, getItemMeta.ExpressionAttributeNames)
res, _, rowErr := services.GetWithProjection(c.Request.Context(), getItemMeta.TableName, getItemMeta.PrimaryKeyMap, getItemMeta.ProjectionExpression, getItemMeta.ExpressionAttributeNames)
if rowErr == nil {
changedColumns := ChangeResponseToOriginalColumns(getItemMeta.TableName, res)
output, err := ChangeMaptoDynamoMap(changedColumns)
Expand Down Expand Up @@ -431,7 +431,7 @@ func DeleteItem(c *gin.Context) {
deleteItem.ConditionExpression = strings.ReplaceAll(deleteItem.ConditionExpression, k, v)
}

oldRes, _ := services.GetWithProjection(c.Request.Context(), deleteItem.TableName, deleteItem.PrimaryKeyMap, "", nil)
oldRes, _, _ := services.GetWithProjection(c.Request.Context(), deleteItem.TableName, deleteItem.PrimaryKeyMap, "", nil)
err := services.Delete(c.Request.Context(), deleteItem.TableName, deleteItem.PrimaryKeyMap, deleteItem.ConditionExpression, deleteItem.ExpressionAttributeMap, nil)
if err == nil {
output, _ := ChangeMaptoDynamoMap(ChangeResponseToOriginalColumns(deleteItem.TableName, oldRes))
Expand Down Expand Up @@ -657,7 +657,7 @@ func batchUpdateItems(con context.Context, batchMetaUpdate models.BatchMetaUpdat
if err != nil {
return err
}
err = services.BatchPut(con, batchMetaUpdate.TableName, batchMetaUpdate.ArrAttrMap)
err = services.BatchPut(con, batchMetaUpdate.TableName, batchMetaUpdate.ArrAttrMap, nil)
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions config-files/staging/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"GoogleProjectID": "Your Google Project ID",
"SpannerDb": "Your Spanner Database Name",
"GoogleProjectID": "cassandra-to-spanner",
shoaibcldcvr marked this conversation as resolved.
Show resolved Hide resolved
"SpannerDb": "cluster9",
"QueryLimit": 5000
}
}
11 changes: 7 additions & 4 deletions config-files/staging/spanner.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"dynamodb_adapter_table_ddl": "instance-ID of dynamodb_adapter_table_ddl table",
"dynamodb_adapter_config_manager": "instance-ID of dynamodb_adapter_config_manager table",
"tableName": "instance-ID of Table"
}
"dynamodb_adapter_table_ddl": "spanner-instance-dev",
"dynamodb_adapter_config_manager": "spanner-instance-dev",
"test_table_for_demo": "spanner-instance-dev",
"stringset": "spanner-instance-dev",
shoaibcldcvr marked this conversation as resolved.
Show resolved Hide resolved
"mapdynamo": "spanner-instance-dev",
"test1": "spanner-instance-dev"
}
30 changes: 12 additions & 18 deletions config-files/staging/tables.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
{
"tableName":{
"partitionKey":"primary key or Partition key",
"sortKey": "sorting key of dynamoDB adapter",
"attributeTypes": {
"ColInt64": "N",
"ColString": "S",
"ColBytes": "B",
"ColBool": "BOOL",
"ColDate": "S",
"ColTimestamp": "S"
},
"indices": {
"indexName1": {
"sortKey": "sort key for indexName1",
"partitionKey": "partition key for indexName1"
}
}
"mapdynamo": {
"partitionKey": "guid",
"sortKey": "context",
"spannerIndexName": "guid",
"actualTable": "mapdynamo"
},
shoaibcldcvr marked this conversation as resolved.
Show resolved Hide resolved
"test1": {
"partitionKey": "guid",
"sortKey": "context",
"spannerIndexName": "guid",
"actualTable": "test1"
}
}
}
45 changes: 30 additions & 15 deletions service/services/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ package services

import (
"context"
"fmt"
"hash/fnv"
"regexp"
"strconv"
"strings"

Expand Down Expand Up @@ -56,7 +58,7 @@ func getSpannerProjections(projectionExpression, table string, expressionAttribu
}

// Put writes an object to Spanner
func Put(ctx context.Context, tableName string, putObj map[string]interface{}, expr *models.UpdateExpressionCondition, conditionExp string, expressionAttr, oldRes map[string]interface{}) (map[string]interface{}, error) {
func Put(ctx context.Context, tableName string, putObj map[string]interface{}, expr *models.UpdateExpressionCondition, conditionExp string, expressionAttr, oldRes map[string]interface{}, spannerRow map[string]interface{}) (map[string]interface{}, error) {
tableConf, err := config.GetTableConf(tableName)
if err != nil {
return nil, err
Expand All @@ -67,7 +69,7 @@ func Put(ctx context.Context, tableName string, putObj map[string]interface{}, e
if err != nil {
return nil, err
}
newResp, err := storage.GetStorageInstance().SpannerPut(ctx, tableName, putObj, e, expr)
newResp, err := storage.GetStorageInstance().SpannerPut(ctx, tableName, putObj, e, expr, spannerRow)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -138,7 +140,7 @@ func Del(ctx context.Context, tableName string, attrMap map[string]interface{},
}
sKey := tableConf.SortKey
pKey := tableConf.PartitionKey
res, err := storage.GetStorageInstance().SpannerGet(ctx, tableName, attrMap[pKey], attrMap[sKey], nil)
res, _, err := storage.GetStorageInstance().SpannerGet(ctx, tableName, attrMap[pKey], attrMap[sKey], nil)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -171,7 +173,7 @@ func BatchGet(ctx context.Context, tableName string, keyMapArray []map[string]in
}

// BatchPut writes bulk records to Spanner
func BatchPut(ctx context.Context, tableName string, arrAttrMap []map[string]interface{}) error {
func BatchPut(ctx context.Context, tableName string, arrAttrMap []map[string]interface{}, spannerRow []map[string]interface{}) error {
if len(arrAttrMap) <= 0 {
return errors.New("ValidationException")
}
Expand All @@ -185,7 +187,7 @@ func BatchPut(ctx context.Context, tableName string, arrAttrMap []map[string]int
return err
}
tableName = tableConf.ActualTable
err = storage.GetStorageInstance().SpannerBatchPut(ctx, tableName, arrAttrMap)
err = storage.GetStorageInstance().SpannerBatchPut(ctx, tableName, arrAttrMap, spannerRow)
if err != nil {
return err
}
Expand All @@ -205,13 +207,13 @@ func BatchPut(ctx context.Context, tableName string, arrAttrMap []map[string]int
}

// GetWithProjection get table data with projection
func GetWithProjection(ctx context.Context, tableName string, primaryKeyMap map[string]interface{}, projectionExpression string, expressionAttributeNames map[string]string) (map[string]interface{}, error) {
func GetWithProjection(ctx context.Context, tableName string, primaryKeyMap map[string]interface{}, projectionExpression string, expressionAttributeNames map[string]string) (map[string]interface{}, map[string]interface{}, error) {
if primaryKeyMap == nil {
return nil, errors.New("ValidationException")
return nil, nil, errors.New("ValidationException")
}
tableConf, err := config.GetTableConf(tableName)
if err != nil {
return nil, err
return nil, nil, err
}

tableName = tableConf.ActualTable
Expand All @@ -222,7 +224,8 @@ func GetWithProjection(ctx context.Context, tableName string, primaryKeyMap map[
if tableConf.SortKey != "" {
sValue = primaryKeyMap[tableConf.SortKey]
}
return storage.GetStorageInstance().SpannerGet(ctx, tableName, pValue, sValue, projectionCols)
res, spannerRow, err := storage.GetStorageInstance().SpannerGet(ctx, tableName, pValue, sValue, projectionCols)
return res, spannerRow, err
}

// QueryAttributes from Spanner
Expand Down Expand Up @@ -391,19 +394,16 @@ func parseSpannerTableName(query *models.Query) string {
func parseSpannerCondition(query *models.Query, pKey, sKey string) (string, map[string]interface{}) {
params := make(map[string]interface{})
whereClause := "WHERE "

if sKey != "" {
whereClause += sKey + " is not null "
}

if query.RangeExp != "" {
whereClause, query.RangeExp = createWhereClause(whereClause, query.RangeExp, "rangeExp", query.RangeValMap, params)
}

if query.FilterExp != "" {
whereClause, query.FilterExp = createWhereClause(whereClause, query.FilterExp, "filterExp", query.RangeValMap, params)
}

if whereClause == "WHERE " {
whereClause = " "
}
Expand All @@ -413,8 +413,8 @@ func parseSpannerCondition(query *models.Query, pKey, sKey string) (string, map[
func createWhereClause(whereClause string, expression string, queryVar string, RangeValueMap map[string]interface{}, params map[string]interface{}) (string, string) {
_, _, expression = utils.ParseBeginsWith(expression)
expression = strings.ReplaceAll(expression, "begins_with", "STARTS_WITH")

if whereClause != "WHERE " {
trimmedString := strings.TrimSpace(whereClause)
shoaibcldcvr marked this conversation as resolved.
Show resolved Hide resolved
if whereClause != "WHERE " && !strings.HasSuffix(trimmedString, "AND") {
whereClause += " AND "
}
count := 1
Expand All @@ -426,7 +426,22 @@ func createWhereClause(whereClause string, expression string, queryVar string, R
count++
}
}
whereClause += expression
// Handle JSON paths if the expression is structured correctly
regexPattern := `^[a-zA-Z_][a-zA-Z0-9_.]*(\.[a-zA-Z_][a-zA-Z0-9_.]*)+\s*=\s*@\w+$`
re := regexp.MustCompile(regexPattern)
shoaibcldcvr marked this conversation as resolved.
Show resolved Hide resolved
if re.MatchString(expression) {
expression := strings.TrimSpace(expression)
expressionParts := strings.Split(expression, "=")
expressionParts[0] = strings.TrimSpace(expressionParts[0])
jsonFields := strings.Split(expressionParts[0], ".")

// Construct new JSON_VALUE expression
newExpression := fmt.Sprintf("JSON_VALUE(%s, '$.%s') = %s", jsonFields[0], strings.Join(jsonFields[1:], "."), expressionParts[1])
whereClause = whereClause + " " + newExpression
expression = newExpression
} else if expression != "" {
whereClause = whereClause + expression
}
return whereClause, expression
}

Expand Down
Loading