public void StringConversions(string stringFormat, SpannerDbType spannerType, bool shouldEqual = true) { Assert.True(SpannerDbType.TryParse(stringFormat, out SpannerDbType result)); if (shouldEqual) { Assert.Equal(spannerType, result); } else { Assert.NotEqual(spannerType, result); } //roundtrip test. Assert.True(SpannerDbType.TryParse(result.ToString(), out SpannerDbType result2)); Assert.Equal(result, result2); }
/// <inheritdoc /> protected override RelationalTypeMapping CreateMappingFromStoreType(string storeType) { if (SpannerDbType.TryParse(storeType, out SpannerDbType parsedType)) { if (!parsedType.Size.HasValue && s_dbTypeMappings.TryGetValue(parsedType, out RelationalTypeMapping mapping)) { return(mapping); } if (parsedType.DbType == DbType.String) { // return a sized string. return(new StringTypeMapping(storeType, parsedType.DbType, true, parsedType.Size)); } return(new SpannerComplexTypeMapping(parsedType)); } return(null); }
public static void ExecuteScript(string databaseName, string scriptPath) { if (File.Exists(@"..\..\" + scriptPath)) { //executing in VS - so path is relative to bin\<config> dir scriptPath = @"..\..\" + scriptPath; } else { scriptPath = Path.Combine(BaseDirectory, scriptPath); } var script = File.ReadAllText(scriptPath); using (var connection = new SpannerConnection(CreateConnectionString(databaseName))) { Execute(connection, command => { var statements = Regex.Split(script, @";[\r?\n]\s+", RegexOptions.Multiline); foreach (var statement in statements) { s_gStatements++; if (string.IsNullOrWhiteSpace(statement) || statement.StartsWith("SET ", StringComparison.Ordinal)) { continue; } var tokens = statement.Split(' ', '(', ')', ',', ';').Where( x => !string.IsNullOrEmpty(x?.Trim())).ToList(); if (tokens.Count == 0) { continue; } if (tokens[0] == "CREATE") { if (tokens[1] == "TABLE") { var tableName = tokens[2]; var columnData = new List <Tuple <string, SpannerDbType> >(); var i = 3; while (tokens[i] != "PRIMARY") { SpannerDbType type; if (!SpannerDbType.TryParse(tokens[i + 1], out type)) { throw new InvalidOperationException($"Unable to parse {tokens[i + 1]}"); } columnData.Add(new Tuple <string, SpannerDbType>(tokens[i], type)); i += 2; if (tokens[i] == "MAX" || tokens[i][0] >= '0' && tokens[i][0] <= '9') { i++; } if (tokens[i] == "NOT") { i += 2; } } s_columnMap[tableName] = columnData; } command.CommandText = statement; } else if (tokens[0] == "INSERT") { // if (s_gStatements >= s_skipToLine) // { // Console.WriteLine("break here"); // } // we do some simple parsing of a DML insert to a write command. if (tokens.Count < 5 || tokens[0] != "INSERT" || tokens[1] != "INTO") { continue; } var m = Regex.Match(statement, @"INSERT INTO ([^\r\n\t\f\v(]+)\s?(\(.*\))?.*VALUES.(\(.*\))", RegexOptions.Singleline); var targetTable = m.Groups[1].Value.Trim(); var columnGroup = m.Groups[2].Value; var valueGroup = m.Groups[3].Value; //get columns to set. IEnumerable <Tuple <string, SpannerDbType> > targetColumns; if (string.IsNullOrEmpty(columnGroup)) { //use the lookup table. targetColumns = s_columnMap[targetTable]; } else { var trimmedCols = columnGroup.Remove(columnGroup.Length - 1, 1).Remove(0, 1); targetColumns = trimmedCols.Split(',') .Select(x => s_columnMap[targetTable].First(y => y.Item1 == x.Trim())); } //value parsing is a bit complicated and we do a simpler (hackish) heuristic which //isnt completely valid for all cases, but works for our inputs. valueGroup = valueGroup.Remove(valueGroup.Length - 1, 1).Remove(0, 1); var valueTokens = valueGroup.Split(',').ToList(); var values = new List <string>(); StringBuilder sb = null; for (var i = 0; i < valueTokens.Count; i++) { var valueToken = valueTokens[i].Replace("''", "'"); if (sb != null) { sb.Append(','); sb.Append(valueToken); if (sb[sb.Length - 1] == '\'') { values.Add(sb.ToString().Substring(0, sb.Length - 1)); sb = null; } continue; } valueToken = valueToken.TrimStart(); if (valueToken.StartsWith("TO_DATE")) { var dateQuoteInd = valueToken.IndexOf('\''); var endDateQuote = valueToken.IndexOf('\'', dateQuoteInd + 1); values.Add(valueToken.Substring(dateQuoteInd + 1, endDateQuote - dateQuoteInd - 1)); i++; } else if (valueToken.StartsWith("'") || valueToken.StartsWith("N'")) { valueToken = valueToken.StartsWith("'") ? valueToken.Substring(1, valueToken.Length - 1) : valueToken.Substring(2, valueToken.Length - 2); if (valueToken.EndsWith("'")) { values.Add(valueToken.Substring(0, valueToken.Length - 1)); } else { sb = new StringBuilder(valueToken); } } else { values.Add(string.Equals(valueToken, "NULL", StringComparison.InvariantCultureIgnoreCase) ? null : valueToken); } } command.CommandText = $"INSERT {targetTable}"; command.Parameters.Clear(); command.Parameters.AddRange(targetColumns.Select(x => new SpannerParameter(x.Item1, x.Item2)).ToArray()); if (values.Count != command.Parameters.Count) { throw new InvalidOperationException("error parsing input northwind.sql"); } for (var j = 0; j < command.Parameters.Count; j++) { if (Equals(((SpannerParameter)command.Parameters[j]).SpannerDbType, SpannerDbType.Bool) && (values[j].Contains("0") || values[j].Contains("1"))) { command.Parameters[j].Value = Convert.ToInt32(values[j]); } else { command.Parameters[j].Value = values[j]; } } } if (s_gStatements < SkipToLine) { continue; } command.ExecuteNonQuery(); } return(0); }, ""); } }
[InlineData("STRUCT<:INT64>")] // No name (but a colon) public void TryParse_Invalid(string text) { Assert.False(SpannerDbType.TryParse(text, out var result)); Assert.Null(result); }