Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

CQL generation tests are passing

  • Loading branch information...
commit 1d0ca56ff80924caaf413e166b85b8a185562455 1 parent cc32376
@nberardi nberardi authored
View
15 src/CassandraColumnFamily.cs
@@ -22,11 +22,12 @@ public CassandraColumnFamily(CassandraContext context, string columnFamily)
public partial class CassandraColumnFamily : BaseCassandraColumnFamily
{
private CassandraColumnFamilySchema _cachedSchema;
+ private ObjectSerializerConventions _conventions;
public CassandraColumnFamily(CassandraContext context, string columnFamily)
: base(context, columnFamily)
{
-
+ _conventions = new ObjectSerializerConventions();
}
public FluentColumnFamily CreateRecord(CassandraObject key)
@@ -37,7 +38,17 @@ public FluentColumnFamily CreateRecord(CassandraObject key)
return new FluentColumnFamily(key, FamilyName, GetSchema());
}
- public ObjectSerializerConventions ObjectConventions { get; set; }
+ public ObjectSerializerConventions ObjectConventions
+ {
+ get { return _conventions; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ _conventions = value;
+ }
+ }
public override CassandraColumnFamilySchema GetSchema()
{
View
1  src/FluentCassandra.csproj
@@ -151,6 +151,7 @@
<Compile Include="CassandraColumnFamilyOperations.cs" />
<Compile Include="IFluentRecordExpression.cs" />
<Compile Include="Linq\CqlObjectQuery.cs" />
+ <Compile Include="Linq\ICassandraColumnFamilyInfo.cs" />
<Compile Include="ObjectSerializer\IObjectSerializer.cs" />
<Compile Include="ObjectSerializer\ObjectSerializerConventions.cs" />
<Compile Include="Linq\CqlObjectQueryProvider.cs" />
View
4 src/Linq/CassandraColumnFamily+QueryProvider.cs
@@ -8,9 +8,9 @@
namespace FluentCassandra
{
- public partial class CassandraColumnFamily : IQueryable, IQueryable<ICqlRow>, IQueryProvider
+ public partial class CassandraColumnFamily : IQueryable, IQueryable<ICqlRow>, IQueryProvider, ICassandraColumnFamilyInfo
{
- public CqlObjectQueryProvider<T> QueryWithObject<T>()
+ public CqlObjectQueryProvider<T> AsObjectQueryable<T>()
{
return new CqlObjectQueryProvider<T>(this);
}
View
2  src/Linq/CqlObjectQuery.cs
@@ -114,7 +114,7 @@ public IQueryProvider Provider
/// <returns></returns>
public override string ToString()
{
- return CqlQueryEvaluator.GetCql(Expression);
+ return CqlQueryEvaluator.GetCql(Expression, _family.ObjectConventions);
}
}
}
View
13 src/Linq/CqlObjectQueryProvider.cs
@@ -6,7 +6,7 @@
namespace FluentCassandra.Linq
{
- public class CqlObjectQueryProvider<T> : IQueryable, IQueryable<T>, IQueryProvider
+ public class CqlObjectQueryProvider<T> : IQueryable, IQueryable<T>, IQueryProvider, ICassandraColumnFamilyInfo
{
private readonly CassandraColumnFamily _family;
@@ -15,6 +15,11 @@ public CqlObjectQueryProvider(CassandraColumnFamily family)
_family = family;
}
+ public string FamilyName
+ {
+ get { return _family.FamilyName; }
+ }
+
public CqlObjectQuery<T> ToQuery()
{
var queryable = (IQueryable)this;
@@ -104,7 +109,11 @@ public IQueryable CreateQuery(Expression expression)
public TResult Execute<TResult>(Expression expression)
{
- throw new NotImplementedException();
+ if (expression.NodeType == ExpressionType.Call)
+ expression = ((MethodCallExpression)expression).Arguments[0];
+
+ var result = new CqlObjectQuery<TResult>(expression, this, _family);
+ return Enumerable.FirstOrDefault(result);
}
public object Execute(Expression expression)
View
93 src/Linq/CqlQueryEvaluator.cs
@@ -4,6 +4,7 @@
using System.Linq;
using System.Linq.Expressions;
using FluentCassandra.Types;
+using FluentCassandra.ObjectSerializer;
namespace FluentCassandra.Linq
{
@@ -12,10 +13,13 @@ namespace FluentCassandra.Linq
internal class CqlQueryEvaluator
{
private string _columnFamily;
+ private readonly ObjectSerializerConventions _conventions;
- internal CqlQueryEvaluator()
+ internal CqlQueryEvaluator(ObjectSerializerConventions conventions = null)
{
FieldsArray = new List<string>();
+
+ _conventions = conventions;
}
public string Query
@@ -70,7 +74,7 @@ private string Fields
private string WhereCriteria { get; set; }
- private void AddTable(CassandraColumnFamily provider)
+ private void AddTable(ICassandraColumnFamilyInfo provider)
{
_columnFamily = provider.FamilyName;
}
@@ -93,7 +97,7 @@ private void AddCriteria(Expression exp)
#region Expression Helpers
- private static Expression SimplifyExpression(Expression exp)
+ private Expression SimplifyExpression(Expression exp)
{
switch (exp.NodeType)
{
@@ -109,7 +113,7 @@ private static Expression SimplifyExpression(Expression exp)
}
}
- private static string GetPropertyName(Expression exp)
+ private string GetPropertyName(Expression exp)
{
exp = SimplifyExpression(exp);
@@ -118,7 +122,17 @@ private static string GetPropertyName(Expression exp)
if (exp.NodeType == ExpressionType.MemberAccess)
{
- var name = ((MemberExpression)exp).Member.Name;
+ var memExp = (MemberExpression)exp;
+ var name = memExp.Member.Name;
+
+ // if object queries
+ if (memExp.Expression.Type != typeof(ICqlRow))
+ {
+ if (_conventions.KeyPropertyNames.Contains(name, _conventions.AreKeyPropertyNamesCaseSensitive ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal))
+ name = "KEY";
+
+ return name;
+ }
if (name != "Key")
throw new NotSupportedException(name + " is not a supported property.");
@@ -138,18 +152,12 @@ private static string GetPropertyName(Expression exp)
#region Expression Parsing
- public static string GetCql(Expression expression)
+ public static string GetCql(Expression expression, ObjectSerializerConventions conventions = null)
{
- var eval = GetEvaluator(expression);
- return eval.Query;
- }
-
- private static CqlQueryEvaluator GetEvaluator(Expression expression)
- {
- var eval = new CqlQueryEvaluator();
+ var eval = new CqlQueryEvaluator(conventions);
eval.Evaluate(expression);
- return eval;
+ return eval.Query;
}
private void Evaluate(Expression exp, Action<string> call = null)
@@ -164,43 +172,25 @@ private void Evaluate(Expression exp, Action<string> call = null)
VisitMethodCall((MethodCallExpression)exp);
break;
- case ExpressionType.New:
- VisitNew((NewExpression)exp, call);
- break;
-
case ExpressionType.MemberInit:
VisitMemberInit((MemberInitExpression)exp, call);
break;
- case ExpressionType.MemberAccess:
- VisitMemberAccess((MemberExpression)exp, call);
- break;
-
case ExpressionType.Constant:
- AddTable(((ConstantExpression)exp).Value as CassandraColumnFamily);
+ var obj = ((ConstantExpression)exp).Value;
+ var family = obj as ICassandraColumnFamilyInfo;
+
+ AddTable(family);
break;
}
}
- private void VisitMemberAccess(MemberExpression exp, Action<string> call)
- {
- call(GetPropertyName(exp));
- }
-
private void VisitMemberInit(MemberInitExpression exp, Action<string> call)
{
foreach (MemberAssignment member in exp.Bindings)
call(GetPropertyName(member.Expression));
}
- private void VisitNew(NewExpression exp, Action<string> call)
- {
- foreach (var arg in exp.Arguments)
- call(GetPropertyName(arg));
-
- VisitMemberInit(Expression.MemberInit(exp, new MemberBinding[0]), call);
- }
-
private void VisitMethodCall(MethodCallExpression exp)
{
Evaluate(exp.Arguments[0]);
@@ -218,9 +208,7 @@ private void VisitMethodCall(MethodCallExpression exp)
private void SetLimit(Expression exp)
{
if (exp.NodeType == ExpressionType.Constant)
- {
LimitCount = (int)((ConstantExpression)exp).Value;
- }
}
private IEnumerable<CassandraObject> VisitSelectExpression(Expression exp)
@@ -233,11 +221,39 @@ private IEnumerable<CassandraObject> VisitSelectExpression(Expression exp)
case ExpressionType.Constant:
return VisitSelectColumnExpression((ConstantExpression)exp);
+ case ExpressionType.MemberAccess:
+ var list = new List<CassandraObject>();
+ VisitSelectMemberAccess((MemberExpression)exp, x => {
+ list.Add(x);
+ });
+ return list;
+
+ case ExpressionType.New:
+ return VisitSelectNew((NewExpression)exp);
+
default:
throw new NotSupportedException(exp.NodeType.ToString() + " is not supported.");
}
}
+ private IEnumerable<CassandraObject> VisitSelectNew(NewExpression exp)
+ {
+ var list = new List<CassandraObject>();
+
+ foreach (var arg in exp.Arguments)
+ VisitSelectMemberAccess((MemberExpression)arg, x => {
+ list.Add(x);
+ });
+
+ return list;
+ }
+
+ private void VisitSelectMemberAccess(MemberExpression exp, Action<string> call)
+ {
+ var name = exp.Member.Name;
+ call(name);
+ }
+
private IEnumerable<CassandraObject> VisitSelectColumnExpression(ConstantExpression exp)
{
return (IEnumerable<CassandraObject>)exp.Value;
@@ -381,6 +397,7 @@ private string VisitWhereConditionalExpression(BinaryExpression exp)
return criteria;
}
+
#endregion
}
}
View
10 src/Linq/ICassandraColumnFamilyInfo.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Linq;
+
+namespace FluentCassandra.Linq
+{
+ public interface ICassandraColumnFamilyInfo
+ {
+ string FamilyName { get; }
+ }
+}
View
6 test/FluentCassandra.Tests/FluentCassandra.Tests.csproj
@@ -59,8 +59,10 @@
<Compile Include="Connections\ConnectionProviderTests.cs" />
<Compile Include="Connections\NormalConnectionProviderTests.cs" />
<Compile Include="Helper.cs" />
- <Compile Include="Linq\LinqTests.cs" />
- <Compile Include="Linq\LinqToCassandraTests.cs" />
+ <Compile Include="Linq\LinqToCqlObjectsCassandraTests.cs" />
+ <Compile Include="Linq\LinqToCqlObjectsTests.cs" />
+ <Compile Include="Linq\LinqToCqlTests.cs" />
+ <Compile Include="Linq\LinqToCqlCassandraTests.cs" />
<Compile Include="Operations\CassandraIndexClauseTest.cs" />
<Compile Include="Operations\CqlTest.cs" />
<Compile Include="ReportedIssuesTests.cs" />
View
3  ...luentCassandra.Tests/Linq/LinqToCassandraTests.cs → ...ntCassandra.Tests/Linq/LinqToCqlCassandraTests.cs
@@ -1,12 +1,11 @@
using System;
using System.Linq;
-using FluentCassandra.Types;
using NUnit.Framework;
namespace FluentCassandra.Linq
{
[TestFixture]
- public class LinqToCassandraTests
+ public class LinqToCqlCassandraTests
{
private CassandraContext _db;
private CassandraColumnFamily _family;
View
142 test/FluentCassandra.Tests/Linq/LinqToCqlObjectsCassandraTests.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Linq;
+using NUnit.Framework;
+
+namespace FluentCassandra.Linq
+{
+ [TestFixture]
+ public class LinqToCqlObjectsCassandraTests
+ {
+ private CassandraContext _db;
+ private CassandraColumnFamily _family;
+ private CassandraDatabaseSetup.User[] _users;
+
+ public class User
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Email { get; set; }
+ public int Age { get; set; }
+ }
+
+ [TestFixtureSetUp]
+ public void TestInit()
+ {
+ var setup = new CassandraDatabaseSetup();
+ _db = setup.DB;
+ _family = setup.UserFamily;
+ _users = setup.Users;
+ }
+
+ [Test]
+ public void SELECT()
+ {
+ var query =
+ from f in _family.AsObjectQueryable<User>()
+ select f;
+ var actual = query.ToList().OrderBy(x => x.Id).ToList();
+
+ Assert.AreEqual(_users.Length, actual.Count);
+ for (int i = 0; i < _users.Length; i++)
+ {
+ var objUser = _users[i];
+ var dbUser = actual[i];
+
+ Assert.AreEqual(objUser.Id, dbUser.Id);
+ Assert.AreEqual(objUser.Name, dbUser.Name);
+ Assert.AreEqual(objUser.Email, dbUser.Email);
+ Assert.AreEqual(objUser.Age, dbUser.Age);
+ }
+ }
+
+ [Test]
+ public void SELECT_One_Column()
+ {
+ var query = _family.AsObjectQueryable<User>().Select(x => x.Age);
+ var actual = query.ToList();
+
+ Assert.AreEqual(_users.Length, actual.Count);
+ for (int i = 0; i < _users.Length; i++)
+ {
+ var objUser = _users[i];
+ var dbAge = actual[i];
+
+ Assert.AreEqual(objUser.Age, dbAge);
+ }
+ }
+
+ [Test]
+ public void SELECT_Two_Columns()
+ {
+ var query = _family.AsObjectQueryable<User>().Select(x => new { x.Age, x.Name });
+ var actual = query.ToList();
+
+ Assert.AreEqual(_users.Length, actual.Count);
+ for (int i = 0; i < _users.Length; i++)
+ {
+ var objUser = _users[i];
+ var dbUser = actual[i];
+
+ Assert.AreEqual(objUser.Age, dbUser.Age);
+ Assert.AreEqual(objUser.Name, dbUser.Name);
+ }
+ }
+
+ [Test]
+ public void WHERE_Using_KEY()
+ {
+ var expected = _users.Where(x => x.Id == 2).FirstOrDefault();
+
+ var query =
+ from f in _family.AsObjectQueryable<User>()
+ where f.Id == 2
+ select f;
+ var response = query.ToList();
+ dynamic actual = response.FirstOrDefault();
+
+ Assert.AreEqual(1, response.Count);
+ Assert.AreEqual(expected.Id, actual.Key);
+ Assert.AreEqual(expected.Name, (string)actual.Name);
+ Assert.AreEqual(expected.Email, (string)actual.Email);
+ Assert.AreEqual(expected.Age, (int)actual.Age);
+ }
+
+ [Test]
+ public void WHERE_Using_KEY_And_One_Parameter()
+ {
+ var expected = _users.Where(x => x.Id == 2).FirstOrDefault();
+
+ var query =
+ from f in _family.AsObjectQueryable<User>()
+ where f.Id == 2 && f.Age == 23
+ select f;
+ var response = query.ToList();
+ dynamic actual = response.FirstOrDefault();
+
+ Assert.AreEqual(1, response.Count);
+ Assert.AreEqual(expected.Id, actual.Key);
+ Assert.AreEqual(expected.Name, (string)actual.Name);
+ Assert.AreEqual(expected.Email, (string)actual.Email);
+ Assert.AreEqual(expected.Age, (int)actual.Age);
+ }
+
+ [Test]
+ public void WHERE_One_Parameter()
+ {
+ var expected = _users.Where(x => x.Id == 2).FirstOrDefault();
+
+ var query =
+ from f in _family.AsObjectQueryable<User>()
+ where f.Age == 23
+ select f;
+ var response = query.ToList();
+ dynamic actual = response.FirstOrDefault();
+
+ Assert.AreEqual(1, response.Count);
+ Assert.AreEqual(expected.Id, actual.Key);
+ Assert.AreEqual(expected.Name, (string)actual.Name);
+ Assert.AreEqual(expected.Email, (string)actual.Email);
+ Assert.AreEqual(expected.Age, (int)actual.Age);
+ }
+ }
+}
View
147 test/FluentCassandra.Tests/Linq/LinqToCqlObjectsTests.cs
@@ -0,0 +1,147 @@
+using System.Linq;
+using FluentCassandra.Connections;
+using NUnit.Framework;
+using FluentCassandra.Types;
+using System;
+
+namespace FluentCassandra.Linq
+{
+ [TestFixture]
+ public class LinqToCqlObjectsTests
+ {
+ private CassandraContext _db;
+ private CassandraColumnFamily<AsciiType> _family;
+
+ public class User
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Email { get; set; }
+ public int Age { get; set; }
+ }
+
+ [TestFixtureSetUp]
+ public void TestInit()
+ {
+ var keyspaceName = "Testing";
+ var server = new Server("localhost");
+
+ _db = new CassandraContext(keyspace: keyspaceName, server: server);
+ _family = _db.GetColumnFamily<AsciiType>("Users");
+ }
+
+ private string ScrubLineBreaks(string query)
+ {
+ return query.Replace("\n", "");
+ }
+
+ private void AreEqual(string expected, string actual)
+ {
+ Assert.AreEqual(ScrubLineBreaks(expected), ScrubLineBreaks(actual));
+ }
+
+ [Test]
+ public void Provider()
+ {
+ var expected = "SELECT * FROM Users";
+
+ var query = _family.AsObjectQueryable<User>().ToQuery();
+ var actual = query.ToString();
+
+ AreEqual(expected, actual);
+ }
+
+ [Test]
+ public void SELECT()
+ {
+ var expected = "SELECT * FROM Users";
+
+ var query =
+ from f in _family.AsObjectQueryable<User>()
+ select f;
+
+ var actual = query.ToString();
+
+ AreEqual(expected, actual);
+ }
+
+ [Test]
+ public void LIMIT()
+ {
+ var expected = "SELECT * FROM Users LIMIT 25";
+
+ var query = (
+ from f in _family.AsObjectQueryable<User>()
+ select f).Take(25);
+
+ var actual = query.ToString();
+
+ AreEqual(expected, actual);
+ }
+
+ [Test]
+ public void SELECT_One_Column()
+ {
+ var expected = "SELECT Age FROM Users";
+
+ var query = _family.AsObjectQueryable<User>().Select(x => x.Age);
+ var actual = query.ToString();
+
+ AreEqual(expected, actual);
+ }
+
+ [Test]
+ public void SELECT_Two_Columns()
+ {
+ var expected = "SELECT Age, Name FROM Users";
+
+ var query = _family.AsObjectQueryable<User>().Select(x => new { x.Age, x.Name });
+ var actual = query.ToString();
+
+ AreEqual(expected, actual);
+ }
+
+ [Test]
+ public void WHERE_Using_KEY()
+ {
+ var expected = "SELECT * FROM Users WHERE KEY = 1234";
+
+ var query =
+ from f in _family.AsObjectQueryable<User>()
+ where f.Id == 1234
+ select f;
+
+ var actual = query.ToString();
+
+ AreEqual(expected, actual);
+ }
+
+ [Test]
+ public void WHERE_Using_KEY_And_One_Parameter()
+ {
+ var expected = "SELECT * FROM Users WHERE KEY = 1234 AND Age = 10";
+
+ var query =
+ from f in _family.AsObjectQueryable<User>()
+ where f.Id == 1234 && f.Age == 10
+ select f;
+
+ var actual = query.ToString();
+
+ AreEqual(expected, actual);
+ }
+
+ [Test]
+ public void WHERE_Two_OR_Parameter()
+ {
+ Assert.Throws<NotSupportedException>(delegate {
+ var query =
+ from f in _family.AsObjectQueryable<User>()
+ where f.Id == 1234 || f.Age == 10
+ select f;
+
+ query.ToString();
+ }, "OR is not supported");
+ }
+ }
+}
View
2  test/FluentCassandra.Tests/Linq/LinqTests.cs → test/FluentCassandra.Tests/Linq/LinqToCqlTests.cs
@@ -7,7 +7,7 @@
namespace FluentCassandra.Linq
{
[TestFixture]
- public class LinqTests
+ public class LinqToCqlTests
{
private CassandraContext _db;
private CassandraColumnFamily<AsciiType> _family;
Please sign in to comment.
Something went wrong with that request. Please try again.