blob: 295fe4d32a9f6087836e856435a3ffdd5187078c [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Buffers;
using System.Collections.Generic;
using Arrow.Flight.Protocol.Sql;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
namespace Apache.Arrow.Flight.Sql
{
/// <summary>
/// Helper methods for doing common Flight Sql tasks and conversions
/// </summary>
public class FlightSqlUtils
{
public static readonly FlightActionType FlightSqlCreatePreparedStatement = new("CreatePreparedStatement",
"Creates a reusable prepared statement resource on the server. \n" +
"Request Message: ActionCreatePreparedStatementRequest\n" +
"Response Message: ActionCreatePreparedStatementResult");
public static readonly FlightActionType FlightSqlClosePreparedStatement = new("ClosePreparedStatement",
"Closes a reusable prepared statement resource on the server. \n" +
"Request Message: ActionClosePreparedStatementRequest\n" +
"Response Message: N/A");
/// <summary>
/// List of possible actions
/// </summary>
public static readonly List<FlightActionType> FlightSqlActions = new()
{
FlightSqlCreatePreparedStatement,
FlightSqlClosePreparedStatement
};
/// <summary>
/// Helper to parse {@link com.google.protobuf.Any} objects to the specific protobuf object.
/// </summary>
/// <param name="source">the raw bytes source value.</param>
/// <returns>the materialized protobuf object.</returns>
public static Any Parse(ByteString source)
{
return Any.Parser.ParseFrom(source);
}
/// <summary>
/// Helper to unpack {@link com.google.protobuf.Any} objects to the specific protobuf object.
/// </summary>
/// <param name="source">the parsed Source value.</param>
/// <typeparam name="T">IMessage</typeparam>
/// <returns>the materialized protobuf object.</returns>
public static T Unpack<T>(Any source) where T : IMessage, new()
{
return source.Unpack<T>();
}
/// <summary>
/// Helper to parse and unpack {@link com.google.protobuf.Any} objects to the specific protobuf object.
/// </summary>
/// <param name="source">the raw bytes source value.</param>
/// <typeparam name="T">IMessage</typeparam>
/// <returns>the materialized protobuf object.</returns>
public static T ParseAndUnpack<T>(ByteString source) where T : IMessage, new()
{
return Unpack<T>(Parse(source));
}
}
/// <summary>
/// A set of helper functions for converting encoded commands to IMessage types
/// </summary>
public static class FlightSqlExtensions
{
private static Any ParsedCommand(this FlightDescriptor descriptor)
{
return FlightSqlUtils.Parse(descriptor.Command);
}
private static IMessage UnpackMessage(this Any command)
{
if (command.Is(CommandStatementQuery.Descriptor))
return FlightSqlUtils.Unpack<CommandStatementQuery>(command);
if (command.Is(CommandPreparedStatementQuery.Descriptor))
return FlightSqlUtils.Unpack<CommandPreparedStatementQuery>(command);
if (command.Is(CommandGetCatalogs.Descriptor))
return FlightSqlUtils.Unpack<CommandGetCatalogs>(command);
if (command.Is(CommandGetDbSchemas.Descriptor))
return FlightSqlUtils.Unpack<CommandGetDbSchemas>(command);
if (command.Is(CommandGetTables.Descriptor))
return FlightSqlUtils.Unpack<CommandGetTables>(command);
if (command.Is(CommandGetTableTypes.Descriptor))
return FlightSqlUtils.Unpack<CommandGetTableTypes>(command);
if (command.Is(CommandGetSqlInfo.Descriptor))
return FlightSqlUtils.Unpack<CommandGetSqlInfo>(command);
if (command.Is(CommandGetPrimaryKeys.Descriptor))
return FlightSqlUtils.Unpack<CommandGetPrimaryKeys>(command);
if (command.Is(CommandGetExportedKeys.Descriptor))
return FlightSqlUtils.Unpack<CommandGetExportedKeys>(command);
if (command.Is(CommandGetImportedKeys.Descriptor))
return FlightSqlUtils.Unpack<CommandGetImportedKeys>(command);
if (command.Is(CommandGetCrossReference.Descriptor))
return FlightSqlUtils.Unpack<CommandGetCrossReference>(command);
if (command.Is(CommandGetXdbcTypeInfo.Descriptor))
return FlightSqlUtils.Unpack<CommandGetXdbcTypeInfo>(command);
if (command.Is(TicketStatementQuery.Descriptor))
return FlightSqlUtils.Unpack<TicketStatementQuery>(command);
if (command.Is(TicketStatementQuery.Descriptor))
return FlightSqlUtils.Unpack<TicketStatementQuery>(command);
if (command.Is(CommandStatementUpdate.Descriptor))
return FlightSqlUtils.Unpack<CommandStatementUpdate>(command);
if (command.Is(CommandPreparedStatementUpdate.Descriptor))
return FlightSqlUtils.Unpack<CommandPreparedStatementUpdate>(command);
if (command.Is(CommandPreparedStatementQuery.Descriptor))
return FlightSqlUtils.Unpack<CommandPreparedStatementQuery>(command);
throw new ArgumentException("The defined request is invalid.");
}
/// <summary>
/// Extracts a command from a FlightDescriptor
/// </summary>
/// <param name="descriptor"></param>
/// <returns>An IMessage that has been parsed and unpacked</returns>
public static IMessage? ParsedAndUnpackedMessage(this FlightDescriptor descriptor)
{
try
{
return descriptor.ParsedCommand().UnpackMessage();
}
catch (ArgumentException)
{
return null;
}
}
public static ByteString Serialize(this IBufferMessage message)
{
int size = message.CalculateSize();
var writer = new ArrayBufferWriter<byte>(size);
message.WriteTo(writer);
var schemaBytes = writer.WrittenSpan;
return ByteString.CopyFrom(schemaBytes);
}
}
}