Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I use tuple in C# call to _EdgeDBclient.QuerySingleAsync() #75

Open
EncompassingResidential opened this issue Jan 16, 2024 · 3 comments

Comments

@EncompassingResidential
Copy link

EncompassingResidential commented Jan 16, 2024

Describe the bug

I submitted a question in Discord -> EdgeDb -> edgedb-dotnet on Mon, 1/15/24
but no one has responded as of 1/16/24 14:58 PAC.

I've tried multiple options for using a tuple in an INSERT statement, but I keep getting different warnings returned from EdgeDB.
For Visual Studio 2022 C# .NET 7 code
$ edgedb --version
EdgeDB CLI 4.0.2+b26c502

Reproduction
Include the code that is causing the error:

Here is the default.esdl

	type Artist {
		required                   artistname: str {
				constraint exclusive;
				constraint min_len_value(3);
								}
		                           othernames: array<str>;
		required              wikipediapageid: int32;
		                            birthdate: datetime;
		                           familyname: tuple<first: str, middle: str, last: str>;
		required multi                 genres: Genre;
		         multi                 labels: MusicCompanyLabel;
		required                    timestamp: datetime;
		}

Here is the C# code (below code is the multiple iterations I tried and the EdgeDB errors that were returned):

		string familyNameFirst = "";
		string familyNameMiddle = "";
		string familyNameLast = "";
		if (artist.FamilyName != null) {
			familyNameFirst  = string.Join(", ", artist.FamilyName.Item1);
			familyNameMiddle = string.Join(", ", artist.FamilyName.Item2);
			familyNameLast   = string.Join(", ", artist.FamilyName.Item3);
		}

            try
            {
                var result = await _EdgeDBclient.QuerySingleAsync<Artist>(
                    " INSERT Artist " +
                    " { artistname      := <str>$name, " + 
                    "   othernames      := <array<str>>$onam, " +
                    "   wikipediapageid := <int32>$wpid, " +
                    "   birthdate       := <datetime>$bdat, " +
                    "   familyname      := <tuple< first: <str>$fname, middle: <str>$mname, last: <str>$lname >>, " +
                    "   genres          := <array<str>>$genr, " +
                    "   labels          := <array<str>>$labl, " +
                    "   timestamp       := <datetime>$ptst } ",
                                        new
                                        {
                                            name = artist.ArtistName,
                                            onam = otherNamesString,
                                            wpid = artist.WikipediaPageID,
                                            bdat = artist.BirthDate,
                                            fname = familyNameFirst,
                                            mname = familyNameMiddle,
                                            lname = familyNameLast,
                                            genr = genreString,
                                            labl = labelString,
                                            ptst = artist.PageTimeStamp
                                        });
            }
            catch (EdgeDB.EdgeDBErrorException ex)
            {
                Console.WriteLine($"{DateTime.Now} BandServer InsertArtistAsync for {artist.ArtistName}, WikiPageID {artist.WikipediaPageID} error from EdgeDB: ( {ex.Message} )");
                return false;
            }

Here are the various versions I've tried and the error returned:

// "   familyname      := tuple{ first := <str>$fname, middle := <str>$mname, last := <str>$lname }, " +
//  object type or alias 'default::tuple' does not exist
//
// "   familyname      := { first := <str>$fname, middle := <str>$mname, last := <str>$lname }, " +
// invalid target for property 'familyname' of object type 'default::Artist': 'std::FreeObject'
//         (expecting 'tuple<first: std::str, middle: std::str, last: std::str>')
//
// "   familyname      := tuple<first: <str>$fname, middle: <str>$mname, last: <str>$lname>, " +
// Unexpected ':'
//
// "   familyname      := tuple<first <str>$fname, middle <str>$mname, last <str>$lname>, " +
// Missing '['
//
// "   familyname          := { first := <str>$fname, middle := <str>$mname, last := <str>$lname }, " +
// invalid target for property 'familyname' of object type 'default::Artist': 
// 'std::FreeObject' (expecting 'tuple<first: std::str, middle: std::str, last: std::str>')
//
// "   familyname          := { first := <str>$fname, middle := <str>$mname, last := <str>$lname }, " +
//
// "   familyname      := <tuple< first := $fname, middle := $mname, last := $lname >>, " +
// Unexpected ':='
//
// "   familyname      := <tuple< first := <str>$fname, middle := <str>$mname, last := <str>$lname >>, " +
// Unexpected ':='
//
//"   familyname      := <tuple< first : <str>$fname, middle : <str>$mname, last : <str>$lname >>, " +
// Missing keyword 'TYPE'

Expected behavior

Trying to not get and error and INSERT the C# tuple properly into the INSERT statement.

Versions (please complete the following information):

$ dotnet --version

8.0.100

Frameworks
MicrosoftAspNetCoreApp
MicrosoftNETCoreApp
Packages
EdgeDB.Net.Driver (1.3.0)
MicrosoftAspNetCore.OpenApi (7.0.10)
Swashbuckle.AspNetCore (6.5.0)
System.Net.Http.Json (8.0.0)

  • OS: Windows 11
  • EdgeDB version:
  • EdgeDB CLI version:
  • edgedb-net version:
  • .NET version:

Additional context

@raddevon
Copy link
Contributor

You could try this:

familyname := <tuple<first:str, middle:str, last:str>>$familyname

You might also consider breaking out familyname as a separate object type. Those can be easier to wrangle than tuples.

@quinchs
Copy link
Collaborator

quinchs commented Jan 17, 2024

Crossposting from Discord:

from just looking at the code you provided, I noted some immediate problems:

  • genres and labels are types within the schema, but in the code your casting them to <array<str>> which doesn't insert/select them
  • familyname in the code doesn't contain type casts for arguments, resulting in this error:
QueryError: missing a type cast before the parameter
   |
 1 |  INSERT Artist  { artistname      := <str>$name,    othernames      := <array<str>>$onam,    wikipediapageid := <int32>$wpid,    birthdate       := <datetime>$bdat,    familyname      := { first := $fname, middle := $mname, last := $lname },    genres          := <array<str>>$genr,    labels          := <array<str>>$labl,    timestamp       := <datetime>$ptst } 
   |                                                                                                                                                                                                       ^^^^^^

for this error:

Code: "   familyname          := { first := <str>$fname, middle := <str>$mname, last := <str>$lname }, " +
Error: invalid target for property 'familyname' of object type 'default::Artist': 
       'std::FreeObject' (expecting 'tuple<first: std::str, middle: std::str, last: std::str>')

Its telling you that you're trying to cast a free object to a tuple, the { x := y, ...} syntax is a free object in EdgeDB, to specify a tuple you can use (x, y, z, ...) syntax.
fixing these issues seems to work on my end

@EncompassingResidential
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants