embulk-input-dynamodb 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/master.yml +34 -0
- data/.github/workflows/test.yml +30 -0
- data/.scalafmt.conf +5 -0
- data/CHANGELOG.md +49 -0
- data/README.md +204 -54
- data/build.gradle +53 -44
- data/example/config-deprecated.yml +20 -0
- data/example/config-query-as-json.yml +18 -0
- data/example/config-query.yml +22 -0
- data/example/config-scan.yml +18 -0
- data/example/prepare_dynamodb_table.sh +67 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +1 -2
- data/gradlew +67 -48
- data/gradlew.bat +20 -10
- data/{test/run_dynamodb_local.sh → run_dynamodb_local.sh} +2 -1
- data/settings.gradle +1 -0
- data/src/main/scala/org/embulk/input/dynamodb/DeprecatedDynamodbInputPlugin.scala +73 -0
- data/src/main/scala/org/embulk/input/dynamodb/DynamodbInputPlugin.scala +76 -25
- data/src/main/scala/org/embulk/input/dynamodb/PluginTask.scala +132 -32
- data/src/main/scala/org/embulk/input/dynamodb/aws/Aws.scala +44 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/AwsClientConfiguration.scala +37 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/AwsCredentials.scala +240 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/AwsDynamodbConfiguration.scala +35 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/AwsEndpointConfiguration.scala +79 -0
- data/src/main/scala/org/embulk/input/dynamodb/aws/HttpProxy.scala +61 -0
- data/src/main/scala/org/embulk/input/dynamodb/deprecated/AttributeValueHelper.scala +72 -0
- data/src/main/scala/org/embulk/input/dynamodb/{Filter.scala → deprecated/Filter.scala} +3 -3
- data/src/main/scala/org/embulk/input/dynamodb/{FilterConfig.scala → deprecated/FilterConfig.scala} +13 -13
- data/src/main/scala/org/embulk/input/dynamodb/{ope → deprecated/ope}/AbstractOperation.scala +36 -18
- data/src/main/scala/org/embulk/input/dynamodb/{ope → deprecated/ope}/QueryOperation.scala +21 -13
- data/src/main/scala/org/embulk/input/dynamodb/{ope → deprecated/ope}/ScanOperation.scala +20 -13
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbAttributeValue.scala +154 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbAttributeValueEmbulkTypeTransformable.scala +245 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbAttributeValueType.scala +33 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemColumnVisitor.scala +50 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemConsumer.scala +40 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemIterator.scala +19 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemReader.scala +64 -0
- data/src/main/scala/org/embulk/input/dynamodb/item/DynamodbItemSchema.scala +135 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/AbstractDynamodbOperation.scala +169 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/DynamodbOperationProxy.scala +59 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/DynamodbQueryOperation.scala +72 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/DynamodbScanOperation.scala +93 -0
- data/src/main/scala/org/embulk/input/dynamodb/operation/EmbulkDynamodbOperation.scala +15 -0
- data/src/main/scala/org/embulk/input/dynamodb/package.scala +4 -9
- data/src/test/scala/org/embulk/input/dynamodb/AttributeValueHelperTest.scala +245 -101
- data/src/test/scala/org/embulk/input/dynamodb/AwsCredentialsTest.scala +150 -97
- data/src/test/scala/org/embulk/input/dynamodb/DynamodbQueryOperationTest.scala +188 -0
- data/src/test/scala/org/embulk/input/dynamodb/DynamodbScanOperationTest.scala +181 -0
- data/src/test/scala/org/embulk/input/dynamodb/testutil/EmbulkTestBase.scala +85 -0
- metadata +73 -49
- data/circle.yml +0 -16
- data/config/checkstyle/checkstyle.xml +0 -128
- data/config/checkstyle/default.xml +0 -108
- data/src/main/scala/org/embulk/input/dynamodb/AttributeValueHelper.scala +0 -41
- data/src/main/scala/org/embulk/input/dynamodb/AwsCredentials.scala +0 -63
- data/src/main/scala/org/embulk/input/dynamodb/DynamoDBClient.scala +0 -23
- data/src/test/resources/yaml/authMethodBasic.yml +0 -21
- data/src/test/resources/yaml/authMethodBasic_Error.yml +0 -19
- data/src/test/resources/yaml/authMethodEnv.yml +0 -19
- data/src/test/resources/yaml/authMethodProfile.yml +0 -20
- data/src/test/resources/yaml/dynamodb-local-query.yml +0 -25
- data/src/test/resources/yaml/dynamodb-local-scan.yml +0 -23
- data/src/test/resources/yaml/notSetAuthMethod.yml +0 -20
- data/src/test/scala/org/embulk/input/dynamodb/ope/QueryOperationTest.scala +0 -83
- data/src/test/scala/org/embulk/input/dynamodb/ope/ScanOperationTest.scala +0 -83
- data/test/create_table.sh +0 -16
- data/test/put_items.sh +0 -25
@@ -1,28 +1,35 @@
|
|
1
|
-
package org.embulk.input.dynamodb.ope
|
1
|
+
package org.embulk.input.dynamodb.deprecated.ope
|
2
2
|
|
3
3
|
import java.util.{List => JList, Map => JMap}
|
4
4
|
|
5
|
-
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient
|
6
|
-
import com.amazonaws.services.dynamodbv2.model.{
|
5
|
+
import com.amazonaws.services.dynamodbv2.{AmazonDynamoDB, AmazonDynamoDBClient}
|
6
|
+
import com.amazonaws.services.dynamodbv2.model.{
|
7
|
+
AttributeValue,
|
8
|
+
Condition,
|
9
|
+
ScanRequest,
|
10
|
+
ScanResult
|
11
|
+
}
|
7
12
|
import org.embulk.input.dynamodb.PluginTask
|
8
13
|
import org.embulk.spi.{BufferAllocator, PageBuilder, PageOutput, Schema}
|
9
14
|
|
10
|
-
import scala.
|
15
|
+
import scala.jdk.CollectionConverters._
|
16
|
+
|
17
|
+
class ScanOperation(client: AmazonDynamoDB) extends AbstractOperation {
|
11
18
|
|
12
|
-
class ScanOperation(client: AmazonDynamoDBClient) extends AbstractOperation {
|
13
19
|
override def execute(
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
{
|
20
|
+
task: PluginTask,
|
21
|
+
schema: Schema,
|
22
|
+
output: PageOutput
|
23
|
+
): Unit = {
|
18
24
|
val allocator: BufferAllocator = task.getBufferAllocator
|
19
25
|
val pageBuilder: PageBuilder = new PageBuilder(allocator, schema, output)
|
20
26
|
|
21
|
-
val attributes: JList[String] =
|
27
|
+
val attributes: JList[String] =
|
28
|
+
schema.getColumns.asScala.map(_.getName).asJava
|
22
29
|
val scanFilter: JMap[String, Condition] = createFilters(task).asJava
|
23
30
|
var evaluateKey: JMap[String, AttributeValue] = null
|
24
31
|
|
25
|
-
val scanLimit: Long
|
32
|
+
val scanLimit: Long = task.getScanLimit
|
26
33
|
val recordLimit: Long = task.getRecordLimit
|
27
34
|
var recordCount: Long = 0
|
28
35
|
|
@@ -42,9 +49,9 @@ class ScanOperation(client: AmazonDynamoDBClient) extends AbstractOperation {
|
|
42
49
|
val result: ScanResult = client.scan(request)
|
43
50
|
evaluateKey = result.getLastEvaluatedKey
|
44
51
|
|
45
|
-
val items = result.getItems.asScala.map(_.asScala.toMap)
|
52
|
+
val items = result.getItems.asScala.map(_.asScala.toMap).toSeq
|
46
53
|
recordCount += write(pageBuilder, schema, items)
|
47
|
-
} while(evaluateKey != null && (recordLimit == 0 || recordLimit > recordCount))
|
54
|
+
} while (evaluateKey != null && (recordLimit == 0 || recordLimit > recordCount))
|
48
55
|
|
49
56
|
pageBuilder.finish()
|
50
57
|
}
|
@@ -0,0 +1,154 @@
|
|
1
|
+
package org.embulk.input.dynamodb.item
|
2
|
+
|
3
|
+
import java.nio.ByteBuffer
|
4
|
+
import java.nio.charset.StandardCharsets
|
5
|
+
import java.util.{Optional, List => JList, Map => JMap}
|
6
|
+
|
7
|
+
import com.amazonaws.services.dynamodbv2.model.AttributeValue
|
8
|
+
import org.embulk.config.{Config, ConfigDefault, Task => EmbulkTask}
|
9
|
+
|
10
|
+
import scala.jdk.CollectionConverters._
|
11
|
+
import scala.util.chaining._
|
12
|
+
|
13
|
+
/**
|
14
|
+
* TODO: I want to bind directly `org.embulk.config.Config`` to `com.amazonaws.services.dynamodbv2.model.AttributeValue`.
|
15
|
+
* Should I implement `com.amazonaws.transform.JsonUnmarshallerContext`?
|
16
|
+
**/
|
17
|
+
object DynamodbAttributeValue {
|
18
|
+
|
19
|
+
trait Task extends EmbulkTask {
|
20
|
+
|
21
|
+
@Config("S")
|
22
|
+
@ConfigDefault("null")
|
23
|
+
def getS: Optional[String]
|
24
|
+
|
25
|
+
@Config("N")
|
26
|
+
@ConfigDefault("null")
|
27
|
+
def getN: Optional[String]
|
28
|
+
|
29
|
+
@Config("B")
|
30
|
+
@ConfigDefault("null")
|
31
|
+
def getB: Optional[String]
|
32
|
+
|
33
|
+
@Config("SS")
|
34
|
+
@ConfigDefault("null")
|
35
|
+
def getSS: Optional[JList[String]]
|
36
|
+
|
37
|
+
@Config("NS")
|
38
|
+
@ConfigDefault("null")
|
39
|
+
def getNS: Optional[JList[String]]
|
40
|
+
|
41
|
+
@Config("BS")
|
42
|
+
@ConfigDefault("null")
|
43
|
+
def getBS: Optional[JList[String]]
|
44
|
+
|
45
|
+
@Config("M")
|
46
|
+
@ConfigDefault("null")
|
47
|
+
def getM: Optional[JMap[String, DynamodbAttributeValue.Task]]
|
48
|
+
|
49
|
+
@Config("L")
|
50
|
+
@ConfigDefault("null")
|
51
|
+
def getL: Optional[JList[DynamodbAttributeValue.Task]]
|
52
|
+
|
53
|
+
@Config("NULL")
|
54
|
+
@ConfigDefault("null")
|
55
|
+
def getNULL: Optional[Boolean]
|
56
|
+
|
57
|
+
@Config("BOOL")
|
58
|
+
@ConfigDefault("null")
|
59
|
+
def getBOOL: Optional[Boolean]
|
60
|
+
}
|
61
|
+
|
62
|
+
def apply(task: Task): DynamodbAttributeValue = {
|
63
|
+
val original = new AttributeValue()
|
64
|
+
.tap(a => task.getS.ifPresent(v => a.setS(v)))
|
65
|
+
.tap(a => task.getN.ifPresent(v => a.setN(v)))
|
66
|
+
.tap { a =>
|
67
|
+
task.getB.ifPresent { v =>
|
68
|
+
a.setB(ByteBuffer.wrap(v.getBytes(StandardCharsets.UTF_8)))
|
69
|
+
}
|
70
|
+
}
|
71
|
+
.tap(a => task.getSS.ifPresent(v => a.setSS(v)))
|
72
|
+
.tap(a => task.getNS.ifPresent(v => a.setNS(v)))
|
73
|
+
.tap { a =>
|
74
|
+
task.getBS.ifPresent { v =>
|
75
|
+
a.setBS(
|
76
|
+
v.asScala
|
77
|
+
.map(e => ByteBuffer.wrap(e.getBytes(StandardCharsets.UTF_8)))
|
78
|
+
.asJava
|
79
|
+
)
|
80
|
+
}
|
81
|
+
}
|
82
|
+
.tap { a =>
|
83
|
+
task.getM.ifPresent { v =>
|
84
|
+
a.setM(v.asScala.map(x => (x._1, apply(x._2).getOriginal)).asJava)
|
85
|
+
}
|
86
|
+
}
|
87
|
+
.tap(a =>
|
88
|
+
task.getL.ifPresent(v =>
|
89
|
+
a.setL(v.asScala.map(apply).map(_.getOriginal).asJava)
|
90
|
+
)
|
91
|
+
)
|
92
|
+
.tap(a => task.getNULL.ifPresent(v => a.setNULL(v)))
|
93
|
+
.tap(a => task.getBOOL.ifPresent(v => a.setBOOL(v)))
|
94
|
+
new DynamodbAttributeValue(original)
|
95
|
+
}
|
96
|
+
|
97
|
+
def apply(original: AttributeValue): DynamodbAttributeValue = {
|
98
|
+
new DynamodbAttributeValue(original)
|
99
|
+
}
|
100
|
+
|
101
|
+
def apply(item: Map[String, AttributeValue]): DynamodbAttributeValue = {
|
102
|
+
val original = new AttributeValue().withM(item.asJava)
|
103
|
+
new DynamodbAttributeValue(original)
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
class DynamodbAttributeValue(original: AttributeValue) {
|
108
|
+
|
109
|
+
require(
|
110
|
+
message =
|
111
|
+
s"Invalid AttributeValue: ${original} which must have 1 attribute value.",
|
112
|
+
requirement = {
|
113
|
+
Seq(hasS, hasN, hasB, hasSS, hasNS, hasBS, hasM, hasL, hasNULL, hasBOOL)
|
114
|
+
.count(has => has) == 1
|
115
|
+
}
|
116
|
+
)
|
117
|
+
|
118
|
+
def getOriginal: AttributeValue = original
|
119
|
+
def isNull: Boolean = Option[Boolean](getOriginal.getNULL).getOrElse(false)
|
120
|
+
def hasS: Boolean = Option(getOriginal.getS).isDefined
|
121
|
+
def hasN: Boolean = Option(getOriginal.getN).isDefined
|
122
|
+
def hasB: Boolean = Option(getOriginal.getB).isDefined
|
123
|
+
def hasSS: Boolean = Option(getOriginal.getSS).isDefined
|
124
|
+
def hasNS: Boolean = Option(getOriginal.getNS).isDefined
|
125
|
+
def hasBS: Boolean = Option(getOriginal.getBS).isDefined
|
126
|
+
def hasM: Boolean = Option(getOriginal.getM).isDefined
|
127
|
+
def hasL: Boolean = Option(getOriginal.getL).isDefined
|
128
|
+
def hasNULL: Boolean = Option(getOriginal.getNULL).isDefined
|
129
|
+
def hasBOOL: Boolean = Option(getOriginal.getBOOL).isDefined
|
130
|
+
def getS: String = getOriginal.getS
|
131
|
+
def getN: String = getOriginal.getN
|
132
|
+
def getB: ByteBuffer = getOriginal.getB
|
133
|
+
def getSS: JList[String] = getOriginal.getSS
|
134
|
+
def getNS: JList[String] = getOriginal.getNS
|
135
|
+
def getBS: JList[ByteBuffer] = getOriginal.getBS
|
136
|
+
def getM: JMap[String, AttributeValue] = getOriginal.getM
|
137
|
+
def getL: JList[AttributeValue] = getOriginal.getL
|
138
|
+
def getNULL: Boolean = getOriginal.getNULL
|
139
|
+
def getBOOL: Boolean = getOriginal.getBOOL
|
140
|
+
|
141
|
+
def getType: DynamodbAttributeValueType = {
|
142
|
+
if (hasS) return DynamodbAttributeValueType.S
|
143
|
+
if (hasN) return DynamodbAttributeValueType.N
|
144
|
+
if (hasB) return DynamodbAttributeValueType.B
|
145
|
+
if (hasSS) return DynamodbAttributeValueType.SS
|
146
|
+
if (hasNS) return DynamodbAttributeValueType.NS
|
147
|
+
if (hasBS) return DynamodbAttributeValueType.BS
|
148
|
+
if (hasM) return DynamodbAttributeValueType.M
|
149
|
+
if (hasL) return DynamodbAttributeValueType.L
|
150
|
+
if (hasNULL) return DynamodbAttributeValueType.NULL
|
151
|
+
if (hasBOOL) return DynamodbAttributeValueType.BOOL
|
152
|
+
DynamodbAttributeValueType.UNKNOWN
|
153
|
+
}
|
154
|
+
}
|
@@ -0,0 +1,245 @@
|
|
1
|
+
package org.embulk.input.dynamodb.item
|
2
|
+
|
3
|
+
import java.nio.ByteBuffer
|
4
|
+
import java.nio.charset.StandardCharsets
|
5
|
+
|
6
|
+
import org.embulk.input.dynamodb.logger
|
7
|
+
import org.embulk.spi.time.{Timestamp, TimestampParser}
|
8
|
+
import org.msgpack.value.{Value, ValueFactory}
|
9
|
+
|
10
|
+
import scala.jdk.CollectionConverters._
|
11
|
+
import scala.util.chaining._
|
12
|
+
|
13
|
+
object DynamodbAttributeValueEmbulkTypeTransformable {
|
14
|
+
|
15
|
+
val TRUTHY_STRINGS: Set[String] = Set(
|
16
|
+
"true",
|
17
|
+
"True",
|
18
|
+
"TRUE",
|
19
|
+
"yes",
|
20
|
+
"Yes",
|
21
|
+
"YES",
|
22
|
+
"t",
|
23
|
+
"T",
|
24
|
+
"y",
|
25
|
+
"Y",
|
26
|
+
"on",
|
27
|
+
"On",
|
28
|
+
"ON",
|
29
|
+
"1"
|
30
|
+
)
|
31
|
+
|
32
|
+
val FALSY_STRINGS: Set[String] = Set(
|
33
|
+
"false",
|
34
|
+
"False",
|
35
|
+
"FALSE",
|
36
|
+
"no",
|
37
|
+
"No",
|
38
|
+
"NO",
|
39
|
+
"f",
|
40
|
+
"F",
|
41
|
+
"n",
|
42
|
+
"N",
|
43
|
+
"off",
|
44
|
+
"Off",
|
45
|
+
"OFF",
|
46
|
+
"0"
|
47
|
+
)
|
48
|
+
}
|
49
|
+
|
50
|
+
case class DynamodbAttributeValueEmbulkTypeTransformable(
|
51
|
+
attributeValue: DynamodbAttributeValue,
|
52
|
+
typeEnforcer: Option[DynamodbAttributeValueType] = None,
|
53
|
+
timestampParser: Option[TimestampParser] = None
|
54
|
+
) {
|
55
|
+
|
56
|
+
private def fromAttributeValueType: DynamodbAttributeValueType =
|
57
|
+
typeEnforcer.getOrElse(attributeValue.getType)
|
58
|
+
|
59
|
+
private def convertNAsLongOrDouble(n: String): Either[Long, Double] = {
|
60
|
+
n.toLongOption match {
|
61
|
+
case Some(l) => Left(l)
|
62
|
+
case None => Right(n.toDouble)
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
private def convertBAsString(b: ByteBuffer): String = {
|
67
|
+
new String(b.array(), StandardCharsets.UTF_8)
|
68
|
+
}
|
69
|
+
|
70
|
+
private def hasAttributeValueType: Boolean = {
|
71
|
+
fromAttributeValueType.equals(attributeValue.getType)
|
72
|
+
}
|
73
|
+
|
74
|
+
def asMessagePack: Option[Value] = {
|
75
|
+
if (!hasAttributeValueType) return None
|
76
|
+
if (attributeValue.isNull) return None
|
77
|
+
|
78
|
+
Option(fromAttributeValueType match {
|
79
|
+
case DynamodbAttributeValueType.S =>
|
80
|
+
ValueFactory.newString(attributeValue.getS)
|
81
|
+
case DynamodbAttributeValueType.N =>
|
82
|
+
convertNAsLongOrDouble(attributeValue.getN) match {
|
83
|
+
case Left(v) => ValueFactory.newInteger(v)
|
84
|
+
case Right(v) => ValueFactory.newFloat(v)
|
85
|
+
}
|
86
|
+
case DynamodbAttributeValueType.B =>
|
87
|
+
ValueFactory.newBinary(attributeValue.getB.array())
|
88
|
+
case DynamodbAttributeValueType.SS =>
|
89
|
+
ValueFactory.newArray(
|
90
|
+
attributeValue.getSS.asScala.map(ValueFactory.newString).asJava
|
91
|
+
)
|
92
|
+
case DynamodbAttributeValueType.NS =>
|
93
|
+
ValueFactory.newArray(
|
94
|
+
attributeValue.getNS.asScala
|
95
|
+
.map(convertNAsLongOrDouble(_) match {
|
96
|
+
case Left(v) => ValueFactory.newInteger(v)
|
97
|
+
case Right(v) => ValueFactory.newFloat(v)
|
98
|
+
})
|
99
|
+
.asJava
|
100
|
+
)
|
101
|
+
case DynamodbAttributeValueType.BS =>
|
102
|
+
ValueFactory.newArray(
|
103
|
+
attributeValue.getBS.asScala
|
104
|
+
.map(b => ValueFactory.newBinary(b.array()))
|
105
|
+
.asJava
|
106
|
+
)
|
107
|
+
case DynamodbAttributeValueType.M =>
|
108
|
+
ValueFactory
|
109
|
+
.newMapBuilder()
|
110
|
+
.tap { builder =>
|
111
|
+
attributeValue.getM.asScala.foreach { x =>
|
112
|
+
builder.put(
|
113
|
+
ValueFactory.newString(x._1),
|
114
|
+
DynamodbAttributeValueEmbulkTypeTransformable(
|
115
|
+
DynamodbAttributeValue(x._2)
|
116
|
+
).asMessagePack.getOrElse(ValueFactory.newNil())
|
117
|
+
)
|
118
|
+
}
|
119
|
+
}
|
120
|
+
.build()
|
121
|
+
case DynamodbAttributeValueType.L =>
|
122
|
+
ValueFactory.newArray(
|
123
|
+
attributeValue.getL.asScala.map { av =>
|
124
|
+
DynamodbAttributeValueEmbulkTypeTransformable(
|
125
|
+
DynamodbAttributeValue(av)
|
126
|
+
).asMessagePack.getOrElse(ValueFactory.newNil())
|
127
|
+
}.asJava
|
128
|
+
)
|
129
|
+
case DynamodbAttributeValueType.BOOL =>
|
130
|
+
ValueFactory.newBoolean(attributeValue.getBOOL)
|
131
|
+
case _ =>
|
132
|
+
logger.warn(
|
133
|
+
s"Unsupported AttributeValue: ${attributeValue.getOriginal.toString}"
|
134
|
+
)
|
135
|
+
return None
|
136
|
+
})
|
137
|
+
}
|
138
|
+
|
139
|
+
def asBoolean: Option[Boolean] = {
|
140
|
+
if (!hasAttributeValueType) return None
|
141
|
+
if (attributeValue.isNull) return None
|
142
|
+
|
143
|
+
Option(fromAttributeValueType match {
|
144
|
+
case DynamodbAttributeValueType.S =>
|
145
|
+
if (DynamodbAttributeValueEmbulkTypeTransformable.TRUTHY_STRINGS
|
146
|
+
.contains(attributeValue.getS)) true
|
147
|
+
else if (DynamodbAttributeValueEmbulkTypeTransformable.FALSY_STRINGS
|
148
|
+
.contains(attributeValue.getS)) false
|
149
|
+
else return None
|
150
|
+
case DynamodbAttributeValueType.N =>
|
151
|
+
convertNAsLongOrDouble(attributeValue.getN) match {
|
152
|
+
case Left(v) => v > 0
|
153
|
+
case Right(v) => v > 0.0
|
154
|
+
}
|
155
|
+
case DynamodbAttributeValueType.B =>
|
156
|
+
val s = convertBAsString(attributeValue.getB)
|
157
|
+
if (DynamodbAttributeValueEmbulkTypeTransformable.TRUTHY_STRINGS
|
158
|
+
.contains(s))
|
159
|
+
true
|
160
|
+
else if (DynamodbAttributeValueEmbulkTypeTransformable.FALSY_STRINGS
|
161
|
+
.contains(s)) false
|
162
|
+
else return None
|
163
|
+
case DynamodbAttributeValueType.BOOL => attributeValue.getBOOL
|
164
|
+
case unsupported =>
|
165
|
+
logger.debug(s"cannot convert ${unsupported.toString} as boolean.")
|
166
|
+
return None
|
167
|
+
})
|
168
|
+
}
|
169
|
+
|
170
|
+
def asLong: Option[Long] = {
|
171
|
+
if (!hasAttributeValueType) return None
|
172
|
+
if (attributeValue.isNull) return None
|
173
|
+
|
174
|
+
Option(fromAttributeValueType match {
|
175
|
+
case DynamodbAttributeValueType.S =>
|
176
|
+
convertNAsLongOrDouble(attributeValue.getS) match {
|
177
|
+
case Left(v) => v
|
178
|
+
case Right(v) => v.toLong
|
179
|
+
}
|
180
|
+
case DynamodbAttributeValueType.N =>
|
181
|
+
convertNAsLongOrDouble(attributeValue.getN) match {
|
182
|
+
case Left(v) => v
|
183
|
+
case Right(v) => v.toLong
|
184
|
+
}
|
185
|
+
case DynamodbAttributeValueType.B =>
|
186
|
+
convertNAsLongOrDouble(convertBAsString(attributeValue.getB)) match {
|
187
|
+
case Left(v) => v
|
188
|
+
case Right(v) => v.toLong
|
189
|
+
}
|
190
|
+
case DynamodbAttributeValueType.BOOL =>
|
191
|
+
if (attributeValue.getBOOL) 1L
|
192
|
+
else 0L
|
193
|
+
case unsupported =>
|
194
|
+
logger.debug(s"cannot convert ${unsupported.toString} as long.")
|
195
|
+
return None
|
196
|
+
})
|
197
|
+
}
|
198
|
+
|
199
|
+
def asDouble: Option[Double] = {
|
200
|
+
if (!hasAttributeValueType) return None
|
201
|
+
if (attributeValue.isNull) return None
|
202
|
+
|
203
|
+
fromAttributeValueType match {
|
204
|
+
case DynamodbAttributeValueType.S => attributeValue.getS.toDoubleOption
|
205
|
+
case DynamodbAttributeValueType.N => attributeValue.getN.toDoubleOption
|
206
|
+
case DynamodbAttributeValueType.B =>
|
207
|
+
convertBAsString(attributeValue.getB).toDoubleOption
|
208
|
+
case DynamodbAttributeValueType.BOOL =>
|
209
|
+
Option(
|
210
|
+
if (attributeValue.getBOOL) 1.0d
|
211
|
+
else 0.0d
|
212
|
+
)
|
213
|
+
case unsupported =>
|
214
|
+
logger.debug(s"cannot convert ${unsupported.toString} as double.")
|
215
|
+
None
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
def asString: Option[String] = {
|
220
|
+
if (!hasAttributeValueType) return None
|
221
|
+
if (attributeValue.isNull) return None
|
222
|
+
|
223
|
+
Option(fromAttributeValueType match {
|
224
|
+
case DynamodbAttributeValueType.S => attributeValue.getS
|
225
|
+
case DynamodbAttributeValueType.N => attributeValue.getN
|
226
|
+
case DynamodbAttributeValueType.B => convertBAsString(attributeValue.getB)
|
227
|
+
case DynamodbAttributeValueType.SS => asMessagePack.map(_.toJson).get
|
228
|
+
case DynamodbAttributeValueType.NS => asMessagePack.map(_.toJson).get
|
229
|
+
case DynamodbAttributeValueType.BS => asMessagePack.map(_.toJson).get
|
230
|
+
case DynamodbAttributeValueType.M => asMessagePack.map(_.toJson).get
|
231
|
+
case DynamodbAttributeValueType.L => asMessagePack.map(_.toJson).get
|
232
|
+
case DynamodbAttributeValueType.BOOL => attributeValue.getBOOL.toString
|
233
|
+
case _ =>
|
234
|
+
logger.warn(
|
235
|
+
s"Unsupported AttributeValue: ${attributeValue.getOriginal.toString}"
|
236
|
+
)
|
237
|
+
return None
|
238
|
+
})
|
239
|
+
}
|
240
|
+
|
241
|
+
def asTimestamp: Option[Timestamp] = {
|
242
|
+
timestampParser.flatMap(p => asString.map(p.parse))
|
243
|
+
}
|
244
|
+
|
245
|
+
}
|