Lesson Description

The "Movie Repository" Lesson is part of the full, Build a Fullstack App with Vanilla JS and Go course featured in this preview video. Here's what you'd learn in this lesson:

Maximiliano demonstrates how to import the Postgres database driver and explains that it is necessary to connect to the database. He demonstrates creating the movie repository, including how it creates a new instance of the repository, implements the interface methods, and handles SQL queries.

Preview
Close

Transcript from the "Movie Repository" Lesson

[00:00:00]
>> Maximiliano Firtman: So remember that we have error here. So every time we make we save, it's actually trying to execute this, which is a problem when our code is not yet ready. So for example, right now we have an error here, it says, fail to connect your database, SQL, unknown driver, postgres.

[00:00:20]
What's going on here? It's difficult to see initially, okay? What's going on, by the way, does anyone know what's going on? Case you have experience with go or with databases in go? No, the problem is that we are missing an import, but VS code is not really complaining about that.

[00:00:42]
So, remember that we do have an external library for accessing the database, in this case Postgres. But the thing is that we are not importing it and how to import that, well, actually, if we go to go.mod, this is the name of the library. So, I could come here and import the library, but if I do that, is it complaining because it said, but you are not using anything from that library, okay?

[00:01:13]
What's the problem? The problem is that we need to load, this driver is a driver for the database library that we have in go. So it's a driver, okay? So we have different drivers for different databases. So something that we can do is to add an underscore there, which actually will solve the problem, okay?

[00:01:40]
This initially, and now I'm not getting any error, and now it says serving the files. So actually it was saying, here forgot an import, but this is an import that you won't get automatically or VS code will never tell you. It's kind of fun, hidden import, that import will load that library, so then the database, when we are trying to open the database, remember we do have here database.open.

[00:02:09]
>> Maximiliano Firtman: When we are trying here, sql.open, that's SQL library is trying to find any provider, any driver, that can work with that kind of database. In this case, we don't have Postgres support directly from go, so, we need an external library that will add that driver to SQL, okay?

[00:02:38]
So it seems like now it's kind of working, okay? Does it make sense? At least we don't get that error anymore, the next step is to actually create the movie repository, the movie repository is the one that will actually comply with that interface. Remember that we didn't have an interface, we want to actually match that interface so we can get top movies, random movies, movies by ID and so on.

[00:03:09]
So we're going to create a new file within data, we can call it movie repository, repository.go, and this one will make all the queries to the database. I already have that one, ready, because it's a lot of work, lots of queries, so we can go and find this is A, B5, we have that code, and then we can analyze the code.

[00:03:42]
>> Maximiliano Firtman: This is movie repository, okay? So let's try to analyze the code here. Well, first is creating a value and a structure, movie repository, remember, this is kind of a class we are emulating a class in go. So, it's creating a movie repositor, okay? The movie repository will need a logger and then database, what's a logger?

[00:04:05]
Something we create, remember, that's a logger that we created before. So in this case, we are receiving both, the database connection that right now is on main and also the logger that is also main, okay? This is a factory, remember this is a design pattern to construct, in this case, instances of that structure.

[00:04:28]
So we create a new movie repository that receives the database and the logger, and internally it's just setting a new instance there, and it's returning a movie repository. So this is the pattern, this is always the same, so this is how you create objects with a factory pattern in go, why I'm creating a factory?

[00:04:52]
Because maybe, not for our particular case, but maybe you wanna create more than one in. Instance, more than one connection to the database. For some reason, sometimes you need to connect to two different database on two different providers or to the same database. But for some reason, you need two or three connections.

[00:05:11]
So that's why you can create more than one it's not a singleton, you could create a singleton if you want, but in this case it's not and then we have get the get movie, we will get one by one, get movies, okay? And get the movies, we have a get the movies and get movies, okay?

[00:05:33]
Are we following in the interface completely? Not yet. So we have, let's look at get movies, get movies will receive a query, okay? As a string SQL query, SQL query, and where returns and a slice of movie, so it collection of movie or error. Remember, this is the pattern, and this is talking to the database, making the query, if there is any error, it will send the error to the logger.

[00:06:07]
That's our object, the object we created, and also it's returning the error, okay? And then we are closing, the rows is actually the cursor over the rows, this is cursor base, okay? And then we're actually creating a slice of movies. Now, this is the our model, and through, we are using the cursor to loop through all the records coming from the database.

[00:06:38]
And what we are doing is creating a movie based on each field that we are getting from the database. The database is giving us a JSON-like object and we are using our model to map the data there, okay? Does it make sense? That's called a scan. So with a scan, we are getting all the fields, all the values of the field for the current row, and with that, okay?

[00:07:11]
We create a movie, so that's why we are appending M into our slices of movies, okay? Does it make sense? And the ampersand that we are sending here is like, hey, you know what the ID? You should put the ID here in m.id you should put the value of the title of the movie.

[00:07:34]
You should put the title inside the title of this movie and create thing here, it's like, I create an empty movie, and then I'm setting the placeholder. I put it here, put it here, put it here, put here, that's roughly how that works. There are other ways to do that, the simpler way, but this is just to understand what's going on, and I'm returning movies.

