CSharp/SearchAzureTableCommand.cs
namespace AzureStorageCmdlets
{ using System; using System.Collections.Generic; using System.Text; using System.Management.Automation; using System.Net; using System.IO; using System.Linq; using System.Xml.Linq; using System.Security; using System.Collections.ObjectModel; using System.Collections.Specialized; [Cmdlet(VerbsCommon.Search, "AzureTable", DefaultParameterSetName="WholeTable")] public class SearchAzureTableCommand : AzureTableCmdletBase { [Parameter(Mandatory = true, Position=0, ValueFromPipelineByPropertyName=true )] [Alias(new string[] { "Name", "Table" })] public string TableName { get; set; } [Parameter(Mandatory = true,ParameterSetName="FilterString")] public string Filter { get; set; } [Parameter(Mandatory = true,ValueFromPipelineByPropertyName=true,ParameterSetName="ContinueSearch")] public string NextRowKey { get; set; } [Parameter(Mandatory = true,ValueFromPipelineByPropertyName=true,ParameterSetName="ContinueSearch")] public string NextPartition { get; set; } [Parameter(ParameterSetName="ContinueSearch")] public uint Next { get; set; } [Parameter(Mandatory = true, Position=1, ParameterSetName = "WhereBlock")] public ScriptBlock[] Where { get; set; } [Parameter(ParameterSetName = "WhereBlock")] public SwitchParameter Or { get; set; } [Parameter()] public string[] Select { get; set; } public string[] Sort { get; set; } [Parameter(ValueFromPipelineByPropertyName=true)] public uint BatchSize { get; set; } [Parameter(ValueFromPipelineByPropertyName=true)] public uint First { get; set; } public uint Skip { get; set; } [Parameter()] public SwitchParameter ExcludeTableInfo { get; set; } protected override void ProcessRecord() { base.ProcessRecord(); if (String.IsNullOrEmpty(StorageAccount) || String.IsNullOrEmpty(StorageKey)) { return; } #region WhereBlockTranslation this.WriteVerbose(this.ParameterSetName); if (this.ParameterSetName == "WhereBlock") { StringCollection filterList = new StringCollection(); foreach (ScriptBlock whereBlock in Where) { this.WriteVerbose(String.Format("Processing Where Clause {0}", whereBlock.ToString())); string whereString = whereBlock.ToString(); if (whereString.Length > 512) { WriteError( new ErrorRecord(new Exception("Will not tokenize filters longer than 512 characters"), "SearchAzureTable.WhereBlockTooLong", ErrorCategory.InvalidArgument, whereBlock)); continue; } Collection<PSParseError> error = new Collection<PSParseError>(); ; Collection<PSToken> tokens = PSParser.Tokenize(whereString, out error); this.WriteVerbose(String.Format("Tokens Count {0}", tokens.Count.ToString())); bool ok = true; string adoFilter = String.Empty; IEnumerator<PSToken> enumerator = tokens.GetEnumerator(); enumerator.MoveNext(); while (enumerator.Current != null) { this.WriteVerbose(String.Format("Processing {0}", enumerator.Current.ToString())); if (enumerator.Current.Type != PSTokenType.Variable || enumerator.Current.Content != "_") { WriteError( new ErrorRecord(new Exception("The first item in the filter script must $_"), "SearchAzureTable.FilterScriptMustStartWithDollarUnderbar", ErrorCategory.InvalidArgument, enumerator.Current)); ok = false; break; } if (!enumerator.MoveNext()) { ok = false; break; } if (enumerator.Current.Type != PSTokenType.Operator && enumerator.Current.Content != ".") { WriteError( new ErrorRecord(new Exception("$_ must be followed by the . operator"), "SearchAzureTable.FilterScriptDollarUnderBarMustBeFollowedByDot", ErrorCategory.InvalidArgument, enumerator.Current)); ok = false; break; } if (!enumerator.MoveNext()) { ok = false; break; } if (enumerator.Current.Type != PSTokenType.Member) { WriteError( new ErrorRecord(new Exception("The . operator must be followed by a property name"), "SearchAzureTable.FilterScriptDotMustBeFollowedByPropertyName", ErrorCategory.InvalidArgument, enumerator.Current)); ok = false; break; } adoFilter += enumerator.Current.Content; if (!enumerator.MoveNext()) { ok = false; break; } if (enumerator.Current.Type != PSTokenType.Operator) { WriteError( new ErrorRecord(new Exception("The filter item must be followed by an operator"), "SearchAzureTable.FilterScriptItemMustBeFollowedByOperator", ErrorCategory.InvalidArgument, enumerator.Current)); ok = false; break; } string[] validOperators = new string[] { "-gt", "-lt", "-ge", "-le", "-ne", "-eq" }; bool isValidOperator = false; foreach (string validOp in validOperators) { if (enumerator.Current.Content == validOp) { isValidOperator = true; break; } } if (!isValidOperator) { WriteError( new ErrorRecord(new Exception(enumerator.Current.Content + @" is not a valid operator. Please use ""-gt"", ""-lt"", ""-ge"", ""-le"", ""-ne"", ""-eq"""), "SearchAzureTable.FilterScriptUsesInvalidOperator", ErrorCategory.InvalidArgument, enumerator.Current)); ok = false; break; } adoFilter += enumerator.Current.Content.Replace("-", " "); if (!enumerator.MoveNext()) { ok = false; break; } this.WriteVerbose(String.Format("Comparing Tokens {0}", enumerator.Current.Type.ToString())); if (! (enumerator.Current.Type == PSTokenType.Number || enumerator.Current.Type == PSTokenType.String)) { WriteError( new ErrorRecord(new Exception("The operator must be followed by a string or a number"), "SearchAzureTable.FilterScriptOperatorMustBeFollowedByStringOrNumber", ErrorCategory.InvalidArgument, enumerator.Current)); ok = false; break; } if (enumerator.Current.Type == PSTokenType.String && enumerator.Current.Content.Contains("$(")) { WriteError( new ErrorRecord(new Exception("Variables expansion not allowed in filter script"), "SearchAzureTable.FilterScriptCannotContainVariables", ErrorCategory.InvalidArgument, enumerator.Current)); ok = false; break; } adoFilter += " '" + this.SessionState.InvokeCommand.ExpandString(enumerator.Current.Content) + "'"; enumerator.MoveNext(); } if (ok) { filterList.Add(adoFilter); } else { return; } } if (filterList.Count >= 1) { if (filterList.Count > 1) { StringBuilder filterBuilder = new StringBuilder(); foreach (string f in filterList) { filterBuilder.Append("("); filterBuilder.Append(f); filterBuilder.Append(")"); if (Or) { filterBuilder.Append("or"); } else { filterBuilder.Append("and"); } } } else { Filter = filterList[0]; } } } #endregion string selectString = String.Empty; if (this.MyInvocation.BoundParameters.ContainsKey("Select")) { for (int i =0 ;i < Select.Length; i++) { selectString+=Select[i]; if (i != (Select.Length - 1)) { selectString += ","; } } } string sortString = String.Empty; if (this.MyInvocation.BoundParameters.ContainsKey("Sort")) { for (int i = 0; i < Sort.Length; i++) { sortString += Sort[i]; if (i != (Sort.Length - 1)) { sortString += ","; } } } if (! this.MyInvocation.BoundParameters.ContainsKey("BatchSize")) { BatchSize =640; } bool thereIsMore =false; nextRow = String.Empty; if (this.MyInvocation.BoundParameters.ContainsKey("NextRowKey")) { nextRow = NextRowKey; } nextPart = String.Empty; if (this.MyInvocation.BoundParameters.ContainsKey("NextPartition")) { nextPart = NextPartition; } int collectedSoFar = 0; if (this.MyInvocation.BoundParameters.ContainsKey("Next")) { First = Next; } if (this.MyInvocation.BoundParameters.ContainsKey("First") && First < BatchSize) { BatchSize = First; } do { if (this.MyInvocation.BoundParameters.ContainsKey("First") || this.MyInvocation.BoundParameters.ContainsKey("Next")) { if (collectedSoFar >= First) { break; } } string result = QueryEntities( this.TableName, null, null, this.Filter, sortString, selectString, BatchSize); if (!String.IsNullOrEmpty(result)) { if (this.MyInvocation.BoundParameters.ContainsKey("First") || this.MyInvocation.BoundParameters.ContainsKey("Next")) { foreach (PSObject resultObj in ExpandObject(result, !ExcludeTableInfo, this.TableName)) { collectedSoFar++; if (collectedSoFar >= First) { if (! (String.IsNullOrEmpty(nextRow) && String.IsNullOrEmpty(nextPart))) { PSNoteProperty nextRowKey = new PSNoteProperty("NextRowKey", nextRow); resultObj.Properties.Add(nextRowKey); PSNoteProperty nextPartition= new PSNoteProperty("NextPartition", nextPart); resultObj.Properties.Add(nextPartition); } WriteObject(resultObj); break; } else { WriteObject(resultObj); } } } else { WriteObject( ExpandObject(result, !ExcludeTableInfo, this.TableName), true); } } if (! (String.IsNullOrEmpty(nextRow) && String.IsNullOrEmpty(nextPart))) { thereIsMore = true; } else { thereIsMore = false; } } while (thereIsMore); } } } |