[00:07:54]
And now we have get top movies, okay? That is making a query, it's selecting all these fields from movies ordered by popularity descendant. We can change that, of course, and I'm doing a limit, okay? So later, we will talk about if you're going to make different pages or pagination here, but this is a query, and we are limiting by 20, we can change that constant later.

[00:08:25]
So for example, we can have another function, forget the random movies, in this case, it's a similar query, but instead of ordering our popularity you order by random. That is actually a Postgres function and that will give you 20 random movies. Okay, does it make sense? And to actually follow or implement the interface, there are more functions that we need to implement or for now, we can go here and say, well, let's comment this for a while, so we can fill those later, okay?

[00:09:11]
So we can go step by step, at least those two are already there. Quick question for you, how can I go to my movie repository or how can I implement the interface, how can I say that I'm implementing the interface movie storage? And this tricky question.
>> Student 1: Has the same methods on it?

[00:09:40]
>> Maximiliano Firtman: Exactly. So the quick answer is that there is no way to say so, go will automatically assign an interface type if you have the methods. So any type with get top movies and get random movies following this pattern. So returning those values, we'll automatically implement this interface, and then we can use this interface as a type somewhere else.

[00:10:12]
Remember, this is an abstraction layer, so later, we can have different implementations, right now we have this one, but later we can create another one. Okay, does it make sense? Do you have any questions on big queries or what we are doing here. The positional parameter in there, it's fixed to 20, but where are you passing that?

[00:10:36]
Where?
>> Student 2: The dollar sign one, right? That's a positional parameter?
>> Maximiliano Firtman: This one, yeah, so let's review that. So one of the things that we need to be careful when we are making queries is SQL injection, mostly with SQL-based framework. So, let's think about this. So if instead of using dollar sign one, I will explain that in a second, I close this string and then concatenate this with the parameter that we receive like that.

[00:11:14]
The problem is that if someone is injecting a value here, it can write it's own query for example, I could, I mean, if the user is sending you that value, it can be something like this.
>> Maximiliano Firtman: Delete.
>> Maximiliano Firtman: For example. So what is this doing? This is adding, actually, to make that word, I should do something like this, I'm a hacker now, so this is SQL injection, so what will happen is that, this string is going to be replaced there, okay?

[00:12:02]
Let's do that, if I put this here,
>> Maximiliano Firtman: This is the final query that will actually be executed, actually the forward lash n is a new line, so it will be like this. Actually, yeah, was missing, I'm not, I need a semicolon, I don't need a comment, I need a semicolon.

[00:12:25]
So, actually, this is now the query that I'm executing, so, it's making a select and after that is deleting the table. So, if I leave that open, okay? Of course, the hacker, I mean the bad actor, will take some time to try to understand my structure, okay? So to solve the problem and avoid, okay?

[00:12:50]
This then we, instead of concatenating when we're talking about values, we use that are the kind of arguments. In this case, the SQL library from go will replace that safely. Safely means that if this is a string, right now, I'm not passing a string, I'm passing default limit, okay?

[00:13:14]
Default limit is actually a number, but if it's a string, so if I pass in like, again, as before, semicolon, drop table, it will just replace it here, but as a string, so like this, safely, in quotes. So it will never be actually, a SQL command, it will treat it as a value always, okay?

[00:13:40]
So from a security point of view, that's why every time you're making a query and that query has values inside, you have to use arguments, and the arguments are with dollar sign and a number. You can have more than one, for example, Now I could say limit one offset, that is offset means, instead of starting from the first one, I want you to start from the other one.

[00:14:07]
So I say, draw sign two, and then I can pass another argument here, so let me remove this so this was default limit, and they will say 10. So now it will start from the 11th, no, the 10th record actually, okay, so you can add as many arguments as you want.

[00:14:30]
That typically works with most of the SQL-based libraries, okay?
>> Student 1: Okay, make sense?
>> Student 3: I wonder if go they have lazy loading.
>> Maximiliano Firtman: What do you want a lazy load?
>> Student 3: It means the structure right there, but you're not going to get a day until you actually.
>> Maximiliano Firtman: Well, actually, this is actually lazy load because what we receive is not like a collection of rows, it's called rows, but it's actually a cursor.

[00:15:07]
So you actually need to move to the next row to actually grab the data, So if that's what you meant by lazy load, I think this is lazy load from your definition of lazy loading. Okay, so when you do a query, what you receive is not the data, you receive a pointer to the beginning of the result, but the data is still in the SQL Server.

[00:15:32]
So then you move the cursor, and you're bringing row by row.
>> Maximiliano Firtman: Okay, that makes sense? That's how this library works. Of course, you can use other libraries or other mechanisms to bring data. Okay, make sense? Any other question for now? No, well, now we need to finally try to use this, so I need to go to main.go and after we are initializing the database, I need to initialize the repository, okay?

[00:16:14]
So we're going to initialize our data repository for movies. So let's call this movie repo repository, and we will call our new movie repository function that we have, and we need to pass a database that we already have, and the log instance. And if there is any error, I should log that saying that failed to initialize repository.

[00:16:57]
Now it's complaining because we are not using it yet, which is okay.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